From d1d274cd1ce2eb979c66233a36a7a92abfc0f18f Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 21 Nov 2011 17:31:02 -0600 Subject: eCryptfs: Prevent file create race condition commit b59db43ad4434519feb338eacb01d77eb50825c5 upstream. The file creation path prematurely called d_instantiate() and unlock_new_inode() before the eCryptfs inode info was fully allocated and initialized and before the eCryptfs metadata was written to the lower file. This could result in race conditions in subsequent file and inode operations leading to unexpected error conditions or a null pointer dereference while attempting to use the unallocated memory. https://launchpad.net/bugs/813146 Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/crypto.c | 22 +++++++++--------- fs/ecryptfs/ecryptfs_kernel.h | 5 +++-- fs/ecryptfs/inode.c | 52 ++++++++++++++++++++++++++----------------- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 58609bde3b9..203a1fdff66 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -967,7 +967,7 @@ static void ecryptfs_set_default_crypt_stat_vals( /** * ecryptfs_new_file_context - * @ecryptfs_dentry: The eCryptfs dentry + * @ecryptfs_inode: The eCryptfs inode * * If the crypto context for the file has not yet been established, * this is where we do that. Establishing a new crypto context @@ -984,13 +984,13 @@ static void ecryptfs_set_default_crypt_stat_vals( * * Returns zero on success; non-zero otherwise */ -int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) +int ecryptfs_new_file_context(struct inode *ecryptfs_inode) { struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; + &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private( - ecryptfs_dentry->d_sb)->mount_crypt_stat; + ecryptfs_inode->i_sb)->mount_crypt_stat; int cipher_name_len; int rc = 0; @@ -1299,12 +1299,12 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t max, } static int -ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry, +ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode, char *virt, size_t virt_len) { int rc; - rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt, + rc = ecryptfs_write_lower(ecryptfs_inode, virt, 0, virt_len); if (rc < 0) printk(KERN_ERR "%s: Error attempting to write header " @@ -1338,7 +1338,8 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask, /** * ecryptfs_write_metadata - * @ecryptfs_dentry: The eCryptfs dentry + * @ecryptfs_dentry: The eCryptfs dentry, which should be negative + * @ecryptfs_inode: The newly created eCryptfs inode * * Write the file headers out. This will likely involve a userspace * callout, in which the session key is encrypted with one or more @@ -1348,10 +1349,11 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask, * * Returns zero on success; non-zero on error */ -int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) +int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode) { struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; + &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; unsigned int order; char *virt; size_t virt_len; @@ -1391,7 +1393,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt, size); else - rc = ecryptfs_write_metadata_to_contents(ecryptfs_dentry, virt, + rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt, virt_len); if (rc) { printk(KERN_ERR "%s: Error writing metadata out to lower file; " diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index b36c5572b3f..9ce1e92c7d9 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -584,9 +584,10 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode); int ecryptfs_encrypt_page(struct page *page); int ecryptfs_decrypt_page(struct page *page); -int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry); +int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode); int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry); -int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry); +int ecryptfs_new_file_context(struct inode *ecryptfs_inode); void ecryptfs_write_crypt_stat_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat, size_t *written); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 11f8582d721..528da01fec2 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -172,22 +172,23 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode, * it. It will also update the eCryptfs directory inode to mimic the * stat of the lower directory inode. * - * Returns zero on success; non-zero on error condition + * Returns the new eCryptfs inode on success; an ERR_PTR on error condition */ -static int +static struct inode * ecryptfs_do_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, int mode) { int rc; struct dentry *lower_dentry; struct dentry *lower_dir_dentry; + struct inode *inode; lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); lower_dir_dentry = lock_parent(lower_dentry); if (IS_ERR(lower_dir_dentry)) { ecryptfs_printk(KERN_ERR, "Error locking directory of " "dentry\n"); - rc = PTR_ERR(lower_dir_dentry); + inode = ERR_CAST(lower_dir_dentry); goto out; } rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode, @@ -195,20 +196,19 @@ ecryptfs_do_create(struct inode *directory_inode, if (rc) { printk(KERN_ERR "%s: Failure to create dentry in lower fs; " "rc = [%d]\n", __func__, rc); + inode = ERR_PTR(rc); goto out_lock; } - rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry, - directory_inode->i_sb); - if (rc) { - ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n"); + inode = __ecryptfs_get_inode(lower_dentry->d_inode, + directory_inode->i_sb); + if (IS_ERR(inode)) goto out_lock; - } fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); out_lock: unlock_dir(lower_dir_dentry); out: - return rc; + return inode; } /** @@ -219,26 +219,26 @@ out: * * Returns zero on success */ -static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) +static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode) { struct ecryptfs_crypt_stat *crypt_stat = - &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; + &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; int rc = 0; - if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { + if (S_ISDIR(ecryptfs_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); goto out; } ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); - rc = ecryptfs_new_file_context(ecryptfs_dentry); + rc = ecryptfs_new_file_context(ecryptfs_inode); if (rc) { ecryptfs_printk(KERN_ERR, "Error creating new file " "context; rc = [%d]\n", rc); goto out; } - rc = ecryptfs_get_lower_file(ecryptfs_dentry, - ecryptfs_dentry->d_inode); + rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " "the lower file for the dentry with name " @@ -246,10 +246,10 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) ecryptfs_dentry->d_name.name, rc); goto out; } - rc = ecryptfs_write_metadata(ecryptfs_dentry); + rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode); if (rc) printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); - ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); + ecryptfs_put_lower_file(ecryptfs_inode); out: return rc; } @@ -269,18 +269,28 @@ static int ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, int mode, struct nameidata *nd) { + struct inode *ecryptfs_inode; int rc; - /* ecryptfs_do_create() calls ecryptfs_interpose() */ - rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode); - if (unlikely(rc)) { + ecryptfs_inode = ecryptfs_do_create(directory_inode, ecryptfs_dentry, + mode); + if (unlikely(IS_ERR(ecryptfs_inode))) { ecryptfs_printk(KERN_WARNING, "Failed to create file in" "lower filesystem\n"); + rc = PTR_ERR(ecryptfs_inode); goto out; } /* At this point, a file exists on "disk"; we need to make sure * that this on disk file is prepared to be an ecryptfs file */ - rc = ecryptfs_initialize_file(ecryptfs_dentry); + rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode); + if (rc) { + drop_nlink(ecryptfs_inode); + unlock_new_inode(ecryptfs_inode); + iput(ecryptfs_inode); + goto out; + } + d_instantiate(ecryptfs_dentry, ecryptfs_inode); + unlock_new_inode(ecryptfs_inode); out: return rc; } -- cgit v1.2.3 From 19c8acbc4a4d444d72d256a7541b040cebddc78b Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 21 Nov 2011 17:31:29 -0600 Subject: eCryptfs: Flush file in vma close commit 32001d6fe9ac6b0423e674a3093aa56740849f3b upstream. Dirty pages weren't being written back when an mmap'ed eCryptfs file was closed before the mapping was unmapped. Since f_ops->flush() is not called by the munmap() path, the lower file was simply being released. This patch flushes the eCryptfs file in the vm_ops->close() path. https://launchpad.net/bugs/870326 Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/file.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index c6ac98cf9ba..d3f95f941c4 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -139,6 +139,27 @@ out: return rc; } +static void ecryptfs_vma_close(struct vm_area_struct *vma) +{ + filemap_write_and_wait(vma->vm_file->f_mapping); +} + +static const struct vm_operations_struct ecryptfs_file_vm_ops = { + .close = ecryptfs_vma_close, + .fault = filemap_fault, +}; + +static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + int rc; + + rc = generic_file_mmap(file, vma); + if (!rc) + vma->vm_ops = &ecryptfs_file_vm_ops; + + return rc; +} + struct kmem_cache *ecryptfs_file_info_cache; /** @@ -349,7 +370,7 @@ const struct file_operations ecryptfs_main_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = ecryptfs_compat_ioctl, #endif - .mmap = generic_file_mmap, + .mmap = ecryptfs_file_mmap, .open = ecryptfs_open, .flush = ecryptfs_flush, .release = ecryptfs_release, -- cgit v1.2.3 From a638f9564fd11b37efee4e78d7ef9dc52eb2a7cd Mon Sep 17 00:00:00 2001 From: "Jeffrey (Sheng-Hui) Chu" Date: Wed, 23 Nov 2011 11:33:07 +0100 Subject: i2c-algo-bit: Generate correct i2c address sequence for 10-bit target commit cc6bcf7d2ec2234e7b41770185e4dc826390185e upstream. The wrong bits were put on the wire, fix that. This fixes kernel bug #42562. Signed-off-by: Sheng-Hui J. Chu Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/algos/i2c-algo-bit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index d6d58684712..eca3bcc4599 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -486,7 +486,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) if (flags & I2C_M_TEN) { /* a ten bit address */ - addr = 0xf0 | ((msg->addr >> 7) & 0x03); + addr = 0xf0 | ((msg->addr >> 7) & 0x06); bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr); /* try extended address code...*/ ret = try_address(i2c_adap, addr, retries); @@ -496,7 +496,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) return -EREMOTEIO; } /* the remaining 8 bit address */ - ret = i2c_outb(i2c_adap, msg->addr & 0x7f); + ret = i2c_outb(i2c_adap, msg->addr & 0xff); if ((ret != 1) && !nak_ok) { /* the chip did not ack / xmission error occurred */ dev_err(&i2c_adap->dev, "died at 2nd address code\n"); -- cgit v1.2.3 From 722daca8514aacaf7ed1311f2cc8e518af675049 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 23 Nov 2011 11:31:24 -0600 Subject: eCryptfs: Extend array bounds for all filename chars commit 0f751e641a71157aa584c2a2e22fda52b52b8a56 upstream. From mhalcrow's original commit message: Characters with ASCII values greater than the size of filename_rev_map[] are valid filename characters. ecryptfs_decode_from_filename() will access kernel memory beyond that array, and ecryptfs_parse_tag_70_packet() will then decrypt those characters. The attacker, using the FNEK of the crafted file, can then re-encrypt the characters to reveal the kernel memory past the end of the filename_rev_map[] array. I expect low security impact since this array is statically allocated in the text area, and the amount of memory past the array that is accessible is limited by the largest possible ASCII filename character. This patch solves the issue reported by mhalcrow but with an implementation suggested by Linus to simply extend the length of filename_rev_map[] to 256. Characters greater than 0x7A are mapped to 0x00, which is how invalid characters less than 0x7A were previously being handled. Signed-off-by: Tyler Hicks Reported-by: Michael Halcrow Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 203a1fdff66..2a834255c75 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1945,7 +1945,7 @@ static unsigned char *portable_filename_chars = ("-.0123456789ABCD" /* We could either offset on every reverse map or just pad some 0x00's * at the front here */ -static const unsigned char filename_rev_map[] = { +static const unsigned char filename_rev_map[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 15 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ @@ -1961,7 +1961,7 @@ static const unsigned char filename_rev_map[] = { 0x00, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, /* 103 */ 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, /* 111 */ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, /* 119 */ - 0x3D, 0x3E, 0x3F + 0x3D, 0x3E, 0x3F /* 123 - 255 initialized to 0x00 */ }; /** -- cgit v1.2.3 From 49f5bf4e65140344f6ab824571b8325b7bd95d9b Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 16 Nov 2011 18:28:01 +0100 Subject: crypto: mv_cesa - fix hashing of chunks > 1920 bytes commit 274252862f386b7868f35bf5ceaa5391a8ccfdf3 upstream. This was broken by commit 7759995c75ae0cbd4c861582908449f6b6208e7a (yes, myself). The basic problem here is since the digest state is only saved after the last chunk, the state array is only valid when handling the first chunk of the next buffer. Broken since linux-3.0. Signed-off-by: Phil Sutter Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/mv_cesa.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c index 3cf303ee3fe..38a3297ae2b 100644 --- a/drivers/crypto/mv_cesa.c +++ b/drivers/crypto/mv_cesa.c @@ -342,11 +342,13 @@ static void mv_process_hash_current(int first_block) else op.config |= CFG_MID_FRAG; - writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A); - writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B); - writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C); - writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D); - writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E); + if (first_block) { + writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A); + writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B); + writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C); + writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D); + writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E); + } } memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config)); -- cgit v1.2.3 From 02a04b98adead5626a395edc21bf6d7f17611938 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 23 Nov 2011 01:12:01 -0500 Subject: drm: integer overflow in drm_mode_dirtyfb_ioctl() commit a5cd335165e31db9dbab636fd29895d41da55dd2 upstream. There is a potential integer overflow in drm_mode_dirtyfb_ioctl() if userspace passes in a large num_clips. The call to kmalloc would allocate a small buffer, and the call to fb->funcs->dirty may result in a memory corruption. Reported-by: Haogang Chen Signed-off-by: Xi Wang Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_crtc.c | 4 ++++ include/drm/drm_mode.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index fe738f05309..2410c4078f3 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1868,6 +1868,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, } if (num_clips && clips_ptr) { + if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { + ret = -EINVAL; + goto out_err1; + } clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); if (!clips) { ret = -ENOMEM; diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index c4961ea50a4..53dfa1098b9 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -233,6 +233,8 @@ struct drm_mode_fb_cmd { #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02 #define DRM_MODE_FB_DIRTY_FLAGS 0x03 +#define DRM_MODE_FB_DIRTY_MAX_CLIPS 256 + /* * Mark a region of a framebuffer as dirty. * -- cgit v1.2.3 From 24966e970264bfffa616f1f2d5f65a2db069b871 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 21 Nov 2011 12:10:14 -0500 Subject: drm/radeon/kms: fix up gpio i2c mask bits for r4xx for real commit d724502a9d7a46f4a56a1663b1f50d2dc9d1ef40 upstream. Fixes i2c test failures when i2c_algo_bit.bit_test=1. The hw doesn't actually require a mask, so just set it to the default mask bits for r1xx-r4xx radeon ddc. I missed this part the first time through. Signed-off-by: Alex Deucher Cc: Jean Delvare Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_atombios.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index bf2b61584cd..9d996c6d4cb 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -169,6 +169,18 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev) gpio = &i2c_info->asGPIO_Info[i]; i2c.valid = false; + /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ + if ((rdev->family == CHIP_R420) || + (rdev->family == CHIP_R423) || + (rdev->family == CHIP_RV410)) { + if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { + gpio->ucClkMaskShift = 0x19; + gpio->ucDataMaskShift = 0x18; + } + } + /* some evergreen boards have bad data for this entry */ if (ASIC_IS_DCE4(rdev)) { if ((i == 7) && -- cgit v1.2.3 From 03d51d153892ab5f07362ba63e088f8bf2d0512e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 9 Oct 2011 21:52:01 +0200 Subject: drm/i915: Ivybridge still has fences! commit 775d17b6ca4357048f36c22151335addfe15db4b upstream. So don't forget to restore them on resume and dump them into the error state. Signed-off-by: Daniel Vetter Reviewed-by: Chris Wilson Signed-off-by: Keith Packard Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_irq.c | 1 + drivers/gpu/drm/i915/i915_suspend.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 9cbb0cd8f46..73248d0ea17 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -822,6 +822,7 @@ static void i915_gem_record_fences(struct drm_device *dev, /* Fences */ switch (INTEL_INFO(dev)->gen) { + case 7: case 6: for (i = 0; i < 16; i++) error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index f10742359ec..9c7706a4c71 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -370,6 +370,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) /* Fences */ switch (INTEL_INFO(dev)->gen) { + case 7: case 6: for (i = 0; i < 16; i++) dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); @@ -404,6 +405,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev) /* Fences */ switch (INTEL_INFO(dev)->gen) { + case 7: case 6: for (i = 0; i < 16; i++) I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]); -- cgit v1.2.3 From 9bdbb716a8c3a3363d40b198f351d78bfecd8917 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 7 Nov 2011 16:07:04 -0800 Subject: drm/i915: Turn on a required 3D clock gating bit on Sandybridge. commit 406478dc911e16677fbd9c84d1d50cdffbc031ab upstream. Fixes rendering failures in Unigine Tropics and Sanctuary and the mesa "fire" demo. Signed-off-by: Eric Anholt Signed-off-by: Keith Packard Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 90587de0e86..900ef944d96 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3401,6 +3401,9 @@ #define GT_FIFO_FREE_ENTRIES 0x120008 #define GT_FIFO_NUM_RESERVED_ENTRIES 20 +#define GEN6_UCGCTL2 0x9404 +# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) + #define GEN6_RPNSWREQ 0xA008 #define GEN6_TURBO_DISABLE (1<<31) #define GEN6_FREQUENCY(x) ((x)<<25) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e1340a248a2..6ebfbb6a559 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7882,6 +7882,15 @@ static void gen6_init_clock_gating(struct drm_device *dev) I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); + /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock + * gating disable must be set. Failure to set it results in + * flickering pixels due to Z write ordering failures after + * some amount of runtime in the Mesa "fire" demo, and Unigine + * Sanctuary and Tropics, and apparently anything else with + * alpha test or pixel discard. + */ + I915_WRITE(GEN6_UCGCTL2, GEN6_RCPBUNIT_CLOCK_GATE_DISABLE); + /* * According to the spec the following bits should be * set in order to enable memory self-refresh and fbc: -- cgit v1.2.3 From 8f9940d1bf1d7dface90977031e327ee237408ca Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 7 Nov 2011 16:07:05 -0800 Subject: drm/i915: Turn on another required clock gating bit on gen6. commit 9ca1d10d748e56964de95e3ed80211b192f56cf4 upstream. Unlike the previous one, I don't have known testcases it fixes. I'd rather not go through the same debug cycle on whatever testcases those might be. Signed-off-by: Eric Anholt Signed-off-by: Keith Packard Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 900ef944d96..ad381a236b3 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3403,6 +3403,7 @@ #define GEN6_UCGCTL2 0x9404 # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) +# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) #define GEN6_RPNSWREQ 0xA008 #define GEN6_TURBO_DISABLE (1<<31) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6ebfbb6a559..07e7cf38068 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7888,8 +7888,13 @@ static void gen6_init_clock_gating(struct drm_device *dev) * some amount of runtime in the Mesa "fire" demo, and Unigine * Sanctuary and Tropics, and apparently anything else with * alpha test or pixel discard. + * + * According to the spec, bit 11 (RCCUNIT) must also be set, + * but we didn't debug actual testcases to find it out. */ - I915_WRITE(GEN6_UCGCTL2, GEN6_RCPBUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(GEN6_UCGCTL2, + GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | + GEN6_RCCUNIT_CLOCK_GATE_DISABLE); /* * According to the spec the following bits should be -- cgit v1.2.3 From d02f594b5287e6b8a0274991b6b6e645cef79b33 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 16 Nov 2011 10:58:03 +0100 Subject: drm/i915: Fix inconsistent backlight level during disabled commit 04b38670cf46c096705f24e92a8747d1ab89e53c upstream. When the brightness property is inquired while the backlight is disabled, the driver returns a wrong value (zero) because it probes the value after the backlight was turned off. This caused a black screen even after the backlight is enabled again. It should return the internal backlight_level instead, so that it won't be influenced by the backlight-enable state. BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=41926 BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/872652 Tested-by: Kamal Mostafa Cc: Alex Davis Signed-off-by: Takashi Iwai Signed-off-by: Keith Packard Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_panel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index af08ff328dd..007f6ca309d 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -326,7 +326,8 @@ static int intel_panel_update_status(struct backlight_device *bd) static int intel_panel_get_brightness(struct backlight_device *bd) { struct drm_device *dev = bl_get_data(bd); - return intel_panel_get_backlight(dev); + struct drm_i915_private *dev_priv = dev->dev_private; + return dev_priv->backlight_level; } static const struct backlight_ops intel_panel_bl_ops = { -- cgit v1.2.3 From 14855077253713109f8a835cc6e9271432460de9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 23 Aug 2011 10:16:43 -0600 Subject: PCI hotplug: shpchp: don't blindly claim non-AMD 0x7450 device IDs commit 4cac2eb158c6da0c761689345c6cc5df788a6292 upstream. Previously we claimed device ID 0x7450, regardless of the vendor, which is clearly wrong. Now we'll claim that device ID only for AMD. I suspect this was just a typo in the original code, but it's possible this change will break shpchp on non-7450 AMD bridges. If so, we'll have to fix them as we find them. Reference: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=638863 Reported-by: Ralf Jung Cc: Joerg Roedel Signed-off-by: Bjorn Helgaas Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_core.c | 4 ++-- drivers/pci/hotplug/shpchp_hpc.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index aca972bbfb4..dd7e0c51a33 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -278,8 +278,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) static int is_shpc_capable(struct pci_dev *dev) { - if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == - PCI_DEVICE_ID_AMD_GOLAM_7450)) + if (dev->vendor == PCI_VENDOR_ID_AMD && + dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450) return 1; if (!pci_find_capability(dev, PCI_CAP_ID_SHPC)) return 0; diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 36547f0ce30..75ba2311b54 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -944,8 +944,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ ctrl_dbg(ctrl, "Hotplug Controller:\n"); - if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == - PCI_DEVICE_ID_AMD_GOLAM_7450)) { + if (pdev->vendor == PCI_VENDOR_ID_AMD && + pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450) { /* amd shpc driver doesn't use Base Offset; assume 0 */ ctrl->mmio_base = pci_resource_start(pdev, 0); ctrl->mmio_size = pci_resource_len(pdev, 0); -- cgit v1.2.3 From cbd00285bbef94804213974a5fd084c3f7197ec6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 14 Nov 2011 14:32:01 -0500 Subject: drm/radeon/kms: fix up gpio i2c mask bits for r4xx commit 6c47e5c23aa2a7c54ad7ac13af4bd56cd9e703bf upstream. Fixes i2c test failures when i2c_algo_bit.bit_test=1. The hw doesn't actually require a mask, so just set it to the default mask bits for r1xx-r4xx radeon ddc. Signed-off-by: Alex Deucher Cc: Jean Delvare Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_atombios.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 9d996c6d4cb..285acc4f1e1 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -85,6 +85,18 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev for (i = 0; i < num_indices; i++) { gpio = &i2c_info->asGPIO_Info[i]; + /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */ + if ((rdev->family == CHIP_R420) || + (rdev->family == CHIP_R423) || + (rdev->family == CHIP_RV410)) { + if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) || + (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) { + gpio->ucClkMaskShift = 0x19; + gpio->ucDataMaskShift = 0x18; + } + } + /* some evergreen boards have bad data for this entry */ if (ASIC_IS_DCE4(rdev)) { if ((i == 7) && -- cgit v1.2.3 From df01c1efffdaf26ef874f96986a64776c170b024 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 21 Nov 2011 15:05:56 +0000 Subject: viafb: correct sync polarity for OLPC DCON commit a32839696a8eef813a1aff604fbad9a32dff6c95 upstream. While the OLPC display appears to be able to handle either positive or negative sync, the Display Controller only recognises positive sync. This brings viafb (for XO-1.5) in line with lxfb (for XO-1) and fixes a recent regression where the XO-1.5 DCON could no longer be frozen. Thanks to Florian Tobias Schandinat for helping identify the fix. Test case: from a vt, echo 1 > /sys/devices/platform/dcon/freeze should cause the current screen contents to freeze, rather than garbage being displayed. Signed-off-by: Daniel Drake Signed-off-by: Florian Tobias Schandinat Signed-off-by: Greg Kroah-Hartman --- drivers/video/via/share.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 61b0bd596b8..1603023e3aa 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -557,8 +557,8 @@ #define M1200X720_R60_VSP POSITIVE /* 1200x900@60 Sync Polarity (DCON) */ -#define M1200X900_R60_HSP NEGATIVE -#define M1200X900_R60_VSP NEGATIVE +#define M1200X900_R60_HSP POSITIVE +#define M1200X900_R60_VSP POSITIVE /* 1280x600@60 Sync Polarity (GTF Mode) */ #define M1280x600_R60_HSP NEGATIVE -- cgit v1.2.3 From 8533dca18388b89bcb1772c5f504ac96a4826632 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Thu, 10 Nov 2011 07:13:07 +0800 Subject: ARM: pxa: fix inconsistent CONFIG_USB_PXA27X commit c0a39151a4055332897cba615623d3de2f3896df upstream. Since CONFIG_USB_GADGET_PXA27X and other macros are renamed to CONFIG_USB_PXA27X. Update them in arch/arm/mach-pxa and arch/arm/configs to keep consistent. Signed-off-by: Haojian Zhuang Acked-by: Felipe Balbi Signed-off-by: Eric Miao Signed-off-by: Greg Kroah-Hartman --- arch/arm/configs/ezx_defconfig | 2 +- arch/arm/configs/imote2_defconfig | 2 +- arch/arm/configs/magician_defconfig | 2 +- arch/arm/configs/zeus_defconfig | 2 +- arch/arm/mach-pxa/balloon3.c | 2 +- arch/arm/mach-pxa/colibri-pxa320.c | 2 +- arch/arm/mach-pxa/gumstix.c | 2 +- arch/arm/mach-pxa/include/mach/palm27x.h | 4 ++-- arch/arm/mach-pxa/palm27x.c | 4 ++-- arch/arm/mach-pxa/palmtc.c | 2 +- arch/arm/mach-pxa/vpac270.c | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig index 227a477346e..d95763d5f0d 100644 --- a/arch/arm/configs/ezx_defconfig +++ b/arch/arm/configs/ezx_defconfig @@ -287,7 +287,7 @@ CONFIG_USB=y # CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_OHCI_HCD=y CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_PXA27X=y +CONFIG_USB_PXA27X=y CONFIG_USB_ETH=m # CONFIG_USB_ETH_RNDIS is not set CONFIG_MMC=y diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig index 176ec22af03..fd996bb1302 100644 --- a/arch/arm/configs/imote2_defconfig +++ b/arch/arm/configs/imote2_defconfig @@ -263,7 +263,7 @@ CONFIG_USB=y # CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_OHCI_HCD=y CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_PXA27X=y +CONFIG_USB_PXA27X=y CONFIG_USB_ETH=m # CONFIG_USB_ETH_RNDIS is not set CONFIG_MMC=y diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig index a88e64d4e9a..443675d317e 100644 --- a/arch/arm/configs/magician_defconfig +++ b/arch/arm/configs/magician_defconfig @@ -132,7 +132,7 @@ CONFIG_USB_MON=m CONFIG_USB_OHCI_HCD=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=500 -CONFIG_USB_GADGET_PXA27X=y +CONFIG_USB_PXA27X=y CONFIG_USB_ETH=m # CONFIG_USB_ETH_RNDIS is not set CONFIG_USB_GADGETFS=m diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig index 59577ad3f4e..547a3c1e59d 100644 --- a/arch/arm/configs/zeus_defconfig +++ b/arch/arm/configs/zeus_defconfig @@ -140,7 +140,7 @@ CONFIG_USB_SERIAL=m CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_MCT_U232=m CONFIG_USB_GADGET=m -CONFIG_USB_GADGET_PXA27X=y +CONFIG_USB_PXA27X=y CONFIG_USB_ETH=m CONFIG_USB_GADGETFS=m CONFIG_USB_FILE_STORAGE=m diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index ef3e8b1e06c..6c6f5e42fbe 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -307,7 +307,7 @@ static inline void balloon3_mmc_init(void) {} /****************************************************************************** * USB Gadget ******************************************************************************/ -#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE) +#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE) static void balloon3_udc_command(int cmd) { if (cmd == PXA2XX_UDC_CMD_CONNECT) diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c index d2c6631915d..db3a9380dc8 100644 --- a/arch/arm/mach-pxa/colibri-pxa320.c +++ b/arch/arm/mach-pxa/colibri-pxa320.c @@ -146,7 +146,7 @@ static void __init colibri_pxa320_init_eth(void) static inline void __init colibri_pxa320_init_eth(void) {} #endif /* CONFIG_AX88796 */ -#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE) +#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE) static struct gpio_vbus_mach_info colibri_pxa320_gpio_vbus_info = { .gpio_vbus = mfp_to_gpio(MFP_PIN_GPIO96), .gpio_pullup = -1, diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c index deaa111c91f..4aa3dba8fc7 100644 --- a/arch/arm/mach-pxa/gumstix.c +++ b/arch/arm/mach-pxa/gumstix.c @@ -106,7 +106,7 @@ static void __init gumstix_mmc_init(void) } #endif -#ifdef CONFIG_USB_GADGET_PXA25X +#ifdef CONFIG_USB_PXA25X static struct gpio_vbus_mach_info gumstix_udc_info = { .gpio_vbus = GPIO_GUMSTIX_USB_GPIOn, .gpio_pullup = GPIO_GUMSTIX_USB_GPIOx, diff --git a/arch/arm/mach-pxa/include/mach/palm27x.h b/arch/arm/mach-pxa/include/mach/palm27x.h index 0a5e5eadebf..8d560437e6e 100644 --- a/arch/arm/mach-pxa/include/mach/palm27x.h +++ b/arch/arm/mach-pxa/include/mach/palm27x.h @@ -37,8 +37,8 @@ extern void __init palm27x_lcd_init(int power, static inline void palm27x_lcd_init(int power, struct pxafb_mode_info *mode) {} #endif -#if defined(CONFIG_USB_GADGET_PXA27X) || \ - defined(CONFIG_USB_GADGET_PXA27X_MODULE) +#if defined(CONFIG_USB_PXA27X) || \ + defined(CONFIG_USB_PXA27X_MODULE) extern void __init palm27x_udc_init(int vbus, int pullup, int vbus_inverted); #else diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c index 325c245c0a0..fbc10d7b95d 100644 --- a/arch/arm/mach-pxa/palm27x.c +++ b/arch/arm/mach-pxa/palm27x.c @@ -164,8 +164,8 @@ void __init palm27x_lcd_init(int power, struct pxafb_mode_info *mode) /****************************************************************************** * USB Gadget ******************************************************************************/ -#if defined(CONFIG_USB_GADGET_PXA27X) || \ - defined(CONFIG_USB_GADGET_PXA27X_MODULE) +#if defined(CONFIG_USB_PXA27X) || \ + defined(CONFIG_USB_PXA27X_MODULE) static struct gpio_vbus_mach_info palm27x_udc_info = { .gpio_vbus_inverted = 1, }; diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c index 6ad4a6c7bc9..9c27b012415 100644 --- a/arch/arm/mach-pxa/palmtc.c +++ b/arch/arm/mach-pxa/palmtc.c @@ -338,7 +338,7 @@ static inline void palmtc_mkp_init(void) {} /****************************************************************************** * UDC ******************************************************************************/ -#if defined(CONFIG_USB_GADGET_PXA25X)||defined(CONFIG_USB_GADGET_PXA25X_MODULE) +#if defined(CONFIG_USB_PXA25X)||defined(CONFIG_USB_PXA25X_MODULE) static struct gpio_vbus_mach_info palmtc_udc_info = { .gpio_vbus = GPIO_NR_PALMTC_USB_DETECT_N, .gpio_vbus_inverted = 1, diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index 5f8490ab07c..3a1fa1d3c6c 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -343,7 +343,7 @@ static inline void vpac270_uhc_init(void) {} /****************************************************************************** * USB Gadget ******************************************************************************/ -#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE) +#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE) static struct gpio_vbus_mach_info vpac270_gpio_vbus_info = { .gpio_vbus = GPIO41_VPAC270_UDC_DETECT, .gpio_pullup = -1, -- cgit v1.2.3 From acc0e76c23b07b8d0bd85774de9904ce278115c4 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 10 Sep 2011 12:26:07 +0200 Subject: arm: mx28: fix bit operation in clock setting commit c2735391fbc68feae10d6d14e60956c8106e725f upstream. reg | (1 << clk->enable_shift) always evaluates to true. Switch it to & which makes much more sense. Same fix as 13be9f00 (ARM i.MX28: fix bit operation) at a different location. Signed-off-by: Wolfram Sang Cc: Sascha Hauer Cc: Shawn Guo Signed-off-by: Shawn Guo Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-mxs/clock-mx28.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index 5dcc59d5b9e..b3a71245f38 100644 --- a/arch/arm/mach-mxs/clock-mx28.c +++ b/arch/arm/mach-mxs/clock-mx28.c @@ -404,7 +404,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ reg &= ~BM_CLKCTRL_##dr##_DIV; \ reg |= div << BP_CLKCTRL_##dr##_DIV; \ - if (reg | (1 << clk->enable_shift)) { \ + if (reg & (1 << clk->enable_shift)) { \ pr_err("%s: clock is gated\n", __func__); \ return -EINVAL; \ } \ -- cgit v1.2.3 From 8fe9f659b730ca92367370cf7ae6de6ef640cf62 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 23 Nov 2011 14:43:37 -0800 Subject: ARM: OMAP: smartreflex: fix IRQ handling bug commit 5a4f1844c2ba21f804d7729306d9b16eaeb724a8 upstream. Fix a bug which has been on this driver since it was added by the original commit 984aa6db which would never clear IRQSTATUS bits. Signed-off-by: Felipe Balbi Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/smartreflex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 34c01a7de81..19ff0104374 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -137,7 +137,7 @@ static irqreturn_t sr_interrupt(int irq, void *data) sr_write_reg(sr_info, ERRCONFIG_V1, status); } else if (sr_info->ip_type == SR_TYPE_V2) { /* Read the status bits */ - sr_read_reg(sr_info, IRQSTATUS); + status = sr_read_reg(sr_info, IRQSTATUS); /* Clear them by writing back */ sr_write_reg(sr_info, IRQSTATUS, status); -- cgit v1.2.3 From 969b42a8899f173a232b5ad14b2a0f5913c8b3b1 Mon Sep 17 00:00:00 2001 From: sricharan Date: Wed, 23 Nov 2011 14:35:07 -0800 Subject: ARM: OMAP: hwmod: Fix the addr space, irq, dma count APIs commit cc1b0765da6078b906772b79ff211b88cc0ae958 upstream. The address spaces, irqs and dma reqs count APIs return the number of corresponding entries in a hwmod including a additional null value or a -1 terminator in the structure introduced recently. More information here: - 212738a4: omap_hwmod: use a terminator record with omap_hwmod_mpu_irqs arrays - 78183f3f: omap_hwmod: use a null structure record to terminate omap_hwmod_addr_space arrays - bc614958: omap_hwmod: use a terminator record with omap_hwmod_dma_info arrays The issue with irqs and dma info was originally reported by Benoit Cousson. The devices which have multiple hwmods and use device_build_ss are broken with this, as their resources are populated with a extra null value, subsequently the probe fails. So fix the API not to include the array terminator in the count. Reported-by: Benoit Cousson Signed-off-by: Santosh Shilimkar Signed-off-by: sricharan Signed-off-by: Benoit Cousson Cc: Paul Walmsley Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/omap_hwmod.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 84cc0bdda3a..f396c83a30c 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -749,7 +749,7 @@ static int _count_mpu_irqs(struct omap_hwmod *oh) ohii = &oh->mpu_irqs[i++]; } while (ohii->irq != -1); - return i; + return i-1; } /** @@ -772,7 +772,7 @@ static int _count_sdma_reqs(struct omap_hwmod *oh) ohdi = &oh->sdma_reqs[i++]; } while (ohdi->dma_req != -1); - return i; + return i-1; } /** @@ -795,7 +795,7 @@ static int _count_ocp_if_addr_spaces(struct omap_hwmod_ocp_if *os) mem = &os->addr[i++]; } while (mem->pa_start != mem->pa_end); - return i; + return i-1; } /** -- cgit v1.2.3 From 8591c9d862e86646a1b76ca3154c0ec1b58d51c6 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 23 Nov 2011 14:44:50 -0800 Subject: ARM: OMAP2: select ARM_AMBA if OMAP3_EMU is defined commit a8a6565c7615cab3608d75af95b5c8a3522cd7c4 upstream. This patch selects ARM_AMBA if OMAP3_EMU is defined because OC_ETM depends on ARM_AMBA, so fix the link failure[1]. [1], arch/arm/kernel/built-in.o: In function `etm_remove': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:609: undefined reference to `amba_release_regions' arch/arm/kernel/built-in.o: In function `etb_remove': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:409: undefined reference to `amba_release_regions' arch/arm/kernel/built-in.o: In function `etm_init': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:640: undefined reference to `amba_driver_register' /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:646: undefined reference to `amba_driver_register' /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:648: undefined reference to `amba_driver_unregister' arch/arm/kernel/built-in.o: In function `etm_probe': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:545: undefined reference to `amba_request_regions' /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:595: undefined reference to `amba_release_regions' arch/arm/kernel/built-in.o: In function `etb_probe': /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:347: undefined reference to `amba_request_regions' /home/tom/git/omap/linux-2.6-omap/arch/arm/kernel/etm.c:392: undefined reference to `amba_release_regions' arch/arm/mach-omap2/built-in.o: In function `emu_init': /home/tom/git/omap/linux-2.6-omap/arch/arm/mach-omap2/emu.c:62: undefined reference to `amba_device_register' /home/tom/git/omap/linux-2.6-omap/arch/arm/mach-omap2/emu.c:63: undefined reference to `amba_device_register' make: *** [.tmp_vmlinux1] Error 1 making modules Signed-off-by: Ming Lei Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 57b66d590c5..b45c88d4276 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -329,6 +329,7 @@ config MACH_OMAP4_PANDA config OMAP3_EMU bool "OMAP3 debugging peripherals" depends on ARCH_OMAP3 + select ARM_AMBA select OC_ETM help Say Y here to enable debugging hardware of omap3 -- cgit v1.2.3 From e9b529a3d8929c793ed6326d407ec7bf18bff6bb Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 23 Nov 2011 14:43:01 -0800 Subject: ARM: OMAP: PM: only register TWL with voltage layer when device is present commit 46232a3622c6e33605906ee6690dfef372925f53 upstream. Current code registers voltage layer details for TWL PMIC even when a TWL has not been registered. Fix this to only register the TWL with voltage layer when the TWL PMIC is initialized by board-level code. Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/pm.c | 6 ++---- arch/arm/mach-omap2/twl-common.c | 11 +++++++++++ arch/arm/mach-omap2/twl-common.h | 3 +++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 472bf22d5e8..95eb863f780 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -23,6 +23,7 @@ #include "powerdomain.h" #include "clockdomain.h" #include "pm.h" +#include "twl-common.h" static struct omap_device_pm_latency *pm_lats; @@ -251,11 +252,8 @@ postcore_initcall(omap2_common_pm_init); static int __init omap2_common_pm_late_init(void) { - /* Init the OMAP TWL parameters */ - omap3_twl_init(); - omap4_twl_init(); - /* Init the voltage layer */ + omap_pmic_late_init(); omap_voltage_late_init(); /* Initialize the voltages */ diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index daa056ed873..47133fae60d 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -30,6 +30,7 @@ #include #include "twl-common.h" +#include "pm.h" static struct i2c_board_info __initdata pmic_i2c_board_info = { .addr = 0x48, @@ -48,6 +49,16 @@ void __init omap_pmic_init(int bus, u32 clkrate, omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1); } +void __init omap_pmic_late_init(void) +{ + /* Init the OMAP TWL parameters (if PMIC has been registerd) */ + if (!pmic_i2c_board_info.irq) + return; + + omap3_twl_init(); + omap4_twl_init(); +} + #if defined(CONFIG_ARCH_OMAP3) static struct twl4030_usb_data omap3_usb_pdata = { .usb_mode = T2_USB_MODE_ULPI, diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h index 5e83a5bd37f..275dde8cb27 100644 --- a/arch/arm/mach-omap2/twl-common.h +++ b/arch/arm/mach-omap2/twl-common.h @@ -1,6 +1,8 @@ #ifndef __OMAP_PMIC_COMMON__ #define __OMAP_PMIC_COMMON__ +#include + #define TWL_COMMON_PDATA_USB (1 << 0) #define TWL_COMMON_PDATA_BCI (1 << 1) #define TWL_COMMON_PDATA_MADC (1 << 2) @@ -30,6 +32,7 @@ struct twl4030_platform_data; void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq, struct twl4030_platform_data *pmic_data); +void omap_pmic_late_init(void); static inline void omap2_pmic_init(const char *pmic_type, struct twl4030_platform_data *pmic_data) -- cgit v1.2.3 From 03c371b70411f1f2805e2965eff0629908b59c13 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 14 Nov 2011 17:24:58 +0100 Subject: ARM: 7161/1: errata: no automatic store buffer drain commit 11ed0ba1754841316d4095478944300acf19acc3 upstream. This patch implements a workaround for PL310 erratum 769419. On revisions of the PL310 prior to r3p2, the Store Buffer does not automatically drain. This can cause normal, non-cacheable writes to be retained when the memory system is idle, leading to suboptimal I/O performance for drivers using coherent DMA. This patch adds an optional wmb() call to the cpu_idle loop. On systems with an outer cache, this causes an explicit flush of the store buffer. Acked-by: Catalin Marinas Tested-by: Marc Zyngier Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/Kconfig | 12 ++++++++++++ arch/arm/kernel/process.c | 3 +++ 2 files changed, 15 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3146ed3f6ec..dfe01400cd1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1297,6 +1297,18 @@ config ARM_ERRATA_764369 relevant cache maintenance functions and sets a specific bit in the diagnostic control register of the SCU. +config PL310_ERRATA_769419 + bool "PL310 errata: no automatic Store Buffer drain" + depends on CACHE_L2X0 + help + On revisions of the PL310 prior to r3p2, the Store Buffer does + not automatically drain. This can cause normal, non-cacheable + writes to be retained when the memory system is idle, leading + to suboptimal I/O performance for drivers using coherent DMA. + This option adds a write barrier to the cpu_idle loop so that, + on systems with an outer cache, the store buffer is drained + explicitly. + endmenu source "arch/arm/common/Kconfig" diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 1a347f481e5..c9d11eaf438 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -192,6 +192,9 @@ void cpu_idle(void) #endif local_irq_disable(); +#ifdef CONFIG_PL310_ERRATA_769419 + wmb(); +#endif if (hlt_counter) { local_irq_enable(); cpu_relax(); -- cgit v1.2.3 From 9b8fd4ef07fdfeb445ab35b2329fe3c1727297fe Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 24 Nov 2011 16:33:09 +0100 Subject: ALSA: hda - Fix jack-detection control of VT1708 commit 187d333edc0a8e1bb507900ce89853ffe3bd2c84 upstream. VT1708 has no support for unsolicited events per jack-plug, the driver implements the workq for polling the jack-detection. The mixer element "Jack Detect" was supposed to control this behavior on/off, but this doesn't work properly as is now. The workq is always started and the HP automute is always enabled. This patch fixes the jack-detect control behavior by triggering / stopping the work appropriately at the state change. Also the work checks the internal state to continue scheduling or not. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_via.c | 76 +++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 4ebfbd874c9..d636d939641 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -207,6 +207,7 @@ struct via_spec { /* work to check hp jack state */ struct hda_codec *codec; struct delayed_work vt1708_hp_work; + int hp_work_active; int vt1708_jack_detect; int vt1708_hp_present; @@ -304,27 +305,35 @@ enum { static void analog_low_current_mode(struct hda_codec *codec); static bool is_aa_path_mute(struct hda_codec *codec); -static void vt1708_start_hp_work(struct via_spec *spec) +#define hp_detect_with_aa(codec) \ + (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \ + !is_aa_path_mute(codec)) + +static void vt1708_stop_hp_work(struct via_spec *spec) { if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) return; - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, - !spec->vt1708_jack_detect); - if (!delayed_work_pending(&spec->vt1708_hp_work)) - schedule_delayed_work(&spec->vt1708_hp_work, - msecs_to_jiffies(100)); + if (spec->hp_work_active) { + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 1); + cancel_delayed_work_sync(&spec->vt1708_hp_work); + spec->hp_work_active = 0; + } } -static void vt1708_stop_hp_work(struct via_spec *spec) +static void vt1708_update_hp_work(struct via_spec *spec) { if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) return; - if (snd_hda_get_bool_hint(spec->codec, "analog_loopback_hp_detect") == 1 - && !is_aa_path_mute(spec->codec)) - return; - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, - !spec->vt1708_jack_detect); - cancel_delayed_work_sync(&spec->vt1708_hp_work); + if (spec->vt1708_jack_detect && + (spec->active_streams || hp_detect_with_aa(spec->codec))) { + if (!spec->hp_work_active) { + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0); + schedule_delayed_work(&spec->vt1708_hp_work, + msecs_to_jiffies(100)); + spec->hp_work_active = 1; + } + } else if (!hp_detect_with_aa(spec->codec)) + vt1708_stop_hp_work(spec); } static void set_widgets_power_state(struct hda_codec *codec) @@ -342,12 +351,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol, set_widgets_power_state(codec); analog_low_current_mode(snd_kcontrol_chip(kcontrol)); - if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) { - if (is_aa_path_mute(codec)) - vt1708_start_hp_work(codec->spec); - else - vt1708_stop_hp_work(codec->spec); - } + vt1708_update_hp_work(codec->spec); return change; } @@ -1153,7 +1157,7 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_dac_stream_tag = stream_tag; spec->cur_dac_format = format; mutex_unlock(&spec->config_mutex); - vt1708_start_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1173,7 +1177,7 @@ static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_hp_stream_tag = stream_tag; spec->cur_hp_format = format; mutex_unlock(&spec->config_mutex); - vt1708_start_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1187,7 +1191,7 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo, snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); spec->active_streams &= ~STREAM_MULTI_OUT; mutex_unlock(&spec->config_mutex); - vt1708_stop_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1202,7 +1206,7 @@ static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo, snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0); spec->active_streams &= ~STREAM_INDEP_HP; mutex_unlock(&spec->config_mutex); - vt1708_stop_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1632,7 +1636,8 @@ static void via_hp_automute(struct hda_codec *codec) int nums; struct via_spec *spec = codec->spec; - if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0]) + if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] && + (spec->codec_type != VT1708 || spec->vt1708_jack_detect)) present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); if (spec->smart51_enabled) @@ -2599,8 +2604,6 @@ static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol, if (spec->codec_type != VT1708) return 0; - spec->vt1708_jack_detect = - !((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1); ucontrol->value.integer.value[0] = spec->vt1708_jack_detect; return 0; } @@ -2610,18 +2613,22 @@ static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; - int change; + int val; if (spec->codec_type != VT1708) return 0; - spec->vt1708_jack_detect = ucontrol->value.integer.value[0]; - change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8)) - == !spec->vt1708_jack_detect; - if (spec->vt1708_jack_detect) { + val = !!ucontrol->value.integer.value[0]; + if (spec->vt1708_jack_detect == val) + return 0; + spec->vt1708_jack_detect = val; + if (spec->vt1708_jack_detect && + snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) { mute_aa_path(codec, 1); notify_aa_path_ctls(codec); } - return change; + via_hp_automute(codec); + vt1708_update_hp_work(spec); + return 1; } static const struct snd_kcontrol_new vt1708_jack_detect_ctl = { @@ -2758,6 +2765,7 @@ static int via_init(struct hda_codec *codec) via_auto_init_unsol_event(codec); via_hp_automute(codec); + vt1708_update_hp_work(spec); return 0; } @@ -2774,7 +2782,9 @@ static void vt1708_update_hp_jack_state(struct work_struct *work) spec->vt1708_hp_present ^= 1; via_hp_automute(spec->codec); } - vt1708_start_hp_work(spec); + if (spec->vt1708_jack_detect) + schedule_delayed_work(&spec->vt1708_hp_work, + msecs_to_jiffies(100)); } static int get_mux_nids(struct hda_codec *codec) -- cgit v1.2.3 From 30444a763d652293e36f38ca43de13d6cf5ec3b0 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Tue, 22 Nov 2011 11:15:45 +0100 Subject: ALSA: lx6464es - fix device communication via command bus commit a29878553a9a7b4c06f93c7e383527cf014d4ceb upstream. commit 6175ddf06b6172046a329e3abfd9c901a43efd2e optimized the mem*io functions that have been used to send commands to the device. these optimizations somehow corrupted the communication with the lx6464es, that resulted the device to be unusable with kernels after 2.6.33. this patch emulates the memcpy_*_io functions via a loop to avoid these problems. Signed-off-by: Tim Blechmann LKML-Reference: <4ECB5257.4040600@ladisch.de> Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/lx6464es/lx_core.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index 5c8717e29ee..aa733725c56 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -80,8 +80,12 @@ unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port) void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len) { - void __iomem *address = lx_dsp_register(chip, port); - memcpy_fromio(data, address, len*sizeof(u32)); + u32 __iomem *address = lx_dsp_register(chip, port); + int i; + + /* we cannot use memcpy_fromio */ + for (i = 0; i != len; ++i) + data[i] = ioread32(address + i); } @@ -94,8 +98,12 @@ void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data) void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data, u32 len) { - void __iomem *address = lx_dsp_register(chip, port); - memcpy_toio(address, data, len*sizeof(u32)); + u32 __iomem *address = lx_dsp_register(chip, port); + int i; + + /* we cannot use memcpy_to */ + for (i = 0; i != len; ++i) + iowrite32(data[i], address + i); } -- cgit v1.2.3 From 45445147b0cf1c398b370aa064dc2fb7f9b5128e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 23 Nov 2011 07:38:59 +0100 Subject: ALSA: hda/realtek - Fix missing inits of item indices for auto-mic commit 6759dc323826c2c806c998cd93945c5476688dd2 upstream. When the imux entries are rebuilt in alc_rebuild_imux_for_auto_mic(), the initialization of index field is missing. It may work without it casually when the original imux was created by the auto-parser, but it's definitely broken in the case of static configs where no imux was parsed beforehand. Because of this, the auto-mic switching doesn't work properly on some model options. This patch adds the missing initialization of index field. Reported-by: Dmitry Nezhevenko Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index be79c9f75c0..c687e14733d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1023,8 +1023,20 @@ static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec) spec->imux_pins[2] = spec->dock_mic_pin; for (i = 0; i < 3; i++) { strcpy(imux->items[i].label, texts[i]); - if (spec->imux_pins[i]) + if (spec->imux_pins[i]) { + hda_nid_t pin = spec->imux_pins[i]; + int c; + for (c = 0; c < spec->num_adc_nids; c++) { + hda_nid_t cap = spec->capsrc_nids ? + spec->capsrc_nids[c] : spec->adc_nids[c]; + int idx = get_connection_index(codec, cap, pin); + if (idx >= 0) { + imux->items[i].index = idx; + break; + } + } imux->num_items = i + 1; + } } spec->num_mux_defs = 1; spec->input_mux = imux; -- cgit v1.2.3 From 71b3b360ee04f567eded77c3bcadb510f9a7c8f0 Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Mon, 14 Nov 2011 17:23:16 +0100 Subject: ASoC: sta32x: preserve coefficient RAM commit 54dc6cabe684375b3cf549c7b0545613d694aba8 upstream. The coefficient RAM must be saved in a shadow so it can be restored when the codec is powered on using regulator_bulk_enable(). Signed-off-by: Johannes Stezenbach Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/sta32x.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/sta32x.h | 1 + 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index fbd7eb9e61c..d5630aff6a0 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -76,6 +76,8 @@ struct sta32x_priv { unsigned int mclk; unsigned int format; + + u32 coef_shadow[STA32X_COEF_COUNT]; }; static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1); @@ -227,6 +229,7 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); int numcoef = kcontrol->private_value >> 16; int index = kcontrol->private_value & 0xffff; unsigned int cfud; @@ -239,6 +242,11 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, snd_soc_write(codec, STA32X_CFUD, cfud); snd_soc_write(codec, STA32X_CFADDR2, index); + for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++) + sta32x->coef_shadow[index + i] = + (ucontrol->value.bytes.data[3 * i] << 16) + | (ucontrol->value.bytes.data[3 * i + 1] << 8) + | (ucontrol->value.bytes.data[3 * i + 2]); for (i = 0; i < 3 * numcoef; i++) snd_soc_write(codec, STA32X_B1CF1 + i, ucontrol->value.bytes.data[i]); @@ -252,6 +260,48 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, return 0; } +int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) +{ + struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); + unsigned int cfud; + int i; + + /* preserve reserved bits in STA32X_CFUD */ + cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; + + for (i = 0; i < STA32X_COEF_COUNT; i++) { + snd_soc_write(codec, STA32X_CFADDR2, i); + snd_soc_write(codec, STA32X_B1CF1, + (sta32x->coef_shadow[i] >> 16) & 0xff); + snd_soc_write(codec, STA32X_B1CF2, + (sta32x->coef_shadow[i] >> 8) & 0xff); + snd_soc_write(codec, STA32X_B1CF3, + (sta32x->coef_shadow[i]) & 0xff); + /* chip documentation does not say if the bits are + * self-clearing, so do it explicitly */ + snd_soc_write(codec, STA32X_CFUD, cfud); + snd_soc_write(codec, STA32X_CFUD, cfud | 0x01); + } + return 0; +} + +int sta32x_cache_sync(struct snd_soc_codec *codec) +{ + unsigned int mute; + int rc; + + if (!codec->cache_sync) + return 0; + + /* mute during register sync */ + mute = snd_soc_read(codec, STA32X_MMUTE); + snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); + sta32x_sync_coef_shadow(codec); + rc = snd_soc_cache_sync(codec); + snd_soc_write(codec, STA32X_MMUTE, mute); + return rc; +} + #define SINGLE_COEF(xname, index) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = sta32x_coefficient_info, \ @@ -657,7 +707,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec, return ret; } - snd_soc_cache_sync(codec); + sta32x_cache_sync(codec); } /* Power up to mute */ @@ -792,6 +842,17 @@ static int sta32x_probe(struct snd_soc_codec *codec) STA32X_CxCFG_OM_MASK, 2 << STA32X_CxCFG_OM_SHIFT); + /* initialize coefficient shadow RAM with reset values */ + for (i = 4; i <= 49; i += 5) + sta32x->coef_shadow[i] = 0x400000; + for (i = 50; i <= 54; i++) + sta32x->coef_shadow[i] = 0x7fffff; + sta32x->coef_shadow[55] = 0x5a9df7; + sta32x->coef_shadow[56] = 0x7fffff; + sta32x->coef_shadow[59] = 0x7fffff; + sta32x->coef_shadow[60] = 0x400000; + sta32x->coef_shadow[61] = 0x400000; + sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Bias level configuration will have done an extra enable */ regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); diff --git a/sound/soc/codecs/sta32x.h b/sound/soc/codecs/sta32x.h index b97ee5a7566..d8e32a6262e 100644 --- a/sound/soc/codecs/sta32x.h +++ b/sound/soc/codecs/sta32x.h @@ -19,6 +19,7 @@ /* STA326 register addresses */ #define STA32X_REGISTER_COUNT 0x2d +#define STA32X_COEF_COUNT 62 #define STA32X_CONFA 0x00 #define STA32X_CONFB 0x01 -- cgit v1.2.3 From 38c15d6ae974128158acee43380508db968c80bf Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Mon, 14 Nov 2011 16:35:26 -0600 Subject: ASoC: fsl_ssi: properly initialize the sysfs attribute object commit 0f768a7235d3dfb6f4833030a95a06419df089cb upstream. Commit 6992f533 ("sysfs: Use one lockdep class per sysfs attribute") requires 'struct attribute' objects to be initialized with sysfs_attr_init(). Signed-off-by: Timur Tabi Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/fsl/fsl_ssi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index d48afea5d93..672982924f1 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -703,6 +703,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) /* Initialize the the device_attribute structure */ dev_attr = &ssi_private->dev_attr; + sysfs_attr_init(&dev_attr->attr); dev_attr->attr.name = "statistics"; dev_attr->attr.mode = S_IRUGO; dev_attr->show = fsl_sysfs_ssi_show; -- cgit v1.2.3 From 101e07082f732dfb645ba370b0c0b510e1283f25 Mon Sep 17 00:00:00 2001 From: Timo Juhani Lindfors Date: Thu, 17 Nov 2011 02:52:50 +0200 Subject: ASoC: wm8753: Skip noop reconfiguration of DAI mode commit 2391a0e06789a3f1718dee30b282562f7ed28c87 upstream. This patch makes it possible to set DAI mode to its currently applied value even if codec is active. This is necessary to allow aplay -t raw -r 44100 -f S16_LE -c 2 < /dev/urandom & alsactl store -f backup.state alsactl restore -f backup.state to work without returning errors. This patch is based on a patch sent by Klaus Kurzmann . Signed-off-by: Timo Juhani Lindfors Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8753.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index aa091a0d818..66d18a3e57f 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -189,6 +189,9 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); u16 ioctl; + if (wm8753->dai_func == ucontrol->value.integer.value[0]) + return 0; + if (codec->active) return -EBUSY; -- cgit v1.2.3 From 854b259aa1fbb2f4e63ba02a008f48c36606e73d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Nov 2011 11:55:41 +0000 Subject: ASoC: Ensure WM8731 register cache is synced when resuming from disabled commit ed3e80c4c991a52f9fce3421536a78e331ae0949 upstream. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8731.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 76b4361e9b8..f5a0ec4ade5 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -463,6 +463,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, snd_soc_write(codec, WM8731_PWR, 0xffff); regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); + codec->cache_sync = 1; break; } codec->dapm.bias_level = level; -- cgit v1.2.3 From 453fdf5561cc042b7e127af6a62138969726f539 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 22 Nov 2011 14:44:28 +0200 Subject: SUNRPC: Ensure we return EAGAIN in xs_nospace if congestion is cleared commit 24ca9a847791fd53d9b217330b15f3c285827a18 upstream. By returning '0' instead of 'EAGAIN' when the tests in xs_nospace() fail to find evidence of socket congestion, we are making the RPC engine believe that the message was incorrectly sent and so it disconnects the socket instead of just retrying. The bug appears to have been introduced by commit 5e3771ce2d6a69e10fcc870cdf226d121d868491 (SUNRPC: Ensure that xs_nospace return values are propagated). Reported-by: Andrew Cooper Signed-off-by: Trond Myklebust Tested-by: Andrew Cooper Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtsock.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d7f97ef2659..b60b75082f3 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -496,7 +496,7 @@ static int xs_nospace(struct rpc_task *task) struct rpc_rqst *req = task->tk_rqstp; struct rpc_xprt *xprt = req->rq_xprt; struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); - int ret = 0; + int ret = -EAGAIN; dprintk("RPC: %5u xmit incomplete (%u left of %u)\n", task->tk_pid, req->rq_slen - req->rq_bytes_sent, @@ -508,7 +508,6 @@ static int xs_nospace(struct rpc_task *task) /* Don't race with disconnect */ if (xprt_connected(xprt)) { if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) { - ret = -EAGAIN; /* * Notify TCP that we're limited by the application * window size -- cgit v1.2.3 From 01da30a885baa667801facc2a54c80346ab6c414 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 24 Nov 2011 19:22:24 -0500 Subject: ext4: fix racy use-after-free in ext4_end_io_dio() commit 4c81f045c0bd2cbb78cc6446a4cd98038fe11a2e upstream. ext4_end_io_dio() queues io_end->work and then clears iocb->private; however, io_end->work calls aio_complete() which frees the iocb object. If that slab object gets reallocated, then ext4_end_io_dio() can end up clearing someone else's iocb->private, this use-after-free can cause a leak of a struct ext4_io_end_t structure. Detected and tested with slab poisoning. [ Note: Can also reproduce using 12 fio's against 12 file systems with the following configuration file: [global] direct=1 ioengine=libaio iodepth=1 bs=4k ba=4k size=128m [create] filename=${TESTDIR} rw=write -- tytso ] Google-Bug-Id: 5354697 Signed-off-by: Tejun Heo Signed-off-by: "Theodore Ts'o" Reported-by: Kent Overstreet Tested-by: Kent Overstreet Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 89c47f4ee00..b644b9c164a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2656,8 +2656,8 @@ out: spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); /* queue the work to convert unwritten extents to written */ - queue_work(wq, &io_end->work); iocb->private = NULL; + queue_work(wq, &io_end->work); /* XXX: probably should move into the real I/O completion handler */ inode_dio_done(inode); -- cgit v1.2.3 From 79f1685c82d882192b1e22b3114be78159c54b86 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 28 Nov 2011 10:33:40 +0100 Subject: rtlwifi: fix lps_lock deadlock commit e55b32c110b025ce07b40227f620e99700bf8741 upstream. rtl_lps_leave can be called from interrupt context, so we have to disable interrupts when taking lps_lock. Below is full lockdep info about deadlock: [ 93.815269] ================================= [ 93.815390] [ INFO: inconsistent lock state ] [ 93.815472] 2.6.41.1-3.offch.fc15.x86_64.debug #1 [ 93.815556] --------------------------------- [ 93.815635] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. [ 93.815743] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: [ 93.815832] (&(&rtlpriv->locks.lps_lock)->rlock){+.?...}, at: [] rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.815947] {SOFTIRQ-ON-W} state was registered at: [ 93.815947] [] __lock_acquire+0x369/0xd0c [ 93.815947] [] lock_acquire+0xf3/0x13e [ 93.815947] [] _raw_spin_lock+0x45/0x79 [ 93.815947] [] rtl_swlps_rf_awake+0x5a/0x76 [rtlwifi] [ 93.815947] [] rtl_op_config+0x12a/0x32a [rtlwifi] [ 93.815947] [] ieee80211_hw_config+0x124/0x129 [mac80211] [ 93.815947] [] ieee80211_dynamic_ps_disable_work+0x32/0x47 [mac80211] [ 93.815947] [] process_one_work+0x205/0x3e7 [ 93.815947] [] worker_thread+0xda/0x15d [ 93.815947] [] kthread+0xa8/0xb0 [ 93.815947] [] kernel_thread_helper+0x4/0x10 [ 93.815947] irq event stamp: 547822 [ 93.815947] hardirqs last enabled at (547822): [] _raw_spin_unlock_irqrestore+0x45/0x61 [ 93.815947] hardirqs last disabled at (547821): [] _raw_spin_lock_irqsave+0x22/0x8e [ 93.815947] softirqs last enabled at (547790): [] _local_bh_enable+0x13/0x15 [ 93.815947] softirqs last disabled at (547791): [] call_softirq+0x1c/0x30 [ 93.815947] [ 93.815947] other info that might help us debug this: [ 93.815947] Possible unsafe locking scenario: [ 93.815947] [ 93.815947] CPU0 [ 93.815947] ---- [ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); [ 93.815947] [ 93.815947] lock(&(&rtlpriv->locks.lps_lock)->rlock); [ 93.815947] [ 93.815947] *** DEADLOCK *** [ 93.815947] [ 93.815947] no locks held by swapper/0. [ 93.815947] [ 93.815947] stack backtrace: [ 93.815947] Pid: 0, comm: swapper Not tainted 2.6.41.1-3.offch.fc15.x86_64.debug #1 [ 93.815947] Call Trace: [ 93.815947] [] print_usage_bug+0x1e7/0x1f8 [ 93.815947] [] ? save_stack_trace+0x2c/0x49 [ 93.815947] [] ? print_irq_inversion_bug.part.18+0x1a0/0x1a0 [ 93.815947] [] mark_lock+0x106/0x220 [ 93.815947] [] __lock_acquire+0x2f5/0xd0c [ 93.815947] [] ? native_sched_clock+0x34/0x36 [ 93.830125] [] ? sched_clock+0x9/0xd [ 93.830125] [] ? sched_clock_local+0x12/0x75 [ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.830125] [] lock_acquire+0xf3/0x13e [ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.830125] [] _raw_spin_lock+0x45/0x79 [ 93.830125] [] ? rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.830125] [] ? skb_dequeue+0x62/0x6d [ 93.830125] [] rtl_lps_leave+0x26/0x103 [rtlwifi] [ 93.830125] [] _rtl_pci_ips_leave_tasklet+0xe/0x10 [rtlwifi] [ 93.830125] [] tasklet_action+0x8d/0xee [ 93.830125] [] __do_softirq+0x112/0x25a [ 93.830125] [] call_softirq+0x1c/0x30 [ 93.830125] [] do_softirq+0x4b/0xa1 [ 93.830125] [] irq_exit+0x5d/0xcf [ 93.830125] [] do_IRQ+0x8e/0xa5 [ 93.830125] [] common_interrupt+0x73/0x73 [ 93.830125] [] ? trace_hardirqs_off+0xd/0xf [ 93.830125] [] ? intel_idle+0xe5/0x10c [ 93.830125] [] ? intel_idle+0xe1/0x10c [ 93.830125] [] cpuidle_idle_call+0x11c/0x1fe [ 93.830125] [] cpu_idle+0xab/0x101 [ 93.830125] [] rest_init+0xd7/0xde [ 93.830125] [] ? csum_partial_copy_generic+0x16c/0x16c [ 93.830125] [] start_kernel+0x3dd/0x3ea [ 93.830125] [] x86_64_start_reservations+0xaf/0xb3 [ 93.830125] [] ? early_idt_handlers+0x140/0x140 [ 93.830125] [] x86_64_start_kernel+0x102/0x111 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=755154 Reported-by: vjain02@students.poly.edu Reported-and-tested-by: Oliver Paukstadt Acked-by: Larry Finger Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/ps.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index a693feffbe7..0b04b2e7b59 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -394,7 +394,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) if (mac->link_state != MAC80211_LINKED) return; - spin_lock(&rtlpriv->locks.lps_lock); + spin_lock_irq(&rtlpriv->locks.lps_lock); /* Idle for a while if we connect to AP a while ago. */ if (mac->cnt_after_linked >= 2) { @@ -406,7 +406,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw) } } - spin_unlock(&rtlpriv->locks.lps_lock); + spin_unlock_irq(&rtlpriv->locks.lps_lock); } /*Leave the leisure power save mode.*/ @@ -415,8 +415,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + unsigned long flags; - spin_lock(&rtlpriv->locks.lps_lock); + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags); if (ppsc->fwctrl_lps) { if (ppsc->dot11_psmode != EACTIVE) { @@ -437,7 +438,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw) rtl_lps_set_psmode(hw, EACTIVE); } } - spin_unlock(&rtlpriv->locks.lps_lock); + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags); } /* For sw LPS*/ @@ -538,9 +539,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw) RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); } - spin_lock(&rtlpriv->locks.lps_lock); + spin_lock_irq(&rtlpriv->locks.lps_lock); rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); - spin_unlock(&rtlpriv->locks.lps_lock); + spin_unlock_irq(&rtlpriv->locks.lps_lock); } void rtl_swlps_rfon_wq_callback(void *data) @@ -573,9 +574,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) if (rtlpriv->link_info.busytraffic) return; - spin_lock(&rtlpriv->locks.lps_lock); + spin_lock_irq(&rtlpriv->locks.lps_lock); rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); - spin_unlock(&rtlpriv->locks.lps_lock); + spin_unlock_irq(&rtlpriv->locks.lps_lock); if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { -- cgit v1.2.3 From 4148011316b640f48be6b7dd9005033b5347172c Mon Sep 17 00:00:00 2001 From: Edward Donovan Date: Sun, 27 Nov 2011 23:07:34 -0500 Subject: genirq: fix regression in irqfixup, irqpoll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 52553ddffad76ccf192d4dd9ce88d5818f57f62a upstream. Commit fa27271bc8d2("genirq: Fixup poll handling") introduced a regression that broke irqfixup/irqpoll for some hardware configurations. Amidst reorganizing 'try_one_irq', that patch removed a test that checked for 'action->handler' returning IRQ_HANDLED, before acting on the interrupt. Restoring this test back returns the functionality lost since 2.6.39. In the current set of tests, after 'action' is set, it must precede '!action->next' to take effect. With this and my previous patch to irq/spurious.c, c75d720fca8a, all IRQ regressions that I have encountered are fixed. Signed-off-by: Edward Donovan Reported-and-tested-by: Rogério Brito Cc: Thomas Gleixner Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/irq/spurious.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index b5f4742693c..dc813a948be 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -84,7 +84,9 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) */ action = desc->action; if (!action || !(action->flags & IRQF_SHARED) || - (action->flags & __IRQF_TIMER) || !action->next) + (action->flags & __IRQF_TIMER) || + (action->handler(irq, action->dev_id) == IRQ_HANDLED) || + !action->next) goto out; /* Already running on another processor */ -- cgit v1.2.3 From 13e15d58a10698371a7d10b5dcdf2ce6630c35ef Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 28 Nov 2011 14:06:31 +0800 Subject: regulator: aat2870: Fix the logic of checking if no id is matched in aat2870_get_regulator commit d4d6373c1109b11c8118340be97ae31b8f94d66a upstream. In current implementation, the pointer ri is not NULL if no id is matched. Fix it by checking i == ARRAY_SIZE(aat2870_regulators) if no id is matched. Signed-off-by: Axel Lin Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/aat2870-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index cd4104542f0..11d1ab4abef 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -159,7 +159,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id) break; } - if (!ri) + if (i == ARRAY_SIZE(aat2870_regulators)) return NULL; ri->enable_addr = AAT2870_LDO_EN; -- cgit v1.2.3 From ffdb8ca9bea2170b97edb9372bb365fd387a1ff9 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 28 Nov 2011 16:53:19 +0200 Subject: regulator: twl: fix twl4030 support for smps regulators commit ba305e31e88ea5c2f598ff9fbc5424711a429e30 upstream. SMPS regulator voltage control differs from the one of the LDO ones. Current TWL code was using LDO regulator ops for controlling the SMPS regulators, which fails. This was fixed fixed by adding separate regulator type which uses correct logic and calculations for the voltage levels. Signed-off-by: Tero Kristo Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/twl-regulator.c | 46 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index ee8747f4fa0..11cc308d66e 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -71,6 +71,7 @@ struct twlreg_info { #define VREG_TYPE 1 #define VREG_REMAP 2 #define VREG_DEDICATED 3 /* LDO control */ +#define VREG_VOLTAGE_SMPS_4030 9 /* TWL6030 register offsets */ #define VREG_TRANS 1 #define VREG_STATE 2 @@ -514,6 +515,32 @@ static struct regulator_ops twl4030ldo_ops = { .get_status = twl4030reg_get_status, }; +static int +twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, + unsigned *selector) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel = DIV_ROUND_UP(min_uV - 600000, 12500); + + twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030, + vsel); + return 0; +} + +static int twl4030smps_get_voltage(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, + VREG_VOLTAGE_SMPS_4030); + + return vsel * 12500 + 600000; +} + +static struct regulator_ops twl4030smps_ops = { + .set_voltage = twl4030smps_set_voltage, + .get_voltage = twl4030smps_get_voltage, +}; + static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) { struct twlreg_info *info = rdev_get_drvdata(rdev); @@ -856,6 +883,21 @@ static struct regulator_ops twlsmps_ops = { }, \ } +#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \ + { \ + .base = offset, \ + .id = num, \ + .delay = turnon_delay, \ + .remap = remap_conf, \ + .desc = { \ + .name = #label, \ + .id = TWL4030_REG_##label, \ + .ops = &twl4030smps_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ + } + #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \ .base = offset, \ .min_mV = min_mVolts, \ @@ -947,8 +989,8 @@ static struct twlreg_info twl_regs[] = { TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08), TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08), TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08), - TWL4030_ADJUSTABLE_LDO(VDD1, 0x55, 15, 1000, 0x08), - TWL4030_ADJUSTABLE_LDO(VDD2, 0x63, 16, 1000, 0x08), + TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08), + TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08), TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08), TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08), TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08), -- cgit v1.2.3 From c1d98cbbfc393f166b8a675b3acbdfab320adadc Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Tue, 22 Nov 2011 07:44:47 -0800 Subject: cgroup_freezer: fix freezing groups with stopped tasks commit 884a45d964dd395eda945842afff5e16bcaedf56 upstream. 2d3cbf8b (cgroup_freezer: update_freezer_state() does incorrect state transitions) removed is_task_frozen_enough and replaced it with a simple frozen call. This, however, breaks freezing for a group with stopped tasks because those cannot be frozen and so the group remains in CGROUP_FREEZING state (update_if_frozen doesn't count stopped tasks) and never reaches CGROUP_FROZEN. Let's add is_task_frozen_enough back and use it at the original locations (update_if_frozen and try_to_freeze_cgroup). Semantically we consider stopped tasks as frozen enough so we should consider both cases when testing frozen tasks. Testcase: mkdir /dev/freezer mount -t cgroup -o freezer none /dev/freezer mkdir /dev/freezer/foo sleep 1h & pid=$! kill -STOP $pid echo $pid > /dev/freezer/foo/tasks echo FROZEN > /dev/freezer/foo/freezer.state while true do cat /dev/freezer/foo/freezer.state [ "`cat /dev/freezer/foo/freezer.state`" = "FROZEN" ] && break sleep 1 done echo OK Signed-off-by: Michal Hocko Acked-by: Li Zefan Cc: Tomasz Buchert Cc: Paul Menage Cc: Andrew Morton Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup_freezer.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index e691818d7e4..a3f638ac3de 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c @@ -153,6 +153,13 @@ static void freezer_destroy(struct cgroup_subsys *ss, kfree(cgroup_freezer(cgroup)); } +/* task is frozen or will freeze immediately when next it gets woken */ +static bool is_task_frozen_enough(struct task_struct *task) +{ + return frozen(task) || + (task_is_stopped_or_traced(task) && freezing(task)); +} + /* * The call to cgroup_lock() in the freezer.state write method prevents * a write to that file racing against an attach, and hence the @@ -231,7 +238,7 @@ static void update_if_frozen(struct cgroup *cgroup, cgroup_iter_start(cgroup, &it); while ((task = cgroup_iter_next(cgroup, &it))) { ntotal++; - if (frozen(task)) + if (is_task_frozen_enough(task)) nfrozen++; } @@ -284,7 +291,7 @@ static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) while ((task = cgroup_iter_next(cgroup, &it))) { if (!freeze_task(task, true)) continue; - if (frozen(task)) + if (is_task_frozen_enough(task)) continue; if (!freezing(task) && !freezer_should_skip(task)) num_cant_freeze_now++; -- cgit v1.2.3 From 92ad5083db212ff3c5f6d1d085d85790f7a6c42c Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Mon, 14 Nov 2011 11:15:25 +0100 Subject: timekeeping: add arch_offset hook to ktime_get functions commit d004e024058a0eaca097513ce62cbcf978913e0a upstream. ktime_get and ktime_get_ts were calling timekeeping_get_ns() but later they were not calling arch_gettimeoffset() so architectures using this mechanism returned 0 ns when calling these functions. This happened for example when running Busybox's ping which calls syscall(__NR_clock_gettime, CLOCK_MONOTONIC, ts) which eventually calls ktime_get. As a result the returned ping travel time was zero. Signed-off-by: Hector Palacios Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 2b021b0e850..da4a77815fa 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -249,6 +249,8 @@ ktime_t ktime_get(void) secs = xtime.tv_sec + wall_to_monotonic.tv_sec; nsecs = xtime.tv_nsec + wall_to_monotonic.tv_nsec; nsecs += timekeeping_get_ns(); + /* If arch requires, add in gettimeoffset() */ + nsecs += arch_gettimeoffset(); } while (read_seqretry(&xtime_lock, seq)); /* @@ -280,6 +282,8 @@ void ktime_get_ts(struct timespec *ts) *ts = xtime; tomono = wall_to_monotonic; nsecs = timekeeping_get_ns(); + /* If arch requires, add in gettimeoffset() */ + nsecs += arch_gettimeoffset(); } while (read_seqretry(&xtime_lock, seq)); -- cgit v1.2.3 From eb5f9ebf61f88796a19df09751762b9e086a5214 Mon Sep 17 00:00:00 2001 From: Jeff Ohlstein Date: Fri, 18 Nov 2011 15:47:10 -0800 Subject: hrtimer: Fix extra wakeups from __remove_hrtimer() commit 27c9cd7e601632b3794e1c3344d37b86917ffb43 upstream. __remove_hrtimer() attempts to reprogram the clockevent device when the timer being removed is the next to expire. However, __remove_hrtimer() reprograms the clockevent *before* removing the timer from the timerqueue and thus when hrtimer_force_reprogram() finds the next timer to expire it finds the timer we're trying to remove. This is especially noticeable when the system switches to NOHz mode and the system tick is removed. The timer tick is removed from the system but the clockevent is programmed to wakeup in another HZ anyway. Silence the extra wakeup by removing the timer from the timerqueue before calling hrtimer_force_reprogram() so that we actually program the clockevent for the next timer to expire. This was broken by 998adc3 "hrtimers: Convert hrtimers to use timerlist infrastructure". Signed-off-by: Jeff Ohlstein Link: http://lkml.kernel.org/r/1321660030-8520-1-git-send-email-johlstei@codeaurora.org Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/hrtimer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index a9205e32a05..2043c08d36c 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -885,10 +885,13 @@ static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, unsigned long newstate, int reprogram) { + struct timerqueue_node *next_timer; if (!(timer->state & HRTIMER_STATE_ENQUEUED)) goto out; - if (&timer->node == timerqueue_getnext(&base->active)) { + next_timer = timerqueue_getnext(&base->active); + timerqueue_del(&base->active, &timer->node); + if (&timer->node == next_timer) { #ifdef CONFIG_HIGH_RES_TIMERS /* Reprogram the clock event device. if enabled */ if (reprogram && hrtimer_hres_active()) { @@ -901,7 +904,6 @@ static void __remove_hrtimer(struct hrtimer *timer, } #endif } - timerqueue_del(&base->active, &timer->node); if (!timerqueue_getnext(&base->active)) base->cpu_base->active_bases &= ~(1 << base->index); out: -- cgit v1.2.3 From be80893d309e256fe05a1e55d440bd6188ba2748 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 31 Oct 2011 17:06:35 -0400 Subject: clocksource: Avoid selecting mult values that might overflow when adjusted commit d65670a78cdbfae94f20a9e05ec705871d7cdf2b upstream. For some frequencies, the clocks_calc_mult_shift() function will unfortunately select mult values very close to 0xffffffff. This has the potential to overflow when NTP adjusts the clock, adding to the mult value. This patch adds a clocksource.maxadj value, which provides an approximation of an 11% adjustment(NTP limits adjustments to 500ppm and the tick adjustment is limited to 10%), which could be made to the clocksource.mult value. This is then used to both check that the current mult value won't overflow/underflow, as well as warning us if the timekeeping_adjust() code pushes over that 11% boundary. v2: Fix max_adjustment calculation, and improve WARN_ONCE messages. v3: Don't warn before maxadj has actually been set CC: Yong Zhang CC: David Daney CC: Thomas Gleixner CC: Chen Jie CC: zhangfx Reported-by: Chen Jie Reported-by: zhangfx Tested-by: Yong Zhang Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- include/linux/clocksource.h | 3 ++- kernel/time/clocksource.c | 58 +++++++++++++++++++++++++++++++++++++-------- kernel/time/timekeeping.c | 7 ++++++ 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 139c4db55f1..c86c940d1de 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -156,6 +156,7 @@ extern u64 timecounter_cyc2time(struct timecounter *tc, * @mult: cycle to nanosecond multiplier * @shift: cycle to nanosecond divisor (power of two) * @max_idle_ns: max idle time permitted by the clocksource (nsecs) + * @maxadj maximum adjustment value to mult (~11%) * @flags: flags describing special properties * @archdata: arch-specific data * @suspend: suspend function for the clocksource, if necessary @@ -172,7 +173,7 @@ struct clocksource { u32 mult; u32 shift; u64 max_idle_ns; - + u32 maxadj; #ifdef CONFIG_ARCH_CLOCKSOURCE_DATA struct arch_clocksource_data archdata; #endif diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index e0980f0d9a0..8277439b004 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -493,6 +493,22 @@ void clocksource_touch_watchdog(void) clocksource_resume_watchdog(); } +/** + * clocksource_max_adjustment- Returns max adjustment amount + * @cs: Pointer to clocksource + * + */ +static u32 clocksource_max_adjustment(struct clocksource *cs) +{ + u64 ret; + /* + * We won't try to correct for more then 11% adjustments (110,000 ppm), + */ + ret = (u64)cs->mult * 11; + do_div(ret,100); + return (u32)ret; +} + /** * clocksource_max_deferment - Returns max time the clocksource can be deferred * @cs: Pointer to clocksource @@ -505,25 +521,28 @@ static u64 clocksource_max_deferment(struct clocksource *cs) /* * Calculate the maximum number of cycles that we can pass to the * cyc2ns function without overflowing a 64-bit signed result. The - * maximum number of cycles is equal to ULLONG_MAX/cs->mult which - * is equivalent to the below. - * max_cycles < (2^63)/cs->mult - * max_cycles < 2^(log2((2^63)/cs->mult)) - * max_cycles < 2^(log2(2^63) - log2(cs->mult)) - * max_cycles < 2^(63 - log2(cs->mult)) - * max_cycles < 1 << (63 - log2(cs->mult)) + * maximum number of cycles is equal to ULLONG_MAX/(cs->mult+cs->maxadj) + * which is equivalent to the below. + * max_cycles < (2^63)/(cs->mult + cs->maxadj) + * max_cycles < 2^(log2((2^63)/(cs->mult + cs->maxadj))) + * max_cycles < 2^(log2(2^63) - log2(cs->mult + cs->maxadj)) + * max_cycles < 2^(63 - log2(cs->mult + cs->maxadj)) + * max_cycles < 1 << (63 - log2(cs->mult + cs->maxadj)) * Please note that we add 1 to the result of the log2 to account for * any rounding errors, ensure the above inequality is satisfied and * no overflow will occur. */ - max_cycles = 1ULL << (63 - (ilog2(cs->mult) + 1)); + max_cycles = 1ULL << (63 - (ilog2(cs->mult + cs->maxadj) + 1)); /* * The actual maximum number of cycles we can defer the clocksource is * determined by the minimum of max_cycles and cs->mask. + * Note: Here we subtract the maxadj to make sure we don't sleep for + * too long if there's a large negative adjustment. */ max_cycles = min_t(u64, max_cycles, (u64) cs->mask); - max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult, cs->shift); + max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult - cs->maxadj, + cs->shift); /* * To ensure that the clocksource does not wrap whilst we are idle, @@ -642,7 +661,6 @@ static void clocksource_enqueue(struct clocksource *cs) void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) { u64 sec; - /* * Calc the maximum number of seconds which we can run before * wrapping around. For clocksources which have a mask > 32bit @@ -663,6 +681,20 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) clocks_calc_mult_shift(&cs->mult, &cs->shift, freq, NSEC_PER_SEC / scale, sec * scale); + + /* + * for clocksources that have large mults, to avoid overflow. + * Since mult may be adjusted by ntp, add an safety extra margin + * + */ + cs->maxadj = clocksource_max_adjustment(cs); + while ((cs->mult + cs->maxadj < cs->mult) + || (cs->mult - cs->maxadj > cs->mult)) { + cs->mult >>= 1; + cs->shift--; + cs->maxadj = clocksource_max_adjustment(cs); + } + cs->max_idle_ns = clocksource_max_deferment(cs); } EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale); @@ -703,6 +735,12 @@ EXPORT_SYMBOL_GPL(__clocksource_register_scale); */ int clocksource_register(struct clocksource *cs) { + /* calculate max adjustment for given mult/shift */ + cs->maxadj = clocksource_max_adjustment(cs); + WARN_ONCE(cs->mult + cs->maxadj < cs->mult, + "Clocksource %s might overflow on 11%% adjustment\n", + cs->name); + /* calculate max idle time permitted for this clocksource */ cs->max_idle_ns = clocksource_max_deferment(cs); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index da4a77815fa..6f9798bf240 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -824,6 +824,13 @@ static void timekeeping_adjust(s64 offset) } else return; + WARN_ONCE(timekeeper.clock->maxadj && + (timekeeper.mult + adj > timekeeper.clock->mult + + timekeeper.clock->maxadj), + "Adjusting %s more then 11%% (%ld vs %ld)\n", + timekeeper.clock->name, (long)timekeeper.mult + adj, + (long)timekeeper.clock->mult + + timekeeper.clock->maxadj); timekeeper.mult += adj; timekeeper.xtime_interval += interval; timekeeper.xtime_nsec -= offset; -- cgit v1.2.3 From 3dcc2d249f99606863f00635e2becf95a389dc9c Mon Sep 17 00:00:00 2001 From: Michael Büsch Date: Wed, 16 Nov 2011 23:48:31 +0100 Subject: p54spi: Add missing spin_lock_init commit 32d3a3922d617a5a685a5e2d24b20d0e88f192a9 upstream. The tx_lock is not initialized properly. Add spin_lock_init(). Signed-off-by: Michael Buesch Acked-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/p54/p54spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 6d9204fef90..72ec212e482 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -657,6 +657,7 @@ static int __devinit p54spi_probe(struct spi_device *spi) init_completion(&priv->fw_comp); INIT_LIST_HEAD(&priv->tx_pending); mutex_init(&priv->mutex); + spin_lock_init(&priv->tx_lock); SET_IEEE80211_DEV(hw, &spi->dev); priv->common.open = p54spi_op_start; priv->common.stop = p54spi_op_stop; -- cgit v1.2.3 From 160b68b38d29c8ab41eeb8187b2d724bf69c6756 Mon Sep 17 00:00:00 2001 From: Michael Büsch Date: Wed, 16 Nov 2011 23:55:46 +0100 Subject: p54spi: Fix workqueue deadlock commit 2d1618170eb493d18f66f2ac03775409a6fb97c6 upstream. priv->work must not be synced while priv->mutex is locked, because the mutex is taken in the work handler. Move cancel_work_sync down to after the device shutdown code. This is safe, because the work handler checks fw_state and bails out early in case of a race. Signed-off-by: Michael Buesch Acked-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/p54/p54spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 72ec212e482..b33ceb1c066 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -589,8 +589,6 @@ static void p54spi_op_stop(struct ieee80211_hw *dev) WARN_ON(priv->fw_state != FW_STATE_READY); - cancel_work_sync(&priv->work); - p54spi_power_off(priv); spin_lock_irqsave(&priv->tx_lock, flags); INIT_LIST_HEAD(&priv->tx_pending); @@ -598,6 +596,8 @@ static void p54spi_op_stop(struct ieee80211_hw *dev) priv->fw_state = FW_STATE_OFF; mutex_unlock(&priv->mutex); + + cancel_work_sync(&priv->work); } static int __devinit p54spi_probe(struct spi_device *spi) -- cgit v1.2.3 From 7ca622f2e52f3161466ebe93e177fb64c6047dc9 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 16 Nov 2011 23:16:15 +0100 Subject: rt2x00: Fix efuse EEPROM reading on PPC32. commit 68fa64ef606bcee688fce46d07aa68f175070156 upstream. Fix __le32 to __le16 conversion of the first word of an 8-word block of EEPROM read via the efuse method. Reported-and-tested-by: Ingvar Hagelund Signed-off-by: Gertjan van Wingerde Acked-by: Helmut Schaa Acked-by: Ivo van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 0019dfd8fb0..c6ad97f6daa 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3699,7 +3699,7 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i) /* Apparently the data is read from end to start */ rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, ®); /* The returned value is in CPU order, but eeprom is le */ - rt2x00dev->eeprom[i] = cpu_to_le32(reg); + *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg); rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, ®); *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, ®); -- cgit v1.2.3 From 5c76953157d60ee044e23c9050347dd3405a2338 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 24 Nov 2011 18:13:56 +0200 Subject: nl80211: fix MAC address validation commit e007b857e88097c96c45620bf3b04a4e309053d1 upstream. MAC addresses have a fixed length. The current policy allows passing < ETH_ALEN bytes, which might result in reading beyond the buffer. Signed-off-by: Eliad Peller Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/nl80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1308050f399..a5c132045ba 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -83,8 +83,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, - [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, - [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN }, + [NL80211_ATTR_MAC] = { .len = ETH_ALEN }, + [NL80211_ATTR_PREV_BSSID] = { .len = ETH_ALEN }, [NL80211_ATTR_KEY] = { .type = NLA_NESTED, }, [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, -- cgit v1.2.3 From 737df45ddfbd5f96a9b38a16d5eef9eb7cd3a9a0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 21 Nov 2011 10:44:00 +0100 Subject: cfg80211: fix regulatory NULL dereference commit de3584bd62d87b4c250129fbc46ca52c80330add upstream. By the time userspace returns with a response to the regulatory domain request, the wiphy causing the request might have gone away. If this is so, reject the update but mark the request as having been processed anyway. Cc: Luis R. Rodriguez Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/reg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1658effdbee..1731e4bbfbc 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2026,6 +2026,10 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) } request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); + if (!request_wiphy) { + reg_set_request_processed(); + return -ENODEV; + } if (!last_request->intersect) { int r; -- cgit v1.2.3 From 743646bb5669b390e18a7d1f45ab5db8db48e09d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 24 Nov 2011 20:06:14 +0100 Subject: mac80211: don't stop a single aggregation session twice commit 24f50a9d165745fd0701c6e089d35f58a229ea69 upstream. Nikolay noticed (by code review) that mac80211 can attempt to stop an aggregation session while it is already being stopped. So to fix it, check whether stop is already being done and bail out if so. Also move setting the STOPPING state into the lock so things are properly atomic. Reported-by: Nikolay Martynov Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/agg-tx.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index c8be8eff70d..23418753a4d 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -162,6 +162,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, return -ENOENT; } + /* if we're already stopping ignore any new requests to stop */ + if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { + spin_unlock_bh(&sta->lock); + return -EALREADY; + } + if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { /* not even started yet! */ ieee80211_assign_tid_tx(sta, tid, NULL); @@ -170,6 +176,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, return 0; } + set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); + spin_unlock_bh(&sta->lock); #ifdef CONFIG_MAC80211_HT_DEBUG @@ -177,8 +185,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, sta->sta.addr, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); - del_timer_sync(&tid_tx->addba_resp_timer); /* -- cgit v1.2.3 From f06b70aa96019273ed984f76c79ad786ac216f7e Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 27 Nov 2011 15:29:44 +0200 Subject: mac80211: fix race between the AGG SM and the Tx data path commit 2a1e0fd175dcfd72096ba9291d31e3b1b5342e60 upstream. When a packet is supposed to sent be as an a-MPDU, mac80211 sets IEEE80211_TX_CTL_AMPDU to let the driver know. On the other hand, mac80211 configures the driver for aggregration with the ampdu_action callback. There is race between these two mechanisms since the following scenario can occur when the BA agreement is torn down: Tx softIRQ drv configuration ========== ================= check OPERATIONAL bit Set the TX_CTL_AMPDU bit in the packet clear OPERATIONAL bit stop Tx AGG Pass Tx packet to the driver. In that case the driver would get a packet with TX_CTL_AMPDU set although it has already been notified that the BA session has been torn down. To fix this, we need to synchronize all the Qdisc activity after we cleared the OPERATIONAL bit. After that step, all the following packets will be buffered until the driver reports it is ready to get new packets for this RA / TID. This buffering allows not to run into another race that would send packets with TX_CTL_AMPDU unset while the driver hasn't been requested to tear down the BA session yet. This race occurs in practice and iwlwifi complains with a WARN_ON when it happens. Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/agg-tx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 23418753a4d..42a59c260e8 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -194,6 +194,20 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, */ clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); + /* + * There might be a few packets being processed right now (on + * another CPU) that have already gotten past the aggregation + * check when it was still OPERATIONAL and consequently have + * IEEE80211_TX_CTL_AMPDU set. In that case, this code might + * call into the driver at the same time or even before the + * TX paths calls into it, which could confuse the driver. + * + * Wait for all currently running TX paths to finish before + * telling the driver. New packets will not go through since + * the aggregation session is no longer OPERATIONAL. + */ + synchronize_net(); + tid_tx->stop_initiator = initiator; tid_tx->tx_stop = tx; -- cgit v1.2.3 From 686da49e5aa50117d8d824c579c3fd9e0318fbc6 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 1 Dec 2011 17:27:39 -0600 Subject: xfs: don't serialise direct IO reads on page cache checks commit 0c38a2512df272b14ef4238b476a2e4f70da1479 upstream. There is no need to grab the i_mutex of the IO lock in exclusive mode if we don't need to invalidate the page cache. Taking these locks on every direct IO effective serialises them as taking the IO lock in exclusive mode has to wait for all shared holders to drop the lock. That only happens when IO is complete, so effective it prevents dispatch of concurrent direct IO reads to the same inode. Fix this by taking the IO lock shared to check the page cache state, and only then drop it and take the IO lock exclusively if there is work to be done. Hence for the normal direct IO case, no exclusive locking will occur. Signed-off-by: Dave Chinner Tested-by: Joern Engel Reviewed-by: Christoph Hellwig Signed-off-by: Alex Elder Cc: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_file.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 7f7b42469ea..8fd4a0708d3 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -317,7 +317,19 @@ xfs_file_aio_read( if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; - if (unlikely(ioflags & IO_ISDIRECT)) { + /* + * Locking is a bit tricky here. If we take an exclusive lock + * for direct IO, we effectively serialise all new concurrent + * read IO to this file and block it behind IO that is currently in + * progress because IO in progress holds the IO lock shared. We only + * need to hold the lock exclusive to blow away the page cache, so + * only take lock exclusively if the page cache needs invalidation. + * This allows the normal direct IO case of no page cache pages to + * proceeed concurrently without serialisation. + */ + xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); + if ((ioflags & IO_ISDIRECT) && inode->i_mapping->nrpages) { + xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); if (inode->i_mapping->nrpages) { @@ -330,8 +342,7 @@ xfs_file_aio_read( } } xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); - } else - xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); + } trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags); -- cgit v1.2.3 From 6a426248da83e544995fc8a494630285260ec4ee Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 1 Dec 2011 17:27:40 -0600 Subject: xfs: avoid direct I/O write vs buffered I/O race commit c58cb165bd44de8aaee9755a144136ae743be116 upstream. Currently a buffered reader or writer can add pages to the pagecache while we are waiting for the iolock in xfs_file_dio_aio_write. Prevent this by re-checking mapping->nrpages after we got the iolock, and if nessecary upgrade the lock to exclusive mode. To simplify this a bit only take the ilock inside of xfs_file_aio_write_checks. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder Cc: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_file.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 8fd4a0708d3..b7e75c6ba09 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -677,6 +677,7 @@ xfs_file_aio_write_checks( xfs_fsize_t new_size; int error = 0; + xfs_rw_ilock(ip, XFS_ILOCK_EXCL); error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode)); if (error) { xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock); @@ -768,14 +769,24 @@ xfs_file_dio_aio_write( *iolock = XFS_IOLOCK_EXCL; else *iolock = XFS_IOLOCK_SHARED; - xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); + xfs_rw_ilock(ip, *iolock); ret = xfs_file_aio_write_checks(file, &pos, &count, iolock); if (ret) return ret; + /* + * Recheck if there are cached pages that need invalidate after we got + * the iolock to protect against other threads adding new pages while + * we were waiting for the iolock. + */ + if (mapping->nrpages && *iolock == XFS_IOLOCK_SHARED) { + xfs_rw_iunlock(ip, *iolock); + *iolock = XFS_IOLOCK_EXCL; + xfs_rw_ilock(ip, *iolock); + } + if (mapping->nrpages) { - WARN_ON(*iolock != XFS_IOLOCK_EXCL); ret = -xfs_flushinval_pages(ip, (pos & PAGE_CACHE_MASK), -1, FI_REMAPF_LOCKED); if (ret) @@ -820,7 +831,7 @@ xfs_file_buffered_aio_write( size_t count = ocount; *iolock = XFS_IOLOCK_EXCL; - xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); + xfs_rw_ilock(ip, *iolock); ret = xfs_file_aio_write_checks(file, &pos, &count, iolock); if (ret) -- cgit v1.2.3 From b4dd4c13166d1aab0c2cd8033f1cc1211f6f1678 Mon Sep 17 00:00:00 2001 From: Mitsuo Hayasaka Date: Thu, 1 Dec 2011 17:27:41 -0600 Subject: xfs: Return -EIO when xfs_vn_getattr() failed commit ed32201e65e15f3e6955cb84cbb544b08f81e5a5 upstream. An attribute of inode can be fetched via xfs_vn_getattr() in XFS. Currently it returns EIO, not negative value, when it failed. As a result, the system call returns not negative value even though an error occured. The stat(2), ls and mv commands cannot handle this error and do not work correctly. This patch fixes this bug, and returns -EIO, not EIO when an error is detected in xfs_vn_getattr(). Signed-off-by: Mitsuo Hayasaka Reviewed-by: Christoph Hellwig Signed-off-by: Alex Elder Cc: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 673704fab74..474920b4655 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -465,7 +465,7 @@ xfs_vn_getattr( trace_xfs_getattr(ip); if (XFS_FORCED_SHUTDOWN(mp)) - return XFS_ERROR(EIO); + return -XFS_ERROR(EIO); stat->size = XFS_ISIZE(ip); stat->dev = inode->i_sb->s_dev; -- cgit v1.2.3 From 7f9fae139e1b34b0ecb0ff8ab051c4497d68db2c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 1 Dec 2011 17:27:42 -0600 Subject: xfs: fix buffer flushing during unmount commit 87c7bec7fc3377b3873eb3a0f4b603981ea16ebb upstream. The code to flush buffers in the umount code is a bit iffy: we first flush all delwri buffers out, but then might be able to queue up a new one when logging the sb counts. On a normal shutdown that one would get flushed out when doing the synchronous superblock write in xfs_unmountfs_writesb, but we skip that one if the filesystem has been shut down. Fix this by moving the delwri list flushing until just before unmounting the log, and while we're at it also remove the superflous delwri list and buffer lru flusing for the rt and log device that can never have cached or delwri buffers. Signed-off-by: Christoph Hellwig Reported-by: Amit Sahrawat Tested-by: Amit Sahrawat Signed-off-by: Alex Elder Cc: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_buf.h | 1 - fs/xfs/xfs_mount.c | 29 ++++++++++------------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 620972b8094..8e8b06b90b6 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -320,7 +320,6 @@ extern struct list_head *xfs_get_buftarg_list(void); #define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev) #define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev) -#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg, 1) #define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg, 1) #endif /* __XFS_BUF_H__ */ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 0081657ad98..d4d5775d6e2 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -44,9 +44,6 @@ #include "xfs_trace.h" -STATIC void xfs_unmountfs_wait(xfs_mount_t *); - - #ifdef HAVE_PERCPU_SB STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, int); @@ -1496,11 +1493,6 @@ xfs_unmountfs( */ xfs_log_force(mp, XFS_LOG_SYNC); - xfs_binval(mp->m_ddev_targp); - if (mp->m_rtdev_targp) { - xfs_binval(mp->m_rtdev_targp); - } - /* * Unreserve any blocks we have so that when we unmount we don't account * the reserved free space as used. This is really only necessary for @@ -1526,7 +1518,16 @@ xfs_unmountfs( xfs_warn(mp, "Unable to update superblock counters. " "Freespace may not be correct on next mount."); xfs_unmountfs_writesb(mp); - xfs_unmountfs_wait(mp); /* wait for async bufs */ + + /* + * Make sure all buffers have been flushed and completed before + * unmounting the log. + */ + error = xfs_flush_buftarg(mp->m_ddev_targp, 1); + if (error) + xfs_warn(mp, "%d busy buffers during unmount.", error); + xfs_wait_buftarg(mp->m_ddev_targp); + xfs_log_unmount_write(mp); xfs_log_unmount(mp); xfs_uuid_unmount(mp); @@ -1537,16 +1538,6 @@ xfs_unmountfs( xfs_free_perag(mp); } -STATIC void -xfs_unmountfs_wait(xfs_mount_t *mp) -{ - if (mp->m_logdev_targp != mp->m_ddev_targp) - xfs_wait_buftarg(mp->m_logdev_targp); - if (mp->m_rtdev_targp) - xfs_wait_buftarg(mp->m_rtdev_targp); - xfs_wait_buftarg(mp->m_ddev_targp); -} - int xfs_fs_writable(xfs_mount_t *mp) { -- cgit v1.2.3 From c38aeb8cd119fddc37d7cd648d6c43e782711247 Mon Sep 17 00:00:00 2001 From: Carlos Maiolino Date: Thu, 1 Dec 2011 17:27:43 -0600 Subject: xfs: Fix possible memory corruption in xfs_readlink commit b52a360b2aa1c59ba9970fb0f52bbb093fcc7a24 upstream. Fixes a possible memory corruption when the link is larger than MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the S_ISLNK assert, since the inode mode is checked previously in xfs_readlink_by_handle() and via VFS. Updated to address concerns raised by Ben Hutchings about the loose attention paid to 32- vs 64-bit values, and the lack of handling a potentially negative pathlen value: - Changed type of "pathlen" to be xfs_fsize_t, to match that of ip->i_d.di_size - Added checking for a negative pathlen to the too-long pathlen test, and generalized the message that gets reported in that case to reflect the change As a result, if a negative pathlen were encountered, this function would return EFSCORRUPTED (and would fail an assertion for a debug build)--just as would a too-long pathlen. Signed-off-by: Alex Elder Signed-off-by: Carlos Maiolino Reviewed-by: Christoph Hellwig Cc: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_vnodeops.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 51fc429527b..b9e28730bbd 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -113,7 +113,7 @@ xfs_readlink( char *link) { xfs_mount_t *mp = ip->i_mount; - int pathlen; + xfs_fsize_t pathlen; int error = 0; trace_xfs_readlink(ip); @@ -123,13 +123,19 @@ xfs_readlink( xfs_ilock(ip, XFS_ILOCK_SHARED); - ASSERT(S_ISLNK(ip->i_d.di_mode)); - ASSERT(ip->i_d.di_size <= MAXPATHLEN); - pathlen = ip->i_d.di_size; if (!pathlen) goto out; + if (pathlen < 0 || pathlen > MAXPATHLEN) { + xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)", + __func__, (unsigned long long) ip->i_ino, + (long long) pathlen); + ASSERT(0); + return XFS_ERROR(EFSCORRUPTED); + } + + if (ip->i_df.if_flags & XFS_IFINLINE) { memcpy(link, ip->i_df.if_u1.if_data, pathlen); link[pathlen] = '\0'; -- cgit v1.2.3 From 5635019b754fa0ccfc2275369b05142a8a2dbde4 Mon Sep 17 00:00:00 2001 From: Mitsuo Hayasaka Date: Thu, 1 Dec 2011 17:27:44 -0600 Subject: xfs: use doalloc flag in xfs_qm_dqattach_one() commit db3e74b582915d66e10b0c73a62763418f54c340 upstream. The doalloc arg in xfs_qm_dqattach_one() is a flag that indicates whether a new area to handle quota information will be allocated if needed. Originally, it was passed to xfs_qm_dqget(), but has been removed by the following commit (probably by mistake): commit 8e9b6e7fa4544ea8a0e030c8987b918509c8ff47 Author: Christoph Hellwig Date: Sun Feb 8 21:51:42 2009 +0100 xfs: remove the unused XFS_QMOPT_DQLOCK flag As the result, xfs_qm_dqget() called from xfs_qm_dqattach_one() never allocates the new area even if it is needed. This patch gives the doalloc arg to xfs_qm_dqget() in xfs_qm_dqattach_one() to fix this problem. Signed-off-by: Mitsuo Hayasaka Cc: Alex Elder Cc: Christoph Hellwig Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers Signed-off-by: Greg Kroah-Hartman --- fs/xfs/xfs_qm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 9a0aa76facd..95ba6dc885a 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -674,7 +674,8 @@ xfs_qm_dqattach_one( * disk and we didn't ask it to allocate; * ESRCH if quotas got turned off suddenly. */ - error = xfs_qm_dqget(ip->i_mount, ip, id, type, XFS_QMOPT_DOWARN, &dqp); + error = xfs_qm_dqget(ip->i_mount, ip, id, type, + doalloc | XFS_QMOPT_DOWARN, &dqp); if (error) return error; -- cgit v1.2.3 From 6d10c223ab5a75fa961019fa91fc811128cb876b Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 9 Nov 2011 08:39:24 +0100 Subject: SCSI: Silencing 'killing requests for dead queue' commit 745718132c3c7cac98a622b610e239dcd5217f71 upstream. When we tear down a device we try to flush all outstanding commands in scsi_free_queue(). However the check in scsi_request_fn() is imperfect as it only signals that we _might start_ aborting commands, not that we've actually aborted some. So move the printk inside the scsi_kill_request function, this will also give us a hint about which commands are aborted. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley Cc: Christoph Biedl Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b4d43ae7613..6d219e48d62 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1408,6 +1408,8 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) blk_start_request(req); + scmd_printk(KERN_INFO, cmd, "killing request\n"); + sdev = cmd->device; starget = scsi_target(sdev); shost = sdev->host; @@ -1489,7 +1491,6 @@ static void scsi_request_fn(struct request_queue *q) struct request *req; if (!sdev) { - printk("scsi: killing requests for dead queue\n"); while ((req = blk_peek_request(q)) != NULL) scsi_kill_request(req, q); return; -- cgit v1.2.3 From d3b2937da9fc51f48ae77735e78be53a8a4c0ae4 Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 15 Nov 2011 14:36:12 -0800 Subject: hugetlb: release pages in the error path of hugetlb_cow() commit ea4039a34c4c206d015d34a49d0b00868e37db1d upstream. If we fail to prepare an anon_vma, the {new, old}_page should be released, or they will leak. Signed-off-by: Hillf Danton Reviewed-by: Andrea Arcangeli Cc: Hugh Dickins Cc: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Michal Hocko Signed-off-by: Greg Kroah-Hartman --- mm/hugetlb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index dae27ba3be2..bb28a5f9db8 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2422,6 +2422,8 @@ retry_avoidcopy: * anon_vma prepared. */ if (unlikely(anon_vma_prepare(vma))) { + page_cache_release(new_page); + page_cache_release(old_page); /* Caller expects lock to be held */ spin_lock(&mm->page_table_lock); return VM_FAULT_OOM; -- cgit v1.2.3 From c66d16e59ba46314e8870e7abc3e1a0f935215e9 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 15 Nov 2011 08:09:14 +0000 Subject: bridge: correct IPv6 checksum after pull commit fa2da8cdae1dd64f78fc915ca1d1a4a93c71e7cb upstream. Bridge multicast snooping of ICMPv6 would incorrectly report a checksum problem when used with Ethernet devices like sky2 that use CHECKSUM_COMPLETE. When bytes are removed from skb, the computed checksum needs to be adjusted. Signed-off-by: Stephen Hemminger Tested-by: Martin Volf Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/bridge/br_multicast.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 995cbe0ac0b..e79ff75b0e7 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1501,6 +1501,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, __skb_pull(skb2, offset); skb_reset_transport_header(skb2); + skb_postpull_rcsum(skb2, skb_network_header(skb2), + skb_network_header_len(skb2)); icmp6_type = icmp6_hdr(skb2)->icmp6_type; -- cgit v1.2.3 From d22ac9ac4c241c598fba39c0f9a7dea3163e1e44 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 27 Oct 2011 17:19:39 -0700 Subject: iwlwifi: allow pci_enable_msi fail commit 8a39ef8ba0fa0410d71db8e981e887fe4fdeca88 upstream. Continue the init process even fail to enable msi out_iounmap is no longer used, remove it Reported-by: werner Tested-by: werner Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-pci.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 2fdbffa079c..32d64e71861 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -442,10 +442,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); err = pci_enable_msi(pdev); - if (err) { - dev_printk(KERN_ERR, &pdev->dev, "pci_enable_msi failed"); - goto out_iounmap; - } + if (err) + dev_printk(KERN_ERR, &pdev->dev, + "pci_enable_msi failed(0X%x)", err); /* TODO: Move this away, not needed if not MSI */ /* enable rfkill interrupt: hw bug w/a */ @@ -466,7 +465,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) out_disable_msi: pci_disable_msi(pdev); -out_iounmap: pci_iounmap(pdev, pci_bus->hw_base); out_pci_release_regions: pci_set_drvdata(pdev, NULL); -- cgit v1.2.3 From 296573cf874d5d78314c5635de35caec372309bd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 1 Dec 2011 11:02:11 -0500 Subject: drm/radeon/kms: add some new pci ids commit 2ed4d9d648cbd4fb1c232a646dbdbdfdd373ca94 upstream. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- include/drm/drm_pciids.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index f81676f1b31..4e4fbb820e2 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -197,6 +197,14 @@ {0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6842, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6843, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6849, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ -- cgit v1.2.3 From 558238140c9a86bd62b9a1146f0439e28d793215 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 28 Nov 2011 14:49:26 -0500 Subject: drm/radeon/kms: add some loop timeouts in pageflip code commit f64964796dedca340608fb1075ab6baad5625851 upstream. Avoid infinite loops waiting for surface updates if a GPU reset happens while waiting for a page flip. See: https://bugs.freedesktop.org/show_bug.cgi?id=43191 Signed-off-by: Alex Deucher Reviewed-by: Mario Kleiner Tested-by: Simon Farnsworth Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/evergreen.c | 7 ++++++- drivers/gpu/drm/radeon/r100.c | 7 ++++++- drivers/gpu/drm/radeon/rs600.c | 7 ++++++- drivers/gpu/drm/radeon/rv770.c | 7 ++++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index fb0a00a3e86..d4ee6f0d3c7 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -82,6 +82,7 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); + int i; /* Lock the graphics update lock */ tmp |= EVERGREEN_GRPH_UPDATE_LOCK; @@ -99,7 +100,11 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) (u32)crtc_base); /* Wait for update_pending to go high. */ - while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) + break; + udelay(1); + } DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index c9a0dae481f..b94d871487e 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -84,13 +84,18 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; + int i; /* Lock the graphics update lock */ /* update the scanout addresses */ WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); /* Wait for update_pending to go high. */ - while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) + break; + udelay(1); + } DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 29d85cf7fbb..0e89a9b885e 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -62,6 +62,7 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); + int i; /* Lock the graphics update lock */ tmp |= AVIVO_D1GRPH_UPDATE_LOCK; @@ -74,7 +75,11 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) (u32)crtc_base); /* Wait for update_pending to go high. */ - while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) + break; + udelay(1); + } DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index b13c2eedc32..ddc206a1f61 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -47,6 +47,7 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); + int i; /* Lock the graphics update lock */ tmp |= AVIVO_D1GRPH_UPDATE_LOCK; @@ -66,7 +67,11 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) (u32)crtc_base); /* Wait for update_pending to go high. */ - while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) + break; + udelay(1); + } DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ -- cgit v1.2.3 From 1db3bb31add93148b1a7ae35d02bff41d9357e9c Mon Sep 17 00:00:00 2001 From: Charles Chin Date: Thu, 1 Dec 2011 11:21:00 +0100 Subject: ALSA: hda - Fix S3/S4 problem on machines with VREF-pin mute-LED commit 88d686027bb43f585914c77dd363f6e817b42c2a upstream. The verb command in stac92xx_post_suspend caused the audio to stop working after resuming from S3 mode on HP laptops with the VREF-pin mute-LED control. Removing relevant post_suspend registering. Although removing D3 on AFG is no optimal solution, the impact should be small in comparison with the broken S3/S4. Signed-off-by: Charles Chin Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_sigmatel.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7ed90113c33..4538caa1fca 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5035,20 +5035,6 @@ static int stac92xx_pre_resume(struct hda_codec *codec) return 0; } -static int stac92xx_post_suspend(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - if (spec->gpio_led > 8) { - /* with vref-out pin used for mute led control - * codec AFG is prevented from D3 state, but on - * system suspend it can (and should) be used - */ - snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - } - return 0; -} - static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state) { @@ -5655,8 +5641,6 @@ again: } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; - codec->patch_ops.post_suspend = - stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = @@ -5978,8 +5962,6 @@ again: } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; - codec->patch_ops.post_suspend = - stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = -- cgit v1.2.3 From adc771853323bb695e50eab52299b82d675cd665 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 22 Nov 2011 09:46:51 +0800 Subject: ASoC: Fix wrong define for AD1836_ADC_WORD_OFFSET commit 72531c9434fa884d20cb3c36fcec83752f32fdf4 upstream. According to the datasheet: The BIT[5:4] of ADC Control Register 2 is to control the word width. 00 = 25 Bits 01 = 20 Bits 10 = 16 Bits 11 = Invalid Thus, the AD1836_ADC_WORD_OFFSET should be defined as 4. Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/ad1836.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 444747f0db2..dd7be0dbbc5 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -34,7 +34,7 @@ #define AD1836_ADC_CTRL2 13 #define AD1836_ADC_WORD_LEN_MASK 0x30 -#define AD1836_ADC_WORD_OFFSET 5 +#define AD1836_ADC_WORD_OFFSET 4 #define AD1836_ADC_SERFMT_MASK (7 << 6) #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) -- cgit v1.2.3 From 3b958a46b7e81c432d7d6ef00ee4bd51ef2d39e2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 Nov 2011 09:44:14 +0100 Subject: firmware: Sigma: Prevent out of bounds memory access commit 4f718a29fe4908c2cea782f751e9805319684e2b upstream. The SigmaDSP firmware loader currently does not perform enough boundary size checks when processing the firmware. As a result it is possible that a malformed firmware can cause an out of bounds memory access. This patch adds checks which ensure that both the action header and the payload are completely inside the firmware data boundaries before processing them. Signed-off-by: Lars-Peter Clausen Acked-by: Mike Frysinger Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/sigma.c | 76 +++++++++++++++++++++++++++++++++++------------- include/linux/sigma.h | 5 ---- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index f10fc521951..c780baa59ed 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -14,13 +14,34 @@ #include #include -/* Return: 0==OK, <0==error, =1 ==no more actions */ +static size_t sigma_action_size(struct sigma_action *sa) +{ + size_t payload = 0; + + switch (sa->instr) { + case SIGMA_ACTION_WRITEXBYTES: + case SIGMA_ACTION_WRITESINGLE: + case SIGMA_ACTION_WRITESAFELOAD: + payload = sigma_action_len(sa); + break; + default: + break; + } + + payload = ALIGN(payload, 2); + + return payload + sizeof(struct sigma_action); +} + +/* + * Returns a negative error value in case of an error, 0 if processing of + * the firmware should be stopped after this action, 1 otherwise. + */ static int -process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) +process_sigma_action(struct i2c_client *client, struct sigma_action *sa) { - struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos); size_t len = sigma_action_len(sa); - int ret = 0; + int ret; pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, sa->instr, sa->addr, len); @@ -29,44 +50,50 @@ process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) case SIGMA_ACTION_WRITEXBYTES: case SIGMA_ACTION_WRITESINGLE: case SIGMA_ACTION_WRITESAFELOAD: - if (ssfw->fw->size < ssfw->pos + len) - return -EINVAL; ret = i2c_master_send(client, (void *)&sa->addr, len); if (ret < 0) return -EINVAL; break; - case SIGMA_ACTION_DELAY: - ret = 0; udelay(len); len = 0; break; - case SIGMA_ACTION_END: - return 1; - + return 0; default: return -EINVAL; } - /* when arrive here ret=0 or sent data */ - ssfw->pos += sigma_action_size(sa, len); - return ssfw->pos == ssfw->fw->size; + return 1; } static int process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw) { - pr_debug("%s: processing %p\n", __func__, ssfw); + struct sigma_action *sa; + size_t size; + int ret; + + while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { + sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); + + size = sigma_action_size(sa); + ssfw->pos += size; + if (ssfw->pos > ssfw->fw->size || size == 0) + break; + + ret = process_sigma_action(client, sa); - while (1) { - int ret = process_sigma_action(client, ssfw); pr_debug("%s: action returned %i\n", __func__, ret); - if (ret == 1) - return 0; - else if (ret) + + if (ret <= 0) return ret; } + + if (ssfw->pos != ssfw->fw->size) + return -EINVAL; + + return 0; } int process_sigma_firmware(struct i2c_client *client, const char *name) @@ -89,7 +116,14 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) /* then verify the header */ ret = -EINVAL; - if (fw->size < sizeof(*ssfw_head)) + + /* + * Reject too small or unreasonable large files. The upper limit has been + * chosen a bit arbitrarily, but it should be enough for all practical + * purposes and having the limit makes it easier to avoid integer + * overflows later in the loading process. + */ + if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) goto done; ssfw_head = (void *)fw->data; diff --git a/include/linux/sigma.h b/include/linux/sigma.h index e2accb3164d..9a138c2946b 100644 --- a/include/linux/sigma.h +++ b/include/linux/sigma.h @@ -50,11 +50,6 @@ static inline u32 sigma_action_len(struct sigma_action *sa) return (sa->len_hi << 16) | sa->len; } -static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len) -{ - return sizeof(*sa) + payload_len + (payload_len % 2); -} - extern int process_sigma_firmware(struct i2c_client *client, const char *name); #endif -- cgit v1.2.3 From 2a323db413fbe17c15cd60376d012f2ee2659f8d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 Nov 2011 09:44:15 +0100 Subject: firmware: Sigma: Skip header during CRC generation commit c56935bdc0a8edf50237d3b0205133a5b0adc604 upstream. The firmware header is not part of the CRC, so skip it. Otherwise the firmware will be rejected due to non-matching CRCs. Signed-off-by: Lars-Peter Clausen Acked-by: Mike Frysinger Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/sigma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index c780baa59ed..36265de0a9e 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -130,7 +130,8 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) goto done; - crc = crc32(0, fw->data, fw->size); + crc = crc32(0, fw->data + sizeof(*ssfw_head), + fw->size - sizeof(*ssfw_head)); pr_debug("%s: crc=%x\n", __func__, crc); if (crc != ssfw_head->crc) goto done; -- cgit v1.2.3 From bdbee02fb09ff4278de3c4656689261ee9647007 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 Nov 2011 09:44:16 +0100 Subject: firmware: Sigma: Fix endianess issues commit bda63586bc5929e97288cdb371bb6456504867ed upstream. Currently the SigmaDSP firmware loader only works correctly on little-endian systems. Fix this by using the proper endianess conversion functions. Signed-off-by: Lars-Peter Clausen Acked-by: Mike Frysinger Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/sigma.c | 2 +- include/linux/sigma.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index 36265de0a9e..1eedb6f7fda 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c @@ -133,7 +133,7 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) crc = crc32(0, fw->data + sizeof(*ssfw_head), fw->size - sizeof(*ssfw_head)); pr_debug("%s: crc=%x\n", __func__, crc); - if (crc != ssfw_head->crc) + if (crc != le32_to_cpu(ssfw_head->crc)) goto done; ssfw.pos = sizeof(*ssfw_head); diff --git a/include/linux/sigma.h b/include/linux/sigma.h index 9a138c2946b..d0de882c0d9 100644 --- a/include/linux/sigma.h +++ b/include/linux/sigma.h @@ -24,7 +24,7 @@ struct sigma_firmware { struct sigma_firmware_header { unsigned char magic[7]; u8 version; - u32 crc; + __le32 crc; }; enum { @@ -40,14 +40,14 @@ enum { struct sigma_action { u8 instr; u8 len_hi; - u16 len; - u16 addr; + __le16 len; + __be16 addr; unsigned char payload[]; }; static inline u32 sigma_action_len(struct sigma_action *sa) { - return (sa->len_hi << 16) | sa->len; + return (sa->len_hi << 16) | le16_to_cpu(sa->len); } extern int process_sigma_firmware(struct i2c_client *client, const char *name); -- cgit v1.2.3 From 60709063c5d50549e834ac75288782e84c8e53db Mon Sep 17 00:00:00 2001 From: wwang Date: Mon, 31 Oct 2011 15:02:53 +0800 Subject: staging:rts_pstor:Complete scanning_done variable commit f7364ba04b0961f3a1f978bbe77102606801e35f upstream. Complete scanning_done variable if rtsx-scan thread created failed. Signed-off-by: wwang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts_pstor/rtsx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c index 16c73fbff51..890e6cce6d3 100644 --- a/drivers/staging/rts_pstor/rtsx.c +++ b/drivers/staging/rts_pstor/rtsx.c @@ -1015,6 +1015,7 @@ static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id th = kthread_create(rtsx_scan_thread, dev, "rtsx-scan"); if (IS_ERR(th)) { printk(KERN_ERR "Unable to start the device-scanning thread\n"); + complete(&dev->scanning_done); quiesce_and_remove_host(dev); err = PTR_ERR(th); goto errout; -- cgit v1.2.3 From df781a42499bdf5a1a4375c55ffed1a80cbdf5b3 Mon Sep 17 00:00:00 2001 From: Bart Westgeest Date: Tue, 1 Nov 2011 15:01:28 -0400 Subject: staging: usbip: bugfix for deadlock commit 438957f8d4a84daa7fa5be6978ad5897a2e9e5e5 upstream. Interrupts must be disabled prior to calling usb_hcd_unlink_urb_from_ep. If interrupts are not disabled, it can potentially lead to a deadlock. The deadlock is readily reproduceable on a slower (ARM based) device such as the TI Pandaboard. Signed-off-by: Bart Westgeest Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_rx.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 09c44abb89e..3872b8cccdc 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -68,6 +68,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, { struct usbip_device *ud = &vdev->ud; struct urb *urb; + unsigned long flags; spin_lock(&vdev->priv_lock); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); @@ -101,9 +102,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, usbip_dbg_vhci_rx("now giveback urb %p\n", urb); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -141,6 +142,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, { struct vhci_unlink *unlink; struct urb *urb; + unsigned long flags; usbip_dump_header(pdu); @@ -170,9 +172,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, urb->status = pdu->u.ret_unlink.status; pr_info("urb->status %d\n", urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); -- cgit v1.2.3 From 7994d8747d9ac088be8a2136dc25ea30135ca1e8 Mon Sep 17 00:00:00 2001 From: Bernd Porr Date: Tue, 8 Nov 2011 21:23:03 +0000 Subject: staging: comedi: fix oops for USB DAQ devices. commit 3ffab428f40849ed5f21bcfd7285bdef7902f9ca upstream. This fixes kernel oops when an USB DAQ device is plugged out while it's communicating with the userspace software. Signed-off-by: Bernd Porr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 71 +++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index e90e3cceb5f..bfda750b42b 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1452,9 +1452,6 @@ static struct vm_operations_struct comedi_vm_ops = { static int comedi_mmap(struct file *file, struct vm_area_struct *vma) { const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; struct comedi_async *async = NULL; unsigned long start = vma->vm_start; unsigned long size; @@ -1462,6 +1459,15 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) int i; int retval; struct comedi_subdevice *s; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + + dev_file_info = comedi_get_device_file_info(minor); + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1528,11 +1534,17 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; struct comedi_subdevice *read_subdev; struct comedi_subdevice *write_subdev; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1578,9 +1590,15 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1683,9 +1701,15 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1885,11 +1909,17 @@ ok: static int comedi_close(struct inode *inode, struct file *file) { const unsigned minor = iminor(inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; struct comedi_subdevice *s = NULL; int i; + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); + + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; mutex_lock(&dev->mutex); @@ -1923,10 +1953,15 @@ static int comedi_close(struct inode *inode, struct file *file) static int comedi_fasync(int fd, struct file *file, int on) { const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info = - comedi_get_device_file_info(minor); + struct comedi_device_file_info *dev_file_info; + struct comedi_device *dev; + dev_file_info = comedi_get_device_file_info(minor); - struct comedi_device *dev = dev_file_info->device; + if (dev_file_info == NULL) + return -ENODEV; + dev = dev_file_info->device; + if (dev == NULL) + return -ENODEV; return fasync_helper(fd, file, on, &dev->async_queue); } -- cgit v1.2.3 From 3762465d4a6c6a92a93d361b95dd453fd736ba73 Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Sat, 29 Oct 2011 09:45:39 +0200 Subject: Staging: comedi: fix mmap_count commit df30b21cb0eed5ba8a8e0cdfeebc66ba8cde821d upstream. In comedi_fops, mmap_count is decremented at comedi_vm_ops->close but it is not incremented at comedi_vm_ops->open. This may result in a negative counter. The patch introduces the open method to keep the counter consistent. The bug was triggerd by this sample code: mmap(0, ...., comedi_fd); fork(); exit(0); Acked-by: Alessandro Rubini Signed-off-by: Federico Vaga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index bfda750b42b..bf55ccec65a 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1432,7 +1432,21 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return ret; } -static void comedi_unmap(struct vm_area_struct *area) + +static void comedi_vm_open(struct vm_area_struct *area) +{ + struct comedi_async *async; + struct comedi_device *dev; + + async = area->vm_private_data; + dev = async->subdevice->device; + + mutex_lock(&dev->mutex); + async->mmap_count++; + mutex_unlock(&dev->mutex); +} + +static void comedi_vm_close(struct vm_area_struct *area) { struct comedi_async *async; struct comedi_device *dev; @@ -1446,7 +1460,8 @@ static void comedi_unmap(struct vm_area_struct *area) } static struct vm_operations_struct comedi_vm_ops = { - .close = comedi_unmap, + .open = comedi_vm_open, + .close = comedi_vm_close, }; static int comedi_mmap(struct file *file, struct vm_area_struct *vma) -- cgit v1.2.3 From a7e9e05141e922b1bbf4315827dcf8c80989255c Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Sat, 29 Oct 2011 09:47:39 +0200 Subject: Staging: comedi: fix signal handling in read and write commit 6a9ce6b654e491981f6ef7e214cbd4f63e033848 upstream. After sleeping on a wait queue, signal_pending(current) should be checked (not before sleeping). Acked-by: Alessandro Rubini Signed-off-by: Federico Vaga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index bf55ccec65a..b347cda3ca9 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1673,11 +1673,11 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, retval = -EAGAIN; break; } + schedule(); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } - schedule(); if (!s->busy) break; if (s->busy != file) { @@ -1780,11 +1780,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, retval = -EAGAIN; break; } + schedule(); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } - schedule(); if (!s->busy) { retval = 0; break; -- cgit v1.2.3 From b5e0fb085f337c2ab00532d09056da3525f2e847 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 22 Nov 2011 17:18:24 -0800 Subject: usb: musb: PM: fix context save/restore in suspend/resume path commit 5d193ce8f1fa7c67c7fd7be2c03ef31eed344a4f upstream. Currently the driver tries to save context in the suspend path, but will cause an abort if the device is already runtime suspended. This happens, for example, if MUSB loaded/compiled-in, in host mode, but no USB devices are attached. MUSB will be runtime suspended, but then attempting a system suspend will crash due to the context save being attempted while the device is disabled. On OMAP, as of v3.1, the driver's ->runtime_suspend() callback will be called late in the suspend path (by the PM domain layer) if the driver is not already runtime suspended, ensuring a full shutdown. Therefore, the context save is not needed in the ->suspend() method since it will be called in the ->runtime_suspend() method anyways (similarily for resume.) NOTE: this leaves the suspend/resume methods basically empty (with some FIXMEs and comments, but I'll leave it to the maintainers to decide whether to remove them. Signed-off-by: Kevin Hilman Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 20a28731c33..a057a5a987b 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2302,18 +2302,12 @@ static int musb_suspend(struct device *dev) */ } - musb_save_context(musb); - spin_unlock_irqrestore(&musb->lock, flags); return 0; } static int musb_resume_noirq(struct device *dev) { - struct musb *musb = dev_to_musb(dev); - - musb_restore_context(musb); - /* for static cmos like DaVinci, register values were preserved * unless for some reason the whole soc powered down or the USB * module got reset through the PSC (vs just being disabled). -- cgit v1.2.3 From da6a65ba7034fe6273bf7dcdae174f4f04dead70 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 22 Nov 2011 10:28:31 +0300 Subject: USB: whci-hcd: fix endian conversion in qset_clear() commit 8746c83d538cab273d335acb2be226d096f4a5af upstream. qset->qh.link is an __le64 field and we should be using cpu_to_le64() to fill it. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/whci/qset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index d6e17542861..a403b53e86b 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -124,7 +124,7 @@ void qset_clear(struct whc *whc, struct whc_qset *qset) { qset->td_start = qset->td_end = qset->ntds = 0; - qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); + qset->qh.link = cpu_to_le64(QH_LINK_NTDS(8) | QH_LINK_T); qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK; qset->qh.err_count = 0; qset->qh.scratch[0] = 0; -- cgit v1.2.3 From 9aee2c52173b2d5ab712d692a31c2016c1dda8f2 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 16 Nov 2011 11:39:52 +0100 Subject: HID: Correct General touch PID commit b1807719f6acdf18cc4bde3b5400d05d77801494 upstream. Genera Touch told us that 0001 is their single point device and 0003 is the multitouch one. Apparently, we made the tests someone having a prototype, and not the final product. They said it should be safe to do the switch. This partially reverts 5572da0 ("HID: hid-mulitouch: add support for the 'Sensing Win7-TwoFinger'"). Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 2 +- drivers/hid/hid-ids.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 5be9f47e41f..f26ae3176a3 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1728,8 +1728,8 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) }, { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0d87d981a57..53c4634fed3 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -266,7 +266,7 @@ #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc -#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 -- cgit v1.2.3 From 523cc1591e42c0b51e334609a841c7566be2091f Mon Sep 17 00:00:00 2001 From: Marcin Kościelnicki Date: Wed, 30 Nov 2011 17:01:04 +0100 Subject: usb: ftdi_sio: add PID for Propox ISPcable III MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 307369b0ca06b27b511b61714e335ddfccf19c4f upstream. Signed-off-by: Marcin Kościelnicki Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e16394c9dbd..bbd2cdd669a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -735,6 +735,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 571fa96b49c..055b64ef0bb 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -112,6 +112,7 @@ /* Propox devices */ #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 +#define FTDI_PROPOX_ISPCABLEIII_PID 0xD739 /* Lenz LI-USB Computer Interface. */ #define FTDI_LENZ_LIUSB_PID 0xD780 -- cgit v1.2.3 From c61954d8c8348de93281f322a3675bb308128414 Mon Sep 17 00:00:00 2001 From: Dirk Nehring Date: Thu, 24 Nov 2011 19:22:23 +0100 Subject: usb: option: add Huawei E353 controlling interfaces commit 46b1848360c8e634e0b063932a1261062fa0f7d6 upstream. This patch creates the missing controlling devices for the Huawei E353 HSPA+ stick. Signed-off-by: Dirk Nehring Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 3a47cbe9fc5..eeab0ad9bf4 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -657,6 +657,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x08) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, -- cgit v1.2.3 From f769c8c9d67806d5ed3c2ab555b56eef44bb08fe Mon Sep 17 00:00:00 2001 From: Veli-Pekka Peltola Date: Thu, 24 Nov 2011 22:08:56 +0200 Subject: usb: option: add SIMCom SIM5218 commit ec0cd94d881ca89cc9fb61d00d0f4b2b52e605b3 upstream. Tested with SIM5218EVB-KIT evaluation kit. Signed-off-by: Veli-Pekka Peltola Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index eeab0ad9bf4..e98a1e1e508 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -746,6 +746,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, -- cgit v1.2.3 From 829d5a92cbfe6e906bbe24a5bb1675a6d27a5db2 Mon Sep 17 00:00:00 2001 From: Qinglin Ye Date: Wed, 23 Nov 2011 23:39:32 +0800 Subject: USB: usb-storage: unusual_devs entry for Kingston DT 101 G2 commit cec28a5428793b6bc64e56687fb239759d6da74e upstream. Kingston DT 101 G2 replies a wrong tag while transporting, add an unusal_devs entry to ignore the tag validation. Signed-off-by: Qinglin Ye Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 3041a974faf..24caba79d72 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1854,6 +1854,13 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Qinglin Ye */ +UNUSUAL_DEV( 0x13fe, 0x3600, 0x0100, 0x0100, + "Kingston", + "DT 101 G2", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BULK_IGNORE_TAG ), + /* Reported by Francesco Foresti */ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, "Super Top", -- cgit v1.2.3 From de5f8dc38303f9a1fc58349f0d1c6f46a8034a00 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 29 Nov 2011 22:31:23 +0100 Subject: IB: Fix RCU lockdep splats commit 580da35a31f91a594f3090b7a2c39b85cb051a12 upstream. Commit f2c31e32b37 ("net: fix NULL dereferences in check_peer_redir()") forgot to take care of infiniband uses of dst neighbours. Many thanks to Marc Aurele who provided a nice bug report and feedback. Reported-by: Marc Aurele La France Signed-off-by: Eric Dumazet Cc: David Miller Signed-off-by: Roland Dreier --- drivers/infiniband/core/addr.c | 9 ++++++--- drivers/infiniband/hw/cxgb3/iwch_cm.c | 4 ++++ drivers/infiniband/hw/cxgb4/cm.c | 4 ++++ drivers/infiniband/hw/mlx4/qp.c | 2 +- drivers/infiniband/hw/nes/nes_cm.c | 6 ++++-- drivers/infiniband/ulp/ipoib/ipoib_main.c | 18 +++++++++++------- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 6 ++++-- 7 files changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 236ad9a89c0..f2a84c6f854 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -215,7 +215,9 @@ static int addr4_resolve(struct sockaddr_in *src_in, neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev); if (!neigh || !(neigh->nud_state & NUD_VALID)) { + rcu_read_lock(); neigh_event_send(dst_get_neighbour(&rt->dst), NULL); + rcu_read_unlock(); ret = -ENODATA; if (neigh) goto release; @@ -273,15 +275,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, goto put; } + rcu_read_lock(); neigh = dst_get_neighbour(dst); if (!neigh || !(neigh->nud_state & NUD_VALID)) { if (neigh) neigh_event_send(neigh, NULL); ret = -ENODATA; - goto put; + } else { + ret = rdma_copy_addr(addr, dst->dev, neigh->ha); } - - ret = rdma_copy_addr(addr, dst->dev, neigh->ha); + rcu_read_unlock(); put: dst_release(dst); return ret; diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index 6cd642aaa4d..e55ce7a428b 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -1365,8 +1365,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) goto reject; } dst = &rt->dst; + rcu_read_lock(); neigh = dst_get_neighbour(dst); l2t = t3_l2t_get(tdev, neigh, neigh->dev); + rcu_read_unlock(); if (!l2t) { printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", __func__); @@ -1936,10 +1938,12 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) } ep->dst = &rt->dst; + rcu_read_lock(); neigh = dst_get_neighbour(ep->dst); /* get a l2t entry */ ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev); + rcu_read_unlock(); if (!ep->l2t) { printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); err = -ENOMEM; diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 77f769d9227..daa93e942e1 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1358,6 +1358,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) goto reject; } dst = &rt->dst; + rcu_read_lock(); neigh = dst_get_neighbour(dst); if (neigh->dev->flags & IFF_LOOPBACK) { pdev = ip_dev_find(&init_net, peer_ip); @@ -1384,6 +1385,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) rss_qid = dev->rdev.lldi.rxq_ids[ cxgb4_port_idx(neigh->dev) * step]; } + rcu_read_unlock(); if (!l2t) { printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", __func__); @@ -1909,6 +1911,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) } ep->dst = &rt->dst; + rcu_read_lock(); neigh = dst_get_neighbour(ep->dst); /* get a l2t entry */ @@ -1945,6 +1948,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[ cxgb4_port_idx(neigh->dev) * step]; } + rcu_read_unlock(); if (!ep->l2t) { printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); err = -ENOMEM; diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 3a91d9d8dc5..5c22514b871 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1309,7 +1309,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, int is_eth; int is_vlan = 0; int is_grh; - u16 vlan; + u16 vlan = 0; send_size = 0; for (i = 0; i < wr->num_sge; ++i) diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index c118663e443..a237547330b 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1150,9 +1150,11 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi neigh_release(neigh); } - if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) + if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) { + rcu_read_lock(); neigh_event_send(dst_get_neighbour(&rt->dst), NULL); - + rcu_read_unlock(); + } ip_rt_put(rt); return rc; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index fe89c4660d5..a98c414978e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -555,6 +555,7 @@ static int path_rec_start(struct net_device *dev, return 0; } +/* called with rcu_read_lock */ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); @@ -636,6 +637,7 @@ err_drop: spin_unlock_irqrestore(&priv->lock, flags); } +/* called with rcu_read_lock */ static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(skb->dev); @@ -720,13 +722,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) struct neighbour *n = NULL; unsigned long flags; + rcu_read_lock(); if (likely(skb_dst(skb))) n = dst_get_neighbour(skb_dst(skb)); if (likely(n)) { if (unlikely(!*to_ipoib_neigh(n))) { ipoib_path_lookup(skb, dev); - return NETDEV_TX_OK; + goto unlock; } neigh = *to_ipoib_neigh(n); @@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) ipoib_neigh_free(dev, neigh); spin_unlock_irqrestore(&priv->lock, flags); ipoib_path_lookup(skb, dev); - return NETDEV_TX_OK; + goto unlock; } if (ipoib_cm_get(neigh)) { if (ipoib_cm_up(neigh)) { ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); - return NETDEV_TX_OK; + goto unlock; } } else if (neigh->ah) { ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha)); - return NETDEV_TX_OK; + goto unlock; } if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { @@ -793,13 +796,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) phdr->hwaddr + 4); dev_kfree_skb_any(skb); ++dev->stats.tx_dropped; - return NETDEV_TX_OK; + goto unlock; } unicast_arp_send(skb, dev, phdr); } } - +unlock: + rcu_read_unlock(); return NETDEV_TX_OK; } @@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_buff *skb, dst = skb_dst(skb); n = NULL; if (dst) - n = dst_get_neighbour(dst); + n = dst_get_neighbour_raw(dst); if ((!dst || !n) && daddr) { struct ipoib_pseudoheader *phdr = (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index ecea4fe1ed0..a8d2a891b84 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -265,7 +265,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, skb->dev = dev; if (dst) - n = dst_get_neighbour(dst); + n = dst_get_neighbour_raw(dst); if (!dst || !n) { /* put pseudoheader back on for next time */ skb_push(skb, sizeof (struct ipoib_pseudoheader)); @@ -721,6 +721,8 @@ out: if (mcast && mcast->ah) { struct dst_entry *dst = skb_dst(skb); struct neighbour *n = NULL; + + rcu_read_lock(); if (dst) n = dst_get_neighbour(dst); if (n && !*to_ipoib_neigh(n)) { @@ -733,7 +735,7 @@ out: list_add_tail(&neigh->list, &mcast->neigh_list); } } - + rcu_read_unlock(); spin_unlock_irqrestore(&priv->lock, flags); ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); return; -- cgit v1.2.3 From 027a53824cc8602232cc38a86d9499efec2dcbee Mon Sep 17 00:00:00 2001 From: Thomas Poussevin Date: Thu, 27 Oct 2011 18:46:48 +0200 Subject: USB: EHCI: fix HUB TT scheduling issue with iso transfer commit 811c926c538f7e8d3c08b630dd5844efd7e000f6 upstream. The current TT scheduling doesn't allow to play and then record on a full-speed device connected to a high speed hub. The IN iso stream can only start on the first uframe (0-2 for a 165 us) because of CSPLIT transactions. For the OUT iso stream there no such restriction. uframe 0-5 are possible. The idea of this patch is that the first uframe are precious (for IN TT iso stream) and we should allocate the last uframes first if possible. For that we reverse the order of uframe allocation (last uframe first). Here an example : hid interrupt stream ---------------------------------------------------------------------- uframe | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ---------------------------------------------------------------------- max_tt_usecs | 125 | 125 | 125 | 125 | 125 | 125 | 30 | 0 | ---------------------------------------------------------------------- used usecs on a frame | 13 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ---------------------------------------------------------------------- iso OUT stream ---------------------------------------------------------------------- uframe | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ---------------------------------------------------------------------- max_tt_usecs | 125 | 125 | 125 | 125 | 125 | 125 | 30 | 0 | ---------------------------------------------------------------------- used usecs on a frame | 13 | 125 | 39 | 0 | 0 | 0 | 0 | 0 | ---------------------------------------------------------------------- There no place for iso IN stream (uframe 0-2 are used) and we got "cannot submit datapipe for urb 0, error -28: not enough bandwidth" error. With the patch this become. iso OUT stream ---------------------------------------------------------------------- uframe | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ---------------------------------------------------------------------- max_tt_usecs | 125 | 125 | 125 | 125 | 125 | 125 | 30 | 0 | ---------------------------------------------------------------------- used usecs on a frame | 13 | 0 | 0 | 0 | 125 | 39 | 0 | 0 | ---------------------------------------------------------------------- iso IN stream ---------------------------------------------------------------------- uframe | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ---------------------------------------------------------------------- max_tt_usecs | 125 | 125 | 125 | 125 | 125 | 125 | 30 | 0 | ---------------------------------------------------------------------- used usecs on a frame | 13 | 0 | 125 | 40 | 125 | 39 | 0 | 0 | ---------------------------------------------------------------------- Signed-off-by: Matthieu Castet Signed-off-by: Thomas Poussevin Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 29bec34973b..afef3df9757 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1480,10 +1480,15 @@ iso_stream_schedule ( /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ - /* find a uframe slot with enough bandwidth */ - next = start + period; - for (; start < next; start++) { - + /* find a uframe slot with enough bandwidth. + * Early uframes are more precious because full-speed + * iso IN transfers can't use late uframes, + * and therefore they should be allocated last. + */ + next = start; + start += period; + do { + start--; /* check schedule: enough space? */ if (stream->highspeed) { if (itd_slot_ok(ehci, mod, start, @@ -1496,7 +1501,7 @@ iso_stream_schedule ( start, sched, period)) break; } - } + } while (start > next); /* no room in the schedule */ if (start == next) { -- cgit v1.2.3 From 07b91eb2d2c53017fbae33d5eae1037cb078d3e4 Mon Sep 17 00:00:00 2001 From: Matthieu CASTET Date: Mon, 28 Nov 2011 11:30:22 +0100 Subject: EHCI : Fix a regression in the ISO scheduler commit e3420901eba65b1c46bed86d360e3a8685d20734 upstream. Fix a regression that was introduced by commit 811c926c538f7e8d3c08b630dd5844efd7e000f6 (USB: EHCI: fix HUB TT scheduling issue with iso transfer). We detect an error if next == start, but this means uframe 0 can't be allocated anymore for iso transfer... Reported-by: Sander Eikelenboom Signed-off-by: Matthieu CASTET Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index afef3df9757..c787af2ba4b 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1476,6 +1476,7 @@ iso_stream_schedule ( * jump until after the queue is primed. */ else { + int done = 0; start = SCHEDULE_SLOP + (now & ~0x07); /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ @@ -1493,18 +1494,18 @@ iso_stream_schedule ( if (stream->highspeed) { if (itd_slot_ok(ehci, mod, start, stream->usecs, period)) - break; + done = 1; } else { if ((start % 8) >= 6) continue; if (sitd_slot_ok(ehci, mod, stream, start, sched, period)) - break; + done = 1; } - } while (start > next); + } while (start > next && !done); /* no room in the schedule */ - if (start == next) { + if (!done) { ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n", urb, now, now + mod); status = -ENOSPC; -- cgit v1.2.3 From ba92f7efc8390db5ed6da4966ef943718eb048b7 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Wed, 30 Nov 2011 16:37:41 +0800 Subject: xHCI: fix bug in xhci_clear_command_ring() commit 158886cd2cf4599e04f9b7e10cb767f5f39b14f1 upstream. When system enters suspend, xHCI driver clears command ring by writing zero to all the TRBs. However, this also writes zero to the Link TRB, and the ring is mangled. This may cause driver accesses wrong memory address and the result is unpredicted. When clear the command ring, keep the last Link TRB intact, only clear its cycle bit. This should fix the "command ring full" issue reported by Oliver Neukum. This should be backported to stable kernels as old as 2.6.37, since the commit 89821320 "xhci: Fix command ring replay after resume" is merged. Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Reported-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 67900ff4146..10dc1bdf3a7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -657,7 +657,10 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) ring = xhci->cmd_ring; seg = ring->deq_seg; do { - memset(seg->trbs, 0, SEGMENT_SIZE); + memset(seg->trbs, 0, + sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1)); + seg->trbs[TRBS_PER_SEGMENT - 1].link.control &= + cpu_to_le32(~TRB_CYCLE); seg = seg->next; } while (seg != ring->deq_seg); -- cgit v1.2.3 From 3ef3c3830482a5de31781a5dca2a9bd7ef6d1562 Mon Sep 17 00:00:00 2001 From: Salman Qazi Date: Tue, 15 Nov 2011 14:12:06 -0800 Subject: sched, x86: Avoid unnecessary overflow in sched_clock commit 4cecf6d401a01d054afc1e5f605bcbfe553cb9b9 upstream. (Added the missing signed-off-by line) In hundreds of days, the __cycles_2_ns calculation in sched_clock has an overflow. cyc * per_cpu(cyc2ns, cpu) exceeds 64 bits, causing the final value to become zero. We can solve this without losing any precision. We can decompose TSC into quotient and remainder of division by the scale factor, and then use this to convert TSC into nanoseconds. Signed-off-by: Salman Qazi Acked-by: John Stultz Reviewed-by: Paul Turner Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20111115221121.7262.88871.stgit@dungbeetle.mtv.corp.google.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/timer.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h index fa7b9176b76..431793e5d48 100644 --- a/arch/x86/include/asm/timer.h +++ b/arch/x86/include/asm/timer.h @@ -32,6 +32,22 @@ extern int no_timer_check; * (mathieu.desnoyers@polymtl.ca) * * -johnstul@us.ibm.com "math is hard, lets go shopping!" + * + * In: + * + * ns = cycles * cyc2ns_scale / SC + * + * Although we may still have enough bits to store the value of ns, + * in some cases, we may not have enough bits to store cycles * cyc2ns_scale, + * leading to an incorrect result. + * + * To avoid this, we can decompose 'cycles' into quotient and remainder + * of division by SC. Then, + * + * ns = (quot * SC + rem) * cyc2ns_scale / SC + * = quot * cyc2ns_scale + (rem * cyc2ns_scale) / SC + * + * - sqazi@google.com */ DECLARE_PER_CPU(unsigned long, cyc2ns); @@ -41,9 +57,14 @@ DECLARE_PER_CPU(unsigned long long, cyc2ns_offset); static inline unsigned long long __cycles_2_ns(unsigned long long cyc) { + unsigned long long quot; + unsigned long long rem; int cpu = smp_processor_id(); unsigned long long ns = per_cpu(cyc2ns_offset, cpu); - ns += cyc * per_cpu(cyc2ns, cpu) >> CYC2NS_SCALE_FACTOR; + quot = (cyc >> CYC2NS_SCALE_FACTOR); + rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1); + ns += quot * per_cpu(cyc2ns, cpu) + + ((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR); return ns; } -- cgit v1.2.3 From 08673cfac6768fce130a6ddb5134299beebfd14f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sun, 25 Sep 2011 15:29:00 -0600 Subject: x86/mpparse: Account for bus types other than ISA and PCI commit 9e6866686bdf2dcf3aeb0838076237ede532dcc8 upstream. In commit f8924e770e04 ("x86: unify mp_bus_info"), the 32-bit and 64-bit versions of MP_bus_info were rearranged to match each other better. Unfortunately it introduced a regression: prior to that change we used to always set the mp_bus_not_pci bit, then clear it if we found a PCI bus. After it, we set mp_bus_not_pci for ISA buses, clear it for PCI buses, and leave it alone otherwise. In the cases of ISA and PCI, there's not much difference. But ISA is not the only non-PCI bus, so it's better to always set mp_bus_not_pci and clear it only for PCI. Without this change, Dan's Dell PowerEdge 4200 panics on boot with a log indicating interrupt routing trouble unless the "noapic" option is supplied. With this change, the machine boots reliably without "noapic". Fixes http://bugs.debian.org/586494 Reported-bisected-and-tested-by: Dan McGrath Signed-off-by: Bjorn Helgaas Cc: Dan McGrath Cc: Alexey Starikovskiy [jrnieder@gmail.com: clarified commit message] Signed-off-by: Jonathan Nieder Link: http://lkml.kernel.org/r/20111122215000.GA9151@elie.hsd1.il.comcast.net Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/mpparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 9103b89c145..0741b062a30 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -95,8 +95,8 @@ static void __init MP_bus_info(struct mpc_bus *m) } #endif + set_bit(m->busid, mp_bus_not_pci); if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) { - set_bit(m->busid, mp_bus_not_pci); #if defined(CONFIG_EISA) || defined(CONFIG_MCA) mp_bus_id_to_type[m->busid] = MP_BUS_ISA; #endif -- cgit v1.2.3 From 7b4a0b336d67d9f706fb83d3050bcd9bef58cb9d Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Mon, 5 Dec 2011 16:53:53 +0300 Subject: x86: Fix "Acer Aspire 1" reboot hang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1ef03890969932e9359b9a4c658f7f87771910ac upstream. Looks like on some Acer Aspire 1s with older bioses, reboot via bios fails. It works on my machine, (with BIOS version 0.3310) but not on some others (BIOS version 0.3309). There's a log of problems at: https://bbs.archlinux.org/viewtopic.php?id=124136 This patch adds a different callback to the reboot quirk table, to allow rebooting via keybaord controller. Reported-by: Uroš Vampl Tested-by: Vasily Khoruzhick Signed-off-by: Peter Chubb Cc: Don Zickus Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1323093233-9481-1-git-send-email-anarsoul@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/reboot.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 9242436e993..d4a705f2283 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -124,7 +124,7 @@ __setup("reboot=", reboot_setup); */ /* - * Some machines require the "reboot=b" commandline option, + * Some machines require the "reboot=b" or "reboot=k" commandline options, * this quirk makes that automatic. */ static int __init set_bios_reboot(const struct dmi_system_id *d) @@ -136,6 +136,15 @@ static int __init set_bios_reboot(const struct dmi_system_id *d) return 0; } +static int __init set_kbd_reboot(const struct dmi_system_id *d) +{ + if (reboot_type != BOOT_KBD) { + reboot_type = BOOT_KBD; + printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident); + } + return 0; +} + static struct dmi_system_id __initdata reboot_dmi_table[] = { { /* Handle problems with rebooting on Dell E520's */ .callback = set_bios_reboot, @@ -295,7 +304,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { }, }, { /* Handle reboot issue on Acer Aspire one */ - .callback = set_bios_reboot, + .callback = set_kbd_reboot, .ident = "Acer Aspire One A110", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -- cgit v1.2.3 From 400b14179e4170817aa476a29e29514c53bf4e25 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 15 Nov 2011 14:49:09 -0800 Subject: x86/paravirt: PTE updates in k(un)map_atomic need to be synchronous, regardless of lazy_mmu mode commit 2cd1c8d4dc7ecca9e9431e2dabe41ae9c7d89e51 upstream. Fix an outstanding issue that has been reported since 2.6.37. Under a heavy loaded machine processing "fork()" calls could crash with: BUG: unable to handle kernel paging request at f573fc8c IP: [] swap_count_continued+0x104/0x180 *pdpt = 000000002a3b9027 *pde = 0000000001bed067 *pte = 0000000000000000 Oops: 0000 [#1] SMP Modules linked in: Pid: 1638, comm: apache2 Not tainted 3.0.4-linode37 #1 EIP: 0061:[] EFLAGS: 00210246 CPU: 3 EIP is at swap_count_continued+0x104/0x180 .. snip.. Call Trace: [] ? __swap_duplicate+0xc2/0x160 [] ? pte_mfn_to_pfn+0x87/0xe0 [] ? swap_duplicate+0x14/0x40 [] ? copy_pte_range+0x45b/0x500 [] ? copy_page_range+0x195/0x200 [] ? dup_mmap+0x1c6/0x2c0 [] ? dup_mm+0xa8/0x130 [] ? copy_process+0x98a/0xb30 [] ? do_fork+0x4f/0x280 [] ? getnstimeofday+0x43/0x100 [] ? sys_clone+0x30/0x40 [] ? ptregs_clone+0x15/0x48 [] ? syscall_call+0x7/0xb The problem is that in copy_page_range() we turn lazy mode on, and then in swap_entry_free() we call swap_count_continued() which ends up in: map = kmap_atomic(page, KM_USER0) + offset; and then later we touch *map. Since we are running in batched mode (lazy) we don't actually set up the PTE mappings and the kmap_atomic is not done synchronously and ends up trying to dereference a page that has not been set. Looking at kmap_atomic_prot_pfn(), it uses 'arch_flush_lazy_mmu_mode' and doing the same in kmap_atomic_prot() and __kunmap_atomic() makes the problem go away. Interestingly, commit b8bcfe997e4615 ("x86/paravirt: remove lazy mode in interrupts") removed part of this to fix an interrupt issue - but it went to far and did not consider this scenario. Signed-off-by: Konrad Rzeszutek Wilk Cc: Peter Zijlstra Cc: Jeremy Fitzhardinge Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/highmem_32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index b4996266210..f4f29b19fac 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c @@ -45,6 +45,7 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot) vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); BUG_ON(!pte_none(*(kmap_pte-idx))); set_pte(kmap_pte-idx, mk_pte(page, prot)); + arch_flush_lazy_mmu_mode(); return (void *)vaddr; } @@ -88,6 +89,7 @@ void __kunmap_atomic(void *kvaddr) */ kpte_clear_flush(kmap_pte-idx, vaddr); kmap_atomic_idx_pop(); + arch_flush_lazy_mmu_mode(); } #ifdef CONFIG_DEBUG_HIGHMEM else { -- cgit v1.2.3 From b11ee9e9403ab72d52c46cc8b3b94de17ed196e6 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 7 Oct 2011 13:36:40 +0200 Subject: perf/x86: Fix PEBS instruction unwind commit 57d1c0c03c6b48b2b96870d831b9ce6b917f53ac upstream. Masami spotted that we always try to decode the instruction stream as 64bit instructions when running a 64bit kernel, this doesn't work for ia32-compat proglets. Use TIF_IA32 to detect if we need to use the 32bit instruction decoder. Reported-by: Masami Hiramatsu Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/perf_event_intel_ds.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 1b1ef3addcf..3213c52db76 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -508,6 +508,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) unsigned long from = cpuc->lbr_entries[0].from; unsigned long old_to, to = cpuc->lbr_entries[0].to; unsigned long ip = regs->ip; + int is_64bit = 0; /* * We don't need to fixup if the PEBS assist is fault like @@ -559,7 +560,10 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) } else kaddr = (void *)to; - kernel_insn_init(&insn, kaddr); +#ifdef CONFIG_X86_64 + is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32); +#endif + insn_init(&insn, kaddr, is_64bit); insn_get_length(&insn); to += insn.length; } while (to < ip); -- cgit v1.2.3 From a6ff8af2ed1af704e400b558b2811ce7a350d2eb Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 10 Oct 2011 16:21:10 +0200 Subject: oprofile, x86: Fix crash when unloading module (nmi timer mode) commit 97f7f8189fe54e3cfe324ef9ad35064f3d2d3bff upstream. If oprofile uses the nmi timer interrupt there is a crash while unloading the module. The bug can be triggered with oprofile build as module and kernel parameter nolapic set. This patch fixes this. oprofile: using NMI timer interrupt. BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 IP: [] unregister_syscore_ops+0x41/0x58 PGD 42dbca067 PUD 41da6a067 PMD 0 Oops: 0002 [#1] PREEMPT SMP CPU 5 Modules linked in: oprofile(-) [last unloaded: oprofile] Pid: 2518, comm: modprobe Not tainted 3.1.0-rc7-00019-gb2fb49d #19 Advanced Micro Device Anaheim/Anaheim RIP: 0010:[] [] unregister_syscore_ops+0x41/0x58 RSP: 0018:ffff88041ef71e98 EFLAGS: 00010296 RAX: 0000000000000000 RBX: ffffffffa0017100 RCX: dead000000200200 RDX: 0000000000000000 RSI: dead000000100100 RDI: ffffffff8178c620 RBP: ffff88041ef71ea8 R08: 0000000000000001 R09: 0000000000000082 R10: 0000000000000000 R11: ffff88041ef71de8 R12: 0000000000000080 R13: fffffffffffffff5 R14: 0000000000000001 R15: 0000000000610210 FS: 00007fc902f20700(0000) GS:ffff88042fd40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000008 CR3: 000000041cdb6000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process modprobe (pid: 2518, threadinfo ffff88041ef70000, task ffff88041d348040) Stack: ffff88041ef71eb8 ffffffffa0017790 ffff88041ef71eb8 ffffffffa0013532 ffff88041ef71ec8 ffffffffa00132d6 ffff88041ef71ed8 ffffffffa00159b2 ffff88041ef71f78 ffffffff81073115 656c69666f72706f 0000000000610200 Call Trace: [] op_nmi_exit+0x15/0x17 [oprofile] [] oprofile_arch_exit+0xe/0x10 [oprofile] [] oprofile_exit+0x1e/0x20 [oprofile] [] sys_delete_module+0x1c3/0x22f [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b Code: 20 c6 78 81 e8 c5 cc 23 00 48 8b 13 48 8b 43 08 48 be 00 01 10 00 00 00 ad de 48 b9 00 02 20 00 00 00 ad de 48 c7 c7 20 c6 78 81 89 42 08 48 89 10 48 89 33 48 89 4b 08 e8 a6 c0 23 00 5a 5b RIP [] unregister_syscore_ops+0x41/0x58 RSP CR2: 0000000000000008 ---[ end trace 43a541a52956b7b0 ]--- Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/init.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/oprofile/init.c b/arch/x86/oprofile/init.c index cdfe4c54dec..f148cf65267 100644 --- a/arch/x86/oprofile/init.c +++ b/arch/x86/oprofile/init.c @@ -21,6 +21,7 @@ extern int op_nmi_timer_init(struct oprofile_operations *ops); extern void op_nmi_exit(void); extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth); +static int nmi_timer; int __init oprofile_arch_init(struct oprofile_operations *ops) { @@ -31,8 +32,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) #ifdef CONFIG_X86_LOCAL_APIC ret = op_nmi_init(ops); #endif + nmi_timer = (ret != 0); #ifdef CONFIG_X86_IO_APIC - if (ret < 0) + if (nmi_timer) ret = op_nmi_timer_init(ops); #endif ops->backtrace = x86_backtrace; @@ -44,6 +46,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) void oprofile_arch_exit(void) { #ifdef CONFIG_X86_LOCAL_APIC - op_nmi_exit(); + if (!nmi_timer) + op_nmi_exit(); #endif } -- cgit v1.2.3 From 05602145e34077a8314636d15ad3dae4c7dd81e4 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 1 Dec 2011 13:32:17 +0100 Subject: add missing .set function for NT_S390_LAST_BREAK regset commit b934069c991355d27a053a932591c77960f4e414 upstream. The last breaking event address is a read-only value, the regset misses the .set function. If a PTRACE_SETREGSET is done for NT_S390_LAST_BREAK we get an oops due to a branch to zero: Kernel BUG at 0000000000000002 verbose debug info unavailable illegal operation: 0001 #1 SMP ... Call Trace: (<0000000000158294> ptrace_regset+0x184/0x188) <00000000001595b6> ptrace_request+0x37a/0x4fc <0000000000109a78> arch_ptrace+0x108/0x1fc <00000000001590d6> SyS_ptrace+0xaa/0x12c <00000000005c7a42> sysc_noemu+0x16/0x1c <000003fffd5ec10c> 0x3fffd5ec10c Last Breaking-Event-Address: <0000000000158242> ptrace_regset+0x132/0x188 Add a nop .set function to prevent the branch to zero. Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/ptrace.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index ae0e14b8880..5804cfa7cba 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -897,6 +897,14 @@ static int s390_last_break_get(struct task_struct *target, return 0; } +static int s390_last_break_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + return 0; +} + #endif static const struct user_regset s390_regsets[] = { @@ -923,6 +931,7 @@ static const struct user_regset s390_regsets[] = { .size = sizeof(long), .align = sizeof(long), .get = s390_last_break_get, + .set = s390_last_break_set, }, #endif }; @@ -1080,6 +1089,14 @@ static int s390_compat_last_break_get(struct task_struct *target, return 0; } +static int s390_compat_last_break_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + return 0; +} + static const struct user_regset s390_compat_regsets[] = { [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, @@ -1103,6 +1120,7 @@ static const struct user_regset s390_compat_regsets[] = { .size = sizeof(long), .align = sizeof(long), .get = s390_compat_last_break_get, + .set = s390_compat_last_break_set, }, [REGSET_GENERAL_EXTENDED] = { .core_note_type = NT_S390_HIGH_GPRS, -- cgit v1.2.3 From 2eca885f630f007513f9f07d9635783917bb94e2 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Wed, 30 Nov 2011 16:56:30 +0100 Subject: mac80211: fill rate filter for internal scan requests commit c72e8d335e2c6a309b6281f2abcf491f37b8b92b upstream. The rates bitmap for internal scan requests shoud be filled, otherwise there will be probe requests with zero rates supported. Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index acb44230b25..3d90dadb5d5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -742,6 +742,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (!local->int_scan_req) return -ENOMEM; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!local->hw.wiphy->bands[band]) + continue; + local->int_scan_req->rates[band] = (u32) -1; + } + /* if low-level driver supports AP, we also support VLAN */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); -- cgit v1.2.3 From 22e244d6a7b8bedfd87cba78d339b2baee00609c Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Tue, 6 Dec 2011 15:39:32 +0100 Subject: mac80211: fix race condition caused by late addBA response Upstream commit d305a6557b2c4dca0110f05ffe745b1ef94adb80. If addBA responses comes in just after addba_resp_timer has expired mac80211 will still accept it and try to open the aggregation session. This causes drivers to be confused and in some cases even crash. This patch fixes the race condition and makes sure that if addba_resp_timer has expired addBA response is not longer accepted and we do not try to open half-closed session. Signed-off-by: Nikolay Martynov [some adjustments] Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 42a59c260e8..db7db43ccf4 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -792,12 +792,27 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, goto out; } - del_timer(&tid_tx->addba_resp_timer); + del_timer_sync(&tid_tx->addba_resp_timer); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); #endif + /* + * addba_resp_timer may have fired before we got here, and + * caused WANT_STOP to be set. If the stop then was already + * processed further, STOPPING might be set. + */ + if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || + test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG + "got addBA resp for tid %d but we already gave up\n", + tid); +#endif + goto out; + } + if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) == WLAN_STATUS_SUCCESS) { /* -- cgit v1.2.3 From 5b157407b89257481a639b869f0f42532fceafaa Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 28 Nov 2011 16:47:15 -0500 Subject: cfg80211: fix race on init and driver registration commit a042994dd377d86bff9446ee76151ceb6267c9ba upstream. There is a theoretical race that if hit will trigger a crash. The race is between when we issue the first regulatory hint, regulatory_hint_core(), gets processed by the workqueue and between when the first device gets registered to the wireless core. This is not easy to reproduce but it was easy to do so through the regulatory simulator I have been working on. This is a port of the fix I implemented there [1]. [1] https://github.com/mcgrof/regsim/commit/a246ccf81f059cb662eee288aa13100f631e4cc8 Cc: Johannes Berg Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/reg.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1731e4bbfbc..3208e059540 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -57,8 +57,17 @@ #define REG_DBG_PRINT(args...) #endif +static struct regulatory_request core_request_world = { + .initiator = NL80211_REGDOM_SET_BY_CORE, + .alpha2[0] = '0', + .alpha2[1] = '0', + .intersect = false, + .processed = true, + .country_ie_env = ENVIRON_ANY, +}; + /* Receipt of information from last regulatory request */ -static struct regulatory_request *last_request; +static struct regulatory_request *last_request = &core_request_world; /* To trigger userspace events */ static struct platform_device *reg_pdev; @@ -150,7 +159,7 @@ static char user_alpha2[2]; module_param(ieee80211_regdom, charp, 0444); MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); -static void reset_regdomains(void) +static void reset_regdomains(bool full_reset) { /* avoid freeing static information or freeing something twice */ if (cfg80211_regdomain == cfg80211_world_regdom) @@ -165,6 +174,13 @@ static void reset_regdomains(void) cfg80211_world_regdom = &world_regdom; cfg80211_regdomain = NULL; + + if (!full_reset) + return; + + if (last_request != &core_request_world) + kfree(last_request); + last_request = &core_request_world; } /* @@ -175,7 +191,7 @@ static void update_world_regdomain(const struct ieee80211_regdomain *rd) { BUG_ON(!last_request); - reset_regdomains(); + reset_regdomains(false); cfg80211_world_regdom = rd; cfg80211_regdomain = rd; @@ -1396,7 +1412,8 @@ static int __regulatory_hint(struct wiphy *wiphy, } new_request: - kfree(last_request); + if (last_request != &core_request_world) + kfree(last_request); last_request = pending_request; last_request->intersect = intersect; @@ -1566,9 +1583,6 @@ static int regulatory_hint_core(const char *alpha2) { struct regulatory_request *request; - kfree(last_request); - last_request = NULL; - request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); if (!request) @@ -1766,7 +1780,7 @@ static void restore_regulatory_settings(bool reset_user) mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); - reset_regdomains(); + reset_regdomains(true); restore_alpha2(alpha2, reset_user); /* @@ -2035,7 +2049,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) int r; if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = rd; return 0; } @@ -2056,7 +2070,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) if (r) return r; - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = rd; return 0; } @@ -2081,7 +2095,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) rd = NULL; - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = intersected_rd; return 0; @@ -2101,7 +2115,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) kfree(rd); rd = NULL; - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = intersected_rd; return 0; @@ -2254,11 +2268,8 @@ void /* __init_or_exit */ regulatory_exit(void) mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); - reset_regdomains(); - - kfree(last_request); + reset_regdomains(true); - last_request = NULL; dev_set_uevent_suppress(®_pdev->dev, true); platform_device_unregister(reg_pdev); -- cgit v1.2.3 From aedebb8ae9811dedc3e57757a1048cd8d902fa3a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 28 Nov 2011 16:47:16 -0500 Subject: cfg80211: amend regulatory NULL dereference fix commit 0bac71af6e66dc798bf07d0c0dd14ee5503362f9 upstream. Johannes' patch for "cfg80211: fix regulatory NULL dereference" broke user regulaotry hints and it did not address the fact that last_request was left populated even if the previous regulatory hint was stale due to the wiphy disappearing. Fix user reguluatory hints by only bailing out if for those regulatory hints where a request_wiphy is expected. The stale last_request considerations are addressed through the previous fixes on last_request where we reset the last_request to a static world regdom request upon reset_regdomains(). In this case though we further enhance the effect by simply restoring reguluatory settings completely. Cc: Johannes Berg Signed-off-by: Luis R. Rodriguez Reviewed-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/reg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3208e059540..1bc36d250ba 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2040,8 +2040,10 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) } request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); - if (!request_wiphy) { - reg_set_request_processed(); + if (!request_wiphy && + (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || + last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) { + schedule_delayed_work(®_timeout, 0); return -ENODEV; } -- cgit v1.2.3 From a4b63ef678714a98dd8886fea14d5f76da671b6f Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 1 Dec 2011 13:55:08 +0200 Subject: genirq: Fix race condition when stopping the irq thread commit 550acb19269d65f32e9ac4ddb26c2b2070e37f1c upstream. In irq_wait_for_interrupt(), the should_stop member is verified before setting the task's state to TASK_INTERRUPTIBLE and calling schedule(). In case kthread_stop sets should_stop and wakes up the process after should_stop is checked by the irq thread but before the task's state is changed, the irq thread might never exit: kthread_stop irq_wait_for_interrupt ------------ ---------------------- ... ... while (!kthread_should_stop()) { kthread->should_stop = 1; wake_up_process(k); wait_for_completion(&kthread->exited); ... set_current_state(TASK_INTERRUPTIBLE); ... schedule(); } Fix this by checking if the thread should stop after modifying the task's state. [ tglx: Simplified it a bit ] Signed-off-by: Ido Yariv Link: http://lkml.kernel.org/r/1322740508-22640-1-git-send-email-ido@wizery.com Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/irq/manage.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 9b956fa2030..d6c4adc2804 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -620,8 +620,9 @@ static irqreturn_t irq_nested_primary_handler(int irq, void *dev_id) static int irq_wait_for_interrupt(struct irqaction *action) { + set_current_state(TASK_INTERRUPTIBLE); + while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); if (test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags)) { @@ -629,7 +630,9 @@ static int irq_wait_for_interrupt(struct irqaction *action) return 0; } schedule(); + set_current_state(TASK_INTERRUPTIBLE); } + __set_current_state(TASK_RUNNING); return -1; } -- cgit v1.2.3 From 3e4f16a375aafec68144d4edaae4ebd8e5017571 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 28 Nov 2011 21:12:40 +0100 Subject: slab, lockdep: Fix silly bug commit 52cef189165d74a5d6030184a8e05595194c69ca upstream. Commit 30765b92 ("slab, lockdep: Annotate the locks before using them") moves the init_lock_keys() call from after g_cpucache_up = FULL, to before it. And overlooks the fact that init_node_lock_keys() tests for it and ignores everything !FULL. Introduce a LATE stage and change the lockdep test to be Cc: Pekka Enberg Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- mm/slab.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm/slab.c b/mm/slab.c index 6d90a091fdc..893c76df924 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -595,6 +595,7 @@ static enum { PARTIAL_AC, PARTIAL_L3, EARLY, + LATE, FULL } g_cpucache_up; @@ -671,7 +672,7 @@ static void init_node_lock_keys(int q) { struct cache_sizes *s = malloc_sizes; - if (g_cpucache_up != FULL) + if (g_cpucache_up < LATE) return; for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) { @@ -1666,6 +1667,8 @@ void __init kmem_cache_init_late(void) { struct kmem_cache *cachep; + g_cpucache_up = LATE; + /* Annotate slab for lockdep -- annotate the malloc caches */ init_lock_keys(); -- cgit v1.2.3 From 43c308bd8d0a3e7d98c5abcd41a4a3fada3d198f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 2 Dec 2011 08:19:18 -0800 Subject: iwlwifi: do not re-configure HT40 after associated commit 34a5b4b6af104cf18eb50748509528b9bdbc4036 upstream. The ht40 setting should not change after association unless channel switch This fix a problem we are seeing which cause uCode assert because driver sending invalid information and make uCode confuse Here is the firmware assert message: kernel: iwlagn 0000:03:00.0: Microcode SW error detected. Restarting 0x82000000. kernel: iwlagn 0000:03:00.0: Loaded firmware version: 17.168.5.3 build 42301 kernel: iwlagn 0000:03:00.0: Start IWL Error Log Dump: kernel: iwlagn 0000:03:00.0: Status: 0x000512E4, count: 6 kernel: iwlagn 0000:03:00.0: 0x00002078 | ADVANCED_SYSASSERT kernel: iwlagn 0000:03:00.0: 0x00009514 | uPc kernel: iwlagn 0000:03:00.0: 0x00009496 | branchlink1 kernel: iwlagn 0000:03:00.0: 0x00009496 | branchlink2 kernel: iwlagn 0000:03:00.0: 0x0000D1F2 | interruptlink1 kernel: iwlagn 0000:03:00.0: 0x00000000 | interruptlink2 kernel: iwlagn 0000:03:00.0: 0x01008035 | data1 kernel: iwlagn 0000:03:00.0: 0x0000C90F | data2 kernel: iwlagn 0000:03:00.0: 0x000005A7 | line kernel: iwlagn 0000:03:00.0: 0x5080B520 | beacon time kernel: iwlagn 0000:03:00.0: 0xCC515AE0 | tsf low kernel: iwlagn 0000:03:00.0: 0x00000003 | tsf hi kernel: iwlagn 0000:03:00.0: 0x00000000 | time gp1 kernel: iwlagn 0000:03:00.0: 0x29703BF0 | time gp2 kernel: iwlagn 0000:03:00.0: 0x00000000 | time gp3 kernel: iwlagn 0000:03:00.0: 0x000111A8 | uCode version kernel: iwlagn 0000:03:00.0: 0x000000B0 | hw version kernel: iwlagn 0000:03:00.0: 0x00480303 | board version kernel: iwlagn 0000:03:00.0: 0x09E8004E | hcmd kernel: iwlagn 0000:03:00.0: CSR values: kernel: iwlagn 0000:03:00.0: (2nd byte of CSR_INT_COALESCING is CSR_INT_PERIODIC_REG) kernel: iwlagn 0000:03:00.0: CSR_HW_IF_CONFIG_REG: 0X00480303 kernel: iwlagn 0000:03:00.0: CSR_INT_COALESCING: 0X0000ff40 kernel: iwlagn 0000:03:00.0: CSR_INT: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_INT_MASK: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_FH_INT_STATUS: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_GPIO_IN: 0X00000030 kernel: iwlagn 0000:03:00.0: CSR_RESET: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_GP_CNTRL: 0X080403c5 kernel: iwlagn 0000:03:00.0: CSR_HW_REV: 0X000000b0 kernel: iwlagn 0000:03:00.0: CSR_EEPROM_REG: 0X07d60ffd kernel: iwlagn 0000:03:00.0: CSR_EEPROM_GP: 0X90000001 kernel: iwlagn 0000:03:00.0: CSR_OTP_GP_REG: 0X00030001 kernel: iwlagn 0000:03:00.0: CSR_GIO_REG: 0X00080044 kernel: iwlagn 0000:03:00.0: CSR_GP_UCODE_REG: 0X000093bb kernel: iwlagn 0000:03:00.0: CSR_GP_DRIVER_REG: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_UCODE_DRV_GP1: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_UCODE_DRV_GP2: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_LED_REG: 0X00000078 kernel: iwlagn 0000:03:00.0: CSR_DRAM_INT_TBL_REG: 0X88214dd2 kernel: iwlagn 0000:03:00.0: CSR_GIO_CHICKEN_BITS: 0X27800200 kernel: iwlagn 0000:03:00.0: CSR_ANA_PLL_CFG: 0X00000000 kernel: iwlagn 0000:03:00.0: CSR_HW_REV_WA_REG: 0X0001001a kernel: iwlagn 0000:03:00.0: CSR_DBG_HPET_MEM_REG: 0Xffff0010 kernel: iwlagn 0000:03:00.0: FH register values: kernel: iwlagn 0000:03:00.0: FH_RSCSR_CHNL0_STTS_WPTR_REG: 0X21316d00 kernel: iwlagn 0000:03:00.0: FH_RSCSR_CHNL0_RBDCB_BASE_REG: 0X021479c0 kernel: iwlagn 0000:03:00.0: FH_RSCSR_CHNL0_WPTR: 0X00000060 kernel: iwlagn 0000:03:00.0: FH_MEM_RCSR_CHNL0_CONFIG_REG: 0X80819104 kernel: iwlagn 0000:03:00.0: FH_MEM_RSSR_SHARED_CTRL_REG: 0X000000fc kernel: iwlagn 0000:03:00.0: FH_MEM_RSSR_RX_STATUS_REG: 0X07030000 kernel: iwlagn 0000:03:00.0: FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV: 0X00000000 kernel: iwlagn 0000:03:00.0: FH_TSSR_TX_STATUS_REG: 0X07ff0001 kernel: iwlagn 0000:03:00.0: FH_TSSR_TX_ERROR_REG: 0X00000000 kernel: iwlagn 0000:03:00.0: Start IWL Event Log Dump: display last 20 entries kernel: ------------[ cut here ]------------ WARNING: at net/mac80211/util.c:1208 ieee80211_reconfig+0x1f1/0x407() kernel: Hardware name: 4290W4H kernel: Pid: 1896, comm: kworker/0:0 Not tainted 3.1.0 #2 kernel: Call Trace: kernel: [] ? warn_slowpath_common+0x73/0x87 kernel: [] ? ieee80211_reconfig+0x1f1/0x407 kernel: [] ? ieee80211_recalc_smps_work+0x32/0x32 kernel: [] ? ieee80211_restart_work+0x7e/0x87 kernel: [] ? process_one_work+0x1c8/0x2e3 kernel: [] ? worker_thread+0x17a/0x23a kernel: [] ? manage_workers.clone.18+0x15b/0x15b kernel: [] ? manage_workers.clone.18+0x15b/0x15b kernel: [] ? kthread+0x7a/0x82 kernel: [] ? kernel_thread_helper+0x4/0x10 kernel: [] ? kthread_flush_work_fn+0x11/0x11 kernel: [] ? gs_change+0xb/0xb Reported-by: Udo Steinberg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 36 ++++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-agn.c | 18 +++------------ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 ++ 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index a7ddc9897a1..eabbf1a128e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -542,6 +542,24 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) return 0; } +void iwlagn_config_ht40(struct ieee80211_conf *conf, + struct iwl_rxon_context *ctx) +{ + if (conf_is_ht40_minus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ctx->ht.is_40mhz = true; + } else if (conf_is_ht40_plus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ctx->ht.is_40mhz = true; + } else { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ctx->ht.is_40mhz = false; + } +} + int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) { struct iwl_priv *priv = hw->priv; @@ -600,19 +618,11 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) ctx->ht.enabled = conf_is_ht(conf); if (ctx->ht.enabled) { - if (conf_is_ht40_minus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ctx->ht.is_40mhz = true; - } else if (conf_is_ht40_plus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ctx->ht.is_40mhz = true; - } else { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_NONE; - ctx->ht.is_40mhz = false; - } + /* if HT40 is used, it should not change + * after associated except channel switch */ + if (iwl_is_associated_ctx(ctx) && + !ctx->ht.is_40mhz) + iwlagn_config_ht40(conf, ctx); } else ctx->ht.is_40mhz = false; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f9c3cd95d61..83cceb0d2ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3075,21 +3075,9 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, /* Configure HT40 channels */ ctx->ht.enabled = conf_is_ht(conf); - if (ctx->ht.enabled) { - if (conf_is_ht40_minus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ctx->ht.is_40mhz = true; - } else if (conf_is_ht40_plus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ctx->ht.is_40mhz = true; - } else { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_NONE; - ctx->ht.is_40mhz = false; - } - } else + if (ctx->ht.enabled) + iwlagn_config_ht40(conf, ctx); + else ctx->ht.is_40mhz = false; if ((le16_to_cpu(ctx->staging.channel) != ch)) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index d941c4c98e4..e172f6baad3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -135,6 +135,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); +void iwlagn_config_ht40(struct ieee80211_conf *conf, + struct iwl_rxon_context *ctx); /* uCode */ void iwlagn_rx_calib_result(struct iwl_priv *priv, -- cgit v1.2.3 From 5c30a5b33f77264cddcfb1a6659d3a9ac2661103 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 2 Dec 2011 08:19:17 -0800 Subject: iwlagn: fix HW crypto for TX-only keys commit 274b89ca3b006926cb9b45d78ab5906f4c0fc0aa upstream. Group keys in IBSS or AP mode are not programmed into the device since we give the key to it with every TX packet. However, we do need mac80211 to create the MMIC & PN in all cases. Move the code around to set the key flags all the time. We set them even when the key is removed again but that is obviously harmless. Reported-by: Reinette Chatre Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 37e624095e4..211a5ad6a4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -440,9 +440,6 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, switch (keyconf->cipher) { case WLAN_CIPHER_SUITE_TKIP: - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - if (sta) addr = sta->addr; else /* station mode case only */ @@ -455,8 +452,6 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, seq.tkip.iv32, p1k, CMD_SYNC); break; case WLAN_CIPHER_SUITE_CCMP: - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - /* fall through */ case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: ret = iwlagn_send_sta_key(priv, keyconf, sta_id, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 83cceb0d2ba..f473c019c64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2793,6 +2793,17 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + /* fall through */ + case WLAN_CIPHER_SUITE_CCMP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + break; + default: + break; + } + /* * We could program these keys into the hardware as well, but we * don't expect much multicast traffic in IBSS and having keys -- cgit v1.2.3 From 03923350d5fbcdb23faca8c9ca55988aac7383c3 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 4 Nov 2011 10:45:23 -0400 Subject: ftrace: Remove force undef config value left for testing commit c7c6ec8becaf742b223c7b491f4893014be23a07 upstream. A forced undef of a config value was used for testing and was accidently left in during the final commit. This causes x86 to run slower than needed while running function tracing as well as causes the function graph selftest to fail when DYNMAIC_FTRACE is not set. This is because the code in MCOUNT expects the ftrace code to be processed with the config value set that happened to be forced not set. The forced config option was left in by: commit 6331c28c962561aee59e5a493b7556a4bb585957 ftrace: Fix dynamic selftest failure on some archs Link: http://lkml.kernel.org/r/20111102150255.GA6973@debian Reported-by: Rabin Vincent Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ftrace.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index c3e4575e782..48d3762b828 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -151,7 +151,6 @@ void clear_ftrace_function(void) ftrace_pid_function = ftrace_stub; } -#undef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST /* * For those archs that do not test ftrace_trace_stop in their -- cgit v1.2.3 From bf34b36a208ecca76e41814ff8837f8b41528248 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 23 Nov 2011 08:49:49 -0800 Subject: trace_events_filter: Use rcu_assign_pointer() when setting ftrace_event_call->filter commit d3d9acf646679c1981032b0985b386d12fccc60c upstream. ftrace_event_call->filter is sched RCU protected but didn't use rcu_assign_pointer(). Use it. TODO: Add proper __rcu annotation to call->filter and all its users. -v2: Use RCU_INIT_POINTER() for %NULL clearing as suggested by Eric. Link: http://lkml.kernel.org/r/20111123164949.GA29639@google.com Cc: Eric Dumazet Cc: Frederic Weisbecker Cc: Jiri Olsa Signed-off-by: Tejun Heo Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace_events_filter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 256764ecccd..bd3c6369f80 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1766,7 +1766,7 @@ static int replace_system_preds(struct event_subsystem *system, * replace the filter for the call. */ filter = call->filter; - call->filter = filter_item->filter; + rcu_assign_pointer(call->filter, filter_item->filter); filter_item->filter = filter; fail = false; @@ -1821,7 +1821,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) filter = call->filter; if (!filter) goto out_unlock; - call->filter = NULL; + RCU_INIT_POINTER(call->filter, NULL); /* Make sure the filter is not being used */ synchronize_sched(); __free_filter(filter); @@ -1862,7 +1862,7 @@ out: * string */ tmp = call->filter; - call->filter = filter; + rcu_assign_pointer(call->filter, filter); if (tmp) { /* Make sure the call is done with the filter */ synchronize_sched(); -- cgit v1.2.3 From 0cbc008c56f7b4a11ba6fe80e196d7ab322baabf Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 22 Nov 2011 11:03:14 +0100 Subject: rtc: Disable the alarm in the hardware commit c0afabd3d553c521e003779c127143ffde55a16f upstream. Currently, the RTC code does not disable the alarm in the hardware. This means that after a sequence such as the one below (the files are in the RTC sysfs), the box will boot up after 2 minutes even though we've asked for the alarm to be turned off. # echo $((`cat since_epoch`)+120) > wakealarm # echo 0 > wakealarm # poweroff Fix this by disabling the alarm when there are no timers to run. Cc: John Stultz Signed-off-by: Rabin Vincent Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/interface.c | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 44e91e598f8..3d9d2b97656 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -318,6 +318,20 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_read_alarm); +static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) +{ + int err; + + if (!rtc->ops) + err = -ENODEV; + else if (!rtc->ops->set_alarm) + err = -EINVAL; + else + err = rtc->ops->set_alarm(rtc->dev.parent, alarm); + + return err; +} + static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { struct rtc_time tm; @@ -341,14 +355,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) * over right here, before we set the alarm. */ - if (!rtc->ops) - err = -ENODEV; - else if (!rtc->ops->set_alarm) - err = -EINVAL; - else - err = rtc->ops->set_alarm(rtc->dev.parent, alarm); - - return err; + return ___rtc_set_alarm(rtc, alarm); } int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) @@ -762,6 +769,20 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) return 0; } +static void rtc_alarm_disable(struct rtc_device *rtc) +{ + struct rtc_wkalrm alarm; + struct rtc_time tm; + + __rtc_read_time(rtc, &tm); + + alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm), + ktime_set(300, 0))); + alarm.enabled = 0; + + ___rtc_set_alarm(rtc, &alarm); +} + /** * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue * @rtc rtc device @@ -783,8 +804,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) struct rtc_wkalrm alarm; int err; next = timerqueue_getnext(&rtc->timerqueue); - if (!next) + if (!next) { + rtc_alarm_disable(rtc); return; + } alarm.time = rtc_ktime_to_tm(next->expires); alarm.enabled = 1; err = __rtc_set_alarm(rtc, &alarm); @@ -846,7 +869,8 @@ again: err = __rtc_set_alarm(rtc, &alarm); if (err == -ETIME) goto again; - } + } else + rtc_alarm_disable(rtc); mutex_unlock(&rtc->ops_lock); } -- cgit v1.2.3 From df9490f1a5f1019ebf36bd7820ff405ddc06bfa9 Mon Sep 17 00:00:00 2001 From: Arve Hjønnevåg Date: Tue, 22 Nov 2011 18:24:51 -0800 Subject: rtc: Fix some bugs that allowed accumulating time drift in suspend/resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6a8943d9ec2567572fca25cf69ad45844d0141a3 upstream. The current code checks if abs(delta_delta.tv_sec) is greater or equal to two before it discards the old delta value, but this can trigger at close to -1 seconds since -1.000000001 seconds is stored as tv_sec -2 and tv_nsec 999999999 in a normalized timespec. rtc_resume had an early return check if the rtc value had not changed since rtc_suspend. This effectivly stops time for the duration of the short sleep. Check if sleep_time is positive after all the adjustments have been applied instead since this allows the old_system adjustment in rtc_suspend to have an effect even for short sleep cycles. Signed-off-by: Arve Hjønnevåg Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/class.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 01a7df5317c..b82a1554cdc 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -66,7 +66,7 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg) */ delta = timespec_sub(old_system, old_rtc); delta_delta = timespec_sub(delta, old_delta); - if (abs(delta_delta.tv_sec) >= 2) { + if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) { /* * if delta_delta is too large, assume time correction * has occured and set old_delta to the current delta. @@ -100,9 +100,8 @@ static int rtc_resume(struct device *dev) rtc_tm_to_time(&tm, &new_rtc.tv_sec); new_rtc.tv_nsec = 0; - if (new_rtc.tv_sec <= old_rtc.tv_sec) { - if (new_rtc.tv_sec < old_rtc.tv_sec) - pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); + if (new_rtc.tv_sec < old_rtc.tv_sec) { + pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); return 0; } @@ -119,7 +118,8 @@ static int rtc_resume(struct device *dev) sleep_time = timespec_sub(sleep_time, timespec_sub(new_system, old_system)); - timekeeping_inject_sleeptime(&sleep_time); + if (sleep_time.tv_sec >= 0) + timekeeping_inject_sleeptime(&sleep_time); return 0; } -- cgit v1.2.3 From fedb66b50d774dc687ac5b6f78fbf4b9bee28865 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Mon, 31 Oct 2011 11:07:42 +0200 Subject: tracing: fix event_subsystem ref counting commit cb59974742aea24adf6637eb0c4b8e7b48bca6fb upstream. Fix a bug introduced by e9dbfae5, which prevents event_subsystem from ever being released. Ref_count was added to keep track of subsystem users, not for counting events. Subsystem is created with ref_count = 1, so there is no need to increment it for every event, we have nr_events for that. Fix this by touching ref_count only when we actually have a new user - subsystem_open(). Signed-off-by: Ilya Dryomov Link: http://lkml.kernel.org/r/1320052062-7846-1-git-send-email-idryomov@gmail.com Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace_events.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 581876f9f38..c212a7f934e 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1078,7 +1078,6 @@ event_subsystem_dir(const char *name, struct dentry *d_events) /* First see if we did not already create this dir */ list_for_each_entry(system, &event_subsystems, list) { if (strcmp(system->name, name) == 0) { - __get_system(system); system->nr_events++; return system->entry; } -- cgit v1.2.3 From 491d3a9bc2ee7ad349a2e03bf259dea8895a5edd Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 2 Dec 2011 12:34:16 +0100 Subject: tick-broadcast: Stop active broadcast device when replacing it commit c1be84309c58b1e7c6d626e28fba41a22b364c3d upstream. When a better rated broadcast device is installed, then the current active device is not disabled, which results in two running broadcast devices. Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/time/tick-broadcast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index c7218d13273..7a90d021b79 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -71,7 +71,7 @@ int tick_check_broadcast_device(struct clock_event_device *dev) (dev->features & CLOCK_EVT_FEAT_C3STOP)) return 0; - clockevents_exchange_device(NULL, dev); + clockevents_exchange_device(tick_broadcast_device.evtdev, dev); tick_broadcast_device.evtdev = dev; if (!cpumask_empty(tick_get_broadcast_mask())) tick_broadcast_start_periodic(dev); -- cgit v1.2.3 From 6bdf07f3dd1c2874792bb07cd84d4210cbc15ca7 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 4 Nov 2011 16:32:25 -0400 Subject: perf: Fix parsing of __print_flags() in TP_printk() commit d06c27b22aa66e48e32f03f9387328a9af9b0625 upstream. A update is made to the sched:sched_switch event that adds some logic to the first parameter of the __print_flags() that shows the state of tasks. This change cause perf to fail parsing the flags. A simple fix is needed to have the parser be able to process ops within the argument. Reported-by: Andrew Vagin Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/trace-event-parse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 0a7ed5b5e28..6c164dc9ee9 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -1537,6 +1537,8 @@ process_flags(struct event *event, struct print_arg *arg, char **tok) field = malloc_or_die(sizeof(*field)); type = process_arg(event, field, &token); + while (type == EVENT_OP) + type = process_op(event, field, &token); if (test_type_token(type, token, EVENT_DELIM, ",")) goto out_free; -- cgit v1.2.3 From cf246087a19a4958fba3123d21f1359b6177ddb5 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Tue, 18 Oct 2011 19:55:51 +0200 Subject: jump_label: jump_label_inc may return before the code is patched commit bbbf7af4bf8fc69bc751818cf30521080fa47dcb upstream. If cpu A calls jump_label_inc() just after atomic_add_return() is called by cpu B, atomic_inc_not_zero() will return value greater then zero and jump_label_inc() will return to a caller before jump_label_update() finishes its job on cpu B. Link: http://lkml.kernel.org/r/20111018175551.GH17571@redhat.com Cc: Peter Zijlstra Acked-by: Jason Baron Signed-off-by: Gleb Natapov Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman --- kernel/jump_label.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/jump_label.c b/kernel/jump_label.c index a8ce45097f3..e6f1f24ad57 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -66,8 +66,9 @@ void jump_label_inc(struct jump_label_key *key) return; jump_label_lock(); - if (atomic_add_return(1, &key->enabled) == 1) + if (atomic_read(&key->enabled) == 0) jump_label_update(key, JUMP_LABEL_ENABLE); + atomic_inc(&key->enabled); jump_label_unlock(); } -- cgit v1.2.3 From 3e31d12fa35d8328128ef672a933ab6b8e09e10b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Fri, 7 Oct 2011 16:31:46 +0200 Subject: oprofile: Fix crash when unloading module (hr timer mode) commit 87121ca504fd1d963a66b3fb0c72054b0fd9a177 upstream. Oprofile may crash in a KVM guest while unlaoding modules. This happens if oprofile_arch_init() fails and oprofile switches to the hr timer mode as a fallback. In this case oprofile_arch_exit() is called, but it never was initialized properly which causes the crash. This patch fixes this. oprofile: using timer interrupt. BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 IP: [] unregister_syscore_ops+0x41/0x58 PGD 41da3f067 PUD 41d80e067 PMD 0 Oops: 0002 [#1] PREEMPT SMP CPU 5 Modules linked in: oprofile(-) Pid: 2382, comm: modprobe Not tainted 3.1.0-rc7-00018-g709a39d #18 Advanced Micro Device Anaheim/Anaheim RIP: 0010:[] [] unregister_syscore_ops+0x41/0x58 RSP: 0018:ffff88041de1de98 EFLAGS: 00010296 RAX: 0000000000000000 RBX: ffffffffa00060e0 RCX: dead000000200200 RDX: 0000000000000000 RSI: dead000000100100 RDI: ffffffff8178c620 RBP: ffff88041de1dea8 R08: 0000000000000001 R09: 0000000000000082 R10: 0000000000000000 R11: ffff88041de1dde8 R12: 0000000000000080 R13: fffffffffffffff5 R14: 0000000000000001 R15: 0000000000610210 FS: 00007f9ae5bef700(0000) GS:ffff88042fd40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000008 CR3: 000000041ca44000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process modprobe (pid: 2382, threadinfo ffff88041de1c000, task ffff88042db6d040) Stack: ffff88041de1deb8 ffffffffa0006770 ffff88041de1deb8 ffffffffa000251e ffff88041de1dec8 ffffffffa00022c2 ffff88041de1ded8 ffffffffa0004993 ffff88041de1df78 ffffffff81073115 656c69666f72706f 0000000000610200 Call Trace: [] op_nmi_exit+0x15/0x17 [oprofile] [] oprofile_arch_exit+0xe/0x10 [oprofile] [] oprofile_exit+0x13/0x15 [oprofile] [] sys_delete_module+0x1c3/0x22f [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b Code: 20 c6 78 81 e8 c5 cc 23 00 48 8b 13 48 8b 43 08 48 be 00 01 10 00 00 00 ad de 48 b9 00 02 20 00 00 00 ad de 48 c7 c7 20 c6 78 81 89 42 08 48 89 10 48 89 33 48 89 4b 08 e8 a6 c0 23 00 5a 5b RIP [] unregister_syscore_ops+0x41/0x58 RSP CR2: 0000000000000008 ---[ end trace 06d4e95b6aa3b437 ]--- Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- drivers/oprofile/oprof.c | 29 ++++++++++++++++++++++++----- drivers/oprofile/timer_int.c | 1 + 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index dccd8636095..f8c752e408a 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -239,26 +239,45 @@ int oprofile_set_ulong(unsigned long *addr, unsigned long val) return err; } +static int timer_mode; + static int __init oprofile_init(void) { int err; + /* always init architecture to setup backtrace support */ err = oprofile_arch_init(&oprofile_ops); - if (err < 0 || timer) { - printk(KERN_INFO "oprofile: using timer interrupt.\n"); + + timer_mode = err || timer; /* fall back to timer mode on errors */ + if (timer_mode) { + if (!err) + oprofile_arch_exit(); err = oprofile_timer_init(&oprofile_ops); if (err) return err; } - return oprofilefs_register(); + + err = oprofilefs_register(); + if (!err) + return 0; + + /* failed */ + if (timer_mode) + oprofile_timer_exit(); + else + oprofile_arch_exit(); + + return err; } static void __exit oprofile_exit(void) { - oprofile_timer_exit(); oprofilefs_unregister(); - oprofile_arch_exit(); + if (timer_mode) + oprofile_timer_exit(); + else + oprofile_arch_exit(); } diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 3ef44624f51..878fba12658 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -110,6 +110,7 @@ int oprofile_timer_init(struct oprofile_operations *ops) ops->start = oprofile_hrtimer_start; ops->stop = oprofile_hrtimer_stop; ops->cpu_type = "timer"; + printk(KERN_INFO "oprofile: using timer interrupt.\n"); return 0; } -- cgit v1.2.3 From 5a643352d2166077f88180372431ea5e90212b15 Mon Sep 17 00:00:00 2001 From: "Yang Honggang (Joseph)" Date: Thu, 1 Dec 2011 22:22:41 -0500 Subject: clocksource: Fix bug with max_deferment margin calculation commit b1f919664d04a8d0ba29cb76673c7ca3325a2006 upstream. In order to leave a margin of 12.5% we should >> 3 not >> 5. Signed-off-by: Yang Honggang (Joseph) [jstultz: Modified commit subject] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- kernel/time/clocksource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 8277439b004..8f77da18fef 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -550,7 +550,7 @@ static u64 clocksource_max_deferment(struct clocksource *cs) * note a margin of 12.5% is used because this can be computed with * a shift, versus say 10% which would require division. */ - return max_nsecs - (max_nsecs >> 5); + return max_nsecs - (max_nsecs >> 3); } #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET @@ -671,7 +671,7 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) * ~ 0.06ppm granularity for NTP. We apply the same 12.5% * margin as we do in clocksource_max_deferment() */ - sec = (cs->mask - (cs->mask >> 5)); + sec = (cs->mask - (cs->mask >> 3)); do_div(sec, freq); do_div(sec, scale); if (!sec) -- cgit v1.2.3 From aeed6baa702a285cf03b7dc4182ffc1a7f4e4ed6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 2 Dec 2011 16:02:45 +0100 Subject: clockevents: Set noop handler in clockevents_exchange_device() commit de28f25e8244c7353abed8de0c7792f5f883588c upstream. If a device is shutdown, then there might be a pending interrupt, which will be processed after we reenable interrupts, which causes the original handler to be run. If the old handler is the (broadcast) periodic handler the shutdown state might hang the kernel completely. Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/time/clockevents.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index e4c699dfa4e..13dfaaba406 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -286,6 +286,7 @@ void clockevents_exchange_device(struct clock_event_device *old, * released list and do a notify add later. */ if (old) { + old->event_handler = clockevents_handle_noop; clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); list_del(&old->list); list_add(&old->list, &clockevents_released); -- cgit v1.2.3 From cfa73cca0cac4e07cc963f332aead8d118707432 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Tue, 8 Nov 2011 12:12:44 +0000 Subject: ah: Correctly pass error codes in ahash output callback. [ Upstream commit 069294e813ed5f27f82613b027609bcda5f1b914 ] The AH4/6 ahash output callbacks pass nexthdr to xfrm_output_resume instead of the error code. This appears to be a copy+paste error from the input case, where nexthdr is expected. This causes the driver to continuously add AH headers to the datagram until either an allocation fails and the packet is dropped or the ahash driver hits a synchronous fallback and the resulting monstrosity is transmitted. Correct this issue by simply passing the error code unadulterated. Signed-off-by: Nick Bowler Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ah4.c | 2 -- net/ipv6/ah6.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index c1f4154552f..33ca18603e3 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -136,8 +136,6 @@ static void ah_output_done(struct crypto_async_request *base, int err) memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr)); } - err = ah->nexthdr; - kfree(AH_SKB_CB(skb)->tmp); xfrm_output_resume(skb, err); } diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 2195ae65192..ede4d9d6cc2 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -324,8 +324,6 @@ static void ah6_output_done(struct crypto_async_request *base, int err) #endif } - err = ah->nexthdr; - kfree(AH_SKB_CB(skb)->tmp); xfrm_output_resume(skb, err); } -- cgit v1.2.3 From f82c753512bfe2fb4127ee72c882924120c11de8 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Tue, 8 Nov 2011 12:12:45 +0000 Subject: ah: Read nexthdr value before overwriting it in ahash input callback. [ Upstream commit b7ea81a58adc123a4e980cb0eff9eb5c144b5dc7 ] The AH4/6 ahash input callbacks read out the nexthdr field from the AH header *after* they overwrite that header. This is obviously not going to end well. Fix it up. Signed-off-by: Nick Bowler Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ah4.c | 4 ++-- net/ipv6/ah6.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 33ca18603e3..c7056b2e831 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -262,12 +262,12 @@ static void ah_input_done(struct crypto_async_request *base, int err) if (err) goto out; + err = ah->nexthdr; + skb->network_header += ah_hlen; memcpy(skb_network_header(skb), work_iph, ihl); __skb_pull(skb, ah_hlen + ihl); skb_set_transport_header(skb, -ihl); - - err = ah->nexthdr; out: kfree(AH_SKB_CB(skb)->tmp); xfrm_input_resume(skb, err); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index ede4d9d6cc2..7a33aaa0022 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -464,12 +464,12 @@ static void ah6_input_done(struct crypto_async_request *base, int err) if (err) goto out; + err = ah->nexthdr; + skb->network_header += ah_hlen; memcpy(skb_network_header(skb), work_iph, hdr_len); __skb_pull(skb, ah_hlen + hdr_len); skb_set_transport_header(skb, -hdr_len); - - err = ah->nexthdr; out: kfree(AH_SKB_CB(skb)->tmp); xfrm_input_resume(skb, err); -- cgit v1.2.3 From db9a8a29b0c7c61b372300978fbe8b01606103f0 Mon Sep 17 00:00:00 2001 From: Li Wei Date: Tue, 8 Nov 2011 21:39:28 +0000 Subject: ipv4: fix for ip_options_rcv_srr() daddr update. [ Upstream commit b12f62efb8ec0b9523bdb6c2d412c07193086de9 ] When opt->srr_is_hit is set skb_rtable(skb) has been updated for 'nexthop' and iph->daddr should always equals to skb_rtable->rt_dst holds, We need update iph->daddr either. Signed-off-by: Li Wei Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_options.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index ec93335901d..05d20cca9d6 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -640,6 +640,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) } if (srrptr <= srrspace) { opt->srr_is_hit = 1; + iph->daddr = nexthop; opt->is_changed = 1; } return 0; -- cgit v1.2.3 From f667de2e66ea9b8f99353ff01221bb355faf3f3c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 29 Nov 2011 20:05:55 +0000 Subject: ipv4: fix lockdep splat in rt_cache_seq_show [ Upstream commit 218fa90f072e4aeff9003d57e390857f4f35513e ] After commit f2c31e32b378 (fix NULL dereferences in check_peer_redir()), dst_get_neighbour() should be guarded by rcu_read_lock() / rcu_read_unlock() section. Reported-by: Miles Lane Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 075212e41b8..8b3661b3cda 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -417,9 +417,13 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) else { struct rtable *r = v; struct neighbour *n; - int len; + int len, HHUptod; + rcu_read_lock(); n = dst_get_neighbour(&r->dst); + HHUptod = (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0; + rcu_read_unlock(); + seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", r->dst.dev ? r->dst.dev->name : "*", @@ -433,7 +437,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) dst_metric(&r->dst, RTAX_RTTVAR)), r->rt_key_tos, -1, - (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0, + HHUptod, r->rt_spec_dst, &len); seq_printf(seq, "%*s\n", 127 - len, ""); -- cgit v1.2.3 From e03d2dc771361ff27ca042b793fa34b27bd6f115 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Tue, 15 Nov 2011 02:31:15 +0000 Subject: qeth: l3 fix rcu splat in xmit [ Upstream commit 1d36cb479f204a0fedc1a3e7ce7b32c0a2c48769 ] when use dst_get_neighbour to get neighbour, we need rcu_read_lock to protect, since dst_get_neighbour uses rcu_dereference. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/s390/net/qeth_l3_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index fafb8c29954..c74e8670fab 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2740,11 +2740,13 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) struct neighbour *n = NULL; struct dst_entry *dst; + rcu_read_lock(); dst = skb_dst(skb); if (dst) n = dst_get_neighbour(dst); if (n) { cast_type = n->type; + rcu_read_unlock(); if ((cast_type == RTN_BROADCAST) || (cast_type == RTN_MULTICAST) || (cast_type == RTN_ANYCAST)) @@ -2752,6 +2754,8 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) else return RTN_UNSPEC; } + rcu_read_unlock(); + /* try something else */ if (skb->protocol == ETH_P_IPV6) return (skb_network_header(skb)[24] == 0xff) ? @@ -2807,6 +2811,8 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, } hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr); + + rcu_read_lock(); dst = skb_dst(skb); if (dst) n = dst_get_neighbour(dst); @@ -2853,6 +2859,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, QETH_CAST_UNICAST | QETH_HDR_PASSTHRU; } } + rcu_read_unlock(); } static inline void qeth_l3_hdr_csum(struct qeth_card *card, -- cgit v1.2.3 From 5eb027bb82d1f9d4af0df73a3ce08945ffc1b481 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 30 Nov 2011 04:08:58 +0000 Subject: sch_teql: fix lockdep splat [ Upstream commit f7e57044eeb1841847c24aa06766c8290c202583 ] We need rcu_read_lock() protection before using dst_get_neighbour(), and we must cache its value (pass it to __teql_resolve()) teql_master_xmit() is called under rcu_read_lock_bh() protection, its not enough. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_teql.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index a3b7120fcc7..4f4c52c0eeb 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -225,11 +225,11 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt) static int -__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) +__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, + struct net_device *dev, struct netdev_queue *txq, + struct neighbour *mn) { - struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0); - struct teql_sched_data *q = qdisc_priv(dev_queue->qdisc); - struct neighbour *mn = dst_get_neighbour(skb_dst(skb)); + struct teql_sched_data *q = qdisc_priv(txq->qdisc); struct neighbour *n = q->ncache; if (mn->tbl == NULL) @@ -262,17 +262,26 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device * } static inline int teql_resolve(struct sk_buff *skb, - struct sk_buff *skb_res, struct net_device *dev) + struct sk_buff *skb_res, + struct net_device *dev, + struct netdev_queue *txq) { - struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); + struct dst_entry *dst = skb_dst(skb); + struct neighbour *mn; + int res; + if (txq->qdisc == &noop_qdisc) return -ENODEV; - if (dev->header_ops == NULL || - skb_dst(skb) == NULL || - dst_get_neighbour(skb_dst(skb)) == NULL) + if (!dev->header_ops || !dst) return 0; - return __teql_resolve(skb, skb_res, dev); + + rcu_read_lock(); + mn = dst_get_neighbour(dst); + res = mn ? __teql_resolve(skb, skb_res, dev, txq, mn) : 0; + rcu_read_unlock(); + + return res; } static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) @@ -307,7 +316,7 @@ restart: continue; } - switch (teql_resolve(skb, skb_res, slave)) { + switch (teql_resolve(skb, skb_res, slave, slave_txq)) { case 0: if (__netif_tx_trylock(slave_txq)) { unsigned int length = qdisc_pkt_len(skb); -- cgit v1.2.3 From fe421e849a3c36373dd59eb5f302705c91a14719 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Wed, 19 Oct 2011 15:34:09 +0000 Subject: ipv4: avoid useless call of the function check_peer_pmtu [ Upstream commit 59445b6b1f90b97c4e28062b96306bacfa4fb170 ] In func ipv4_dst_check,check_peer_pmtu should be called only when peer is updated. So,if the peer is not updated in ip_rt_frag_needed,we can not inc __rt_peer_genid. Signed-off-by: Gao feng Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 8b3661b3cda..c3fcdb4fe2d 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1572,11 +1572,10 @@ unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph, est_mtu = mtu; peer->pmtu_learned = mtu; peer->pmtu_expires = pmtu_expires; + atomic_inc(&__rt_peer_genid); } inet_putpeer(peer); - - atomic_inc(&__rt_peer_genid); } return est_mtu ? : new_mtu; } -- cgit v1.2.3 From 5c9c7437749337f1af355eb9e447e75a58822da4 Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Mon, 24 Oct 2011 02:56:38 -0400 Subject: route: fix ICMP redirect validation [ Upstream commit 7cc9150ebe8ec06cafea9f1c10d92ddacf88d8ae ] The commit f39925dbde7788cfb96419c0f092b086aa325c0f (ipv4: Cache learned redirect information in inetpeer.) removed some ICMP packet validations which are required by RFC 1122, section 3.2.2.2: ... A Redirect message SHOULD be silently discarded if the new gateway address it specifies is not on the same connected (sub-) net through which the Redirect arrived [INTRO:2, Appendix A], or if the source of the Redirect is not the current first-hop gateway for the specified destination (see Section 3.3.1). Signed-off-by: Flavio Leitner Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index c3fcdb4fe2d..e9b273b923e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1313,7 +1313,12 @@ static void rt_del(unsigned hash, struct rtable *rt) void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, __be32 saddr, struct net_device *dev) { + int s, i; struct in_device *in_dev = __in_dev_get_rcu(dev); + struct rtable *rt; + __be32 skeys[2] = { saddr, 0 }; + int ikeys[2] = { dev->ifindex, 0 }; + struct flowi4 fl4; struct inet_peer *peer; struct net *net; @@ -1336,13 +1341,34 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, goto reject_redirect; } - peer = inet_getpeer_v4(daddr, 1); - if (peer) { - peer->redirect_learned.a4 = new_gw; + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = daddr; + for (s = 0; s < 2; s++) { + for (i = 0; i < 2; i++) { + fl4.flowi4_oif = ikeys[i]; + fl4.saddr = skeys[s]; + rt = __ip_route_output_key(net, &fl4); + if (IS_ERR(rt)) + continue; - inet_putpeer(peer); + if (rt->dst.error || rt->dst.dev != dev || + rt->rt_gateway != old_gw) { + ip_rt_put(rt); + continue; + } + + if (!rt->peer) + rt_bind_peer(rt, rt->rt_dst, 1); + + peer = rt->peer; + if (peer) { + peer->redirect_learned.a4 = new_gw; + atomic_inc(&__rt_peer_genid); + } - atomic_inc(&__rt_peer_genid); + ip_rt_put(rt); + return; + } } return; -- cgit v1.2.3 From 427814da7d68739ec2c53a9433f62323c68ef34d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 18 Nov 2011 15:24:32 -0500 Subject: ipv4: fix redirect handling [ Upstream commit 9cc20b268a5a14f5e57b8ad405a83513ab0d78dc ] commit f39925dbde77 (ipv4: Cache learned redirect information in inetpeer.) introduced a regression in ICMP redirect handling. It assumed ipv4_dst_check() would be called because all possible routes were attached to the inetpeer we modify in ip_rt_redirect(), but thats not true. commit 7cc9150ebe (route: fix ICMP redirect validation) tried to fix this but solution was not complete. (It fixed only one route) So we must lookup existing routes (including different TOS values) and call check_peer_redir() on them. Reported-by: Ivan Zahariev Signed-off-by: Eric Dumazet CC: Flavio Leitner Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 110 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index e9b273b923e..b2e9544a543 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1309,16 +1309,42 @@ static void rt_del(unsigned hash, struct rtable *rt) spin_unlock_bh(rt_hash_lock_addr(hash)); } +static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) +{ + struct rtable *rt = (struct rtable *) dst; + __be32 orig_gw = rt->rt_gateway; + struct neighbour *n, *old_n; + + dst_confirm(&rt->dst); + + rt->rt_gateway = peer->redirect_learned.a4; + + n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); + if (IS_ERR(n)) + return PTR_ERR(n); + old_n = xchg(&rt->dst._neighbour, n); + if (old_n) + neigh_release(old_n); + if (!n || !(n->nud_state & NUD_VALID)) { + if (n) + neigh_event_send(n, NULL); + rt->rt_gateway = orig_gw; + return -EAGAIN; + } else { + rt->rt_flags |= RTCF_REDIRECTED; + call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); + } + return 0; +} + /* called in rcu_read_lock() section */ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, __be32 saddr, struct net_device *dev) { int s, i; struct in_device *in_dev = __in_dev_get_rcu(dev); - struct rtable *rt; __be32 skeys[2] = { saddr, 0 }; int ikeys[2] = { dev->ifindex, 0 }; - struct flowi4 fl4; struct inet_peer *peer; struct net *net; @@ -1341,33 +1367,42 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, goto reject_redirect; } - memset(&fl4, 0, sizeof(fl4)); - fl4.daddr = daddr; for (s = 0; s < 2; s++) { for (i = 0; i < 2; i++) { - fl4.flowi4_oif = ikeys[i]; - fl4.saddr = skeys[s]; - rt = __ip_route_output_key(net, &fl4); - if (IS_ERR(rt)) - continue; - - if (rt->dst.error || rt->dst.dev != dev || - rt->rt_gateway != old_gw) { - ip_rt_put(rt); - continue; - } + unsigned int hash; + struct rtable __rcu **rthp; + struct rtable *rt; + + hash = rt_hash(daddr, skeys[s], ikeys[i], rt_genid(net)); + + rthp = &rt_hash_table[hash].chain; + + while ((rt = rcu_dereference(*rthp)) != NULL) { + rthp = &rt->dst.rt_next; + + if (rt->rt_key_dst != daddr || + rt->rt_key_src != skeys[s] || + rt->rt_oif != ikeys[i] || + rt_is_input_route(rt) || + rt_is_expired(rt) || + !net_eq(dev_net(rt->dst.dev), net) || + rt->dst.error || + rt->dst.dev != dev || + rt->rt_gateway != old_gw) + continue; - if (!rt->peer) - rt_bind_peer(rt, rt->rt_dst, 1); + if (!rt->peer) + rt_bind_peer(rt, rt->rt_dst, 1); - peer = rt->peer; - if (peer) { - peer->redirect_learned.a4 = new_gw; - atomic_inc(&__rt_peer_genid); + peer = rt->peer; + if (peer) { + if (peer->redirect_learned.a4 != new_gw) { + peer->redirect_learned.a4 = new_gw; + atomic_inc(&__rt_peer_genid); + } + check_peer_redir(&rt->dst, peer); + } } - - ip_rt_put(rt); - return; } } return; @@ -1654,33 +1689,6 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) } } -static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) -{ - struct rtable *rt = (struct rtable *) dst; - __be32 orig_gw = rt->rt_gateway; - struct neighbour *n, *old_n; - - dst_confirm(&rt->dst); - - rt->rt_gateway = peer->redirect_learned.a4; - - n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); - if (IS_ERR(n)) - return PTR_ERR(n); - old_n = xchg(&rt->dst._neighbour, n); - if (old_n) - neigh_release(old_n); - if (!n || !(n->nud_state & NUD_VALID)) { - if (n) - neigh_event_send(n, NULL); - rt->rt_gateway = orig_gw; - return -EAGAIN; - } else { - rt->rt_flags |= RTCF_REDIRECTED; - call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); - } - return 0; -} static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) { -- cgit v1.2.3 From 9c8da5125682191090bf32917a6bfba3d711492d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 26 Nov 2011 12:13:44 +0000 Subject: inet: add a redirect generation id in inetpeer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit de68dca1816660b0d3ac89fa59ffb410007a143f ] Now inetpeer is the place where we cache redirect information for ipv4 destinations, we must be able to invalidate informations when a route is added/removed on host. As inetpeer is not yet namespace aware, this patch adds a shared redirect_genid, and a per inetpeer redirect_genid. This might be changed later if inetpeer becomes ns aware. Cache information for one inerpeer is valid as long as its redirect_genid has the same value than global redirect_genid. Reported-by: Arkadiusz Miśkiewicz Tested-by: Arkadiusz Miśkiewicz Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/inetpeer.h | 1 + net/ipv4/route.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index 78c83e62218..e9ff3fc5e68 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -35,6 +35,7 @@ struct inet_peer { u32 metrics[RTAX_MAX]; u32 rate_tokens; /* rate limiting for ICMP */ + int redirect_genid; unsigned long rate_last; unsigned long pmtu_expires; u32 pmtu_orig; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b2e9544a543..65d25725448 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -132,6 +132,7 @@ static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; static int ip_rt_min_advmss __read_mostly = 256; static int rt_chain_length_max __read_mostly = 20; +static int redirect_genid; /* * Interface to generic destination cache. @@ -842,6 +843,7 @@ static void rt_cache_invalidate(struct net *net) get_random_bytes(&shuffle, sizeof(shuffle)); atomic_add(shuffle + 1U, &net->ipv4.rt_genid); + redirect_genid++; } /* @@ -1396,8 +1398,10 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, peer = rt->peer; if (peer) { - if (peer->redirect_learned.a4 != new_gw) { + if (peer->redirect_learned.a4 != new_gw || + peer->redirect_genid != redirect_genid) { peer->redirect_learned.a4 = new_gw; + peer->redirect_genid = redirect_genid; atomic_inc(&__rt_peer_genid); } check_peer_redir(&rt->dst, peer); @@ -1706,6 +1710,8 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) if (peer) { check_peer_pmtu(dst, peer); + if (peer->redirect_genid != redirect_genid) + peer->redirect_learned.a4 = 0; if (peer->redirect_learned.a4 && peer->redirect_learned.a4 != rt->rt_gateway) { if (check_peer_redir(dst, peer)) @@ -1857,6 +1863,8 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, dst_init_metrics(&rt->dst, peer->metrics, false); check_peer_pmtu(&rt->dst, peer); + if (peer->redirect_genid != redirect_genid) + peer->redirect_learned.a4 = 0; if (peer->redirect_learned.a4 && peer->redirect_learned.a4 != rt->rt_gateway) { rt->rt_gateway = peer->redirect_learned.a4; -- cgit v1.2.3 From 9fdec5ec64644ce4f4081e045dfbcd7518276edb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 1 Dec 2011 13:38:59 -0500 Subject: ipv4: Perform peer validation on cached route lookup. [ Upstream commit efbc368dcc6426d5430b9b8eeda944cf2cb74b8c, incorporating a follow-on change to prevent an OOPS ] Otherwise we won't notice the peer GENID change. Reported-by: Steffen Klassert Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 65d25725448..5c9b20ff748 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1311,7 +1311,7 @@ static void rt_del(unsigned hash, struct rtable *rt) spin_unlock_bh(rt_hash_lock_addr(hash)); } -static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) +static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) { struct rtable *rt = (struct rtable *) dst; __be32 orig_gw = rt->rt_gateway; @@ -1322,21 +1322,19 @@ static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) rt->rt_gateway = peer->redirect_learned.a4; n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); - if (IS_ERR(n)) - return PTR_ERR(n); + if (IS_ERR(n)) { + rt->rt_gateway = orig_gw; + return; + } old_n = xchg(&rt->dst._neighbour, n); if (old_n) neigh_release(old_n); - if (!n || !(n->nud_state & NUD_VALID)) { - if (n) - neigh_event_send(n, NULL); - rt->rt_gateway = orig_gw; - return -EAGAIN; + if (!(n->nud_state & NUD_VALID)) { + neigh_event_send(n, NULL); } else { rt->rt_flags |= RTCF_REDIRECTED; call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); } - return 0; } /* called in rcu_read_lock() section */ @@ -1694,12 +1692,8 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) } -static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) +static void ipv4_validate_peer(struct rtable *rt) { - struct rtable *rt = (struct rtable *) dst; - - if (rt_is_expired(rt)) - return NULL; if (rt->rt_peer_genid != rt_peer_genid()) { struct inet_peer *peer; @@ -1708,19 +1702,26 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) peer = rt->peer; if (peer) { - check_peer_pmtu(dst, peer); + check_peer_pmtu(&rt->dst, peer); if (peer->redirect_genid != redirect_genid) peer->redirect_learned.a4 = 0; if (peer->redirect_learned.a4 && - peer->redirect_learned.a4 != rt->rt_gateway) { - if (check_peer_redir(dst, peer)) - return NULL; - } + peer->redirect_learned.a4 != rt->rt_gateway) + check_peer_redir(&rt->dst, peer); } rt->rt_peer_genid = rt_peer_genid(); } +} + +static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) +{ + struct rtable *rt = (struct rtable *) dst; + + if (rt_is_expired(rt)) + return NULL; + ipv4_validate_peer(rt); return dst; } @@ -2370,6 +2371,7 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_mark == skb->mark && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { + ipv4_validate_peer(rth); if (noref) { dst_use_noref(&rth->dst, jiffies); skb_dst_set_noref(skb, &rth->dst); @@ -2745,6 +2747,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) (IPTOS_RT_MASK | RTO_ONLINK)) && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { + ipv4_validate_peer(rth); dst_use(&rth->dst, jiffies); RT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); -- cgit v1.2.3 From 51338aa88d3ef2d05bf8b1f8a3019ebffcea74f1 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Fri, 2 Dec 2011 11:39:42 +0000 Subject: ipv4: make sure RTO_ONLINK is saved in routing cache [ Upstream commit f61759e6b831a55b89e584b198c3da325e2bc379 ] __mkroute_output fails to work with the original tos and uses value with stripped RTO_ONLINK bit. Make sure we put the original TOS bits into rt_key_tos because it used to match cached route. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/route.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 5c9b20ff748..05ac666c330 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -112,7 +112,7 @@ #include #define RT_FL_TOS(oldflp4) \ - ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) + ((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)) #define IP_MAX_MTU 0xFFF0 @@ -2430,11 +2430,11 @@ EXPORT_SYMBOL(ip_route_input_common); static struct rtable *__mkroute_output(const struct fib_result *res, const struct flowi4 *fl4, __be32 orig_daddr, __be32 orig_saddr, - int orig_oif, struct net_device *dev_out, + int orig_oif, __u8 orig_rtos, + struct net_device *dev_out, unsigned int flags) { struct fib_info *fi = res->fi; - u32 tos = RT_FL_TOS(fl4); struct in_device *in_dev; u16 type = res->type; struct rtable *rth; @@ -2485,7 +2485,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_genid = rt_genid(dev_net(dev_out)); rth->rt_flags = flags; rth->rt_type = type; - rth->rt_key_tos = tos; + rth->rt_key_tos = orig_rtos; rth->rt_dst = fl4->daddr; rth->rt_src = fl4->saddr; rth->rt_route_iif = 0; @@ -2535,7 +2535,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) { struct net_device *dev_out = NULL; - u32 tos = RT_FL_TOS(fl4); + __u8 tos = RT_FL_TOS(fl4); unsigned int flags = 0; struct fib_result res; struct rtable *rth; @@ -2711,7 +2711,7 @@ static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) make_route: rth = __mkroute_output(&res, fl4, orig_daddr, orig_saddr, orig_oif, - dev_out, flags); + tos, dev_out, flags); if (!IS_ERR(rth)) { unsigned int hash; -- cgit v1.2.3 From 4851c6a079350393f4a9219878e699845412bace Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 30 Nov 2011 12:10:53 +0000 Subject: sch_red: fix red_calc_qavg_from_idle_time [ Upstream commit ea6a5d3b97b768561db6358f15e4c84ced0f4f7e ] Since commit a4a710c4a7490587 (pkt_sched: Change PSCHED_SHIFT from 10 to 6) it seems RED/GRED are broken. red_calc_qavg_from_idle_time() computes a delay in us units, but this delay is now 16 times bigger than real delay, so the final qavg result smaller than expected. Use standard kernel time services since there is no need to obfuscate them. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/red.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/include/net/red.h b/include/net/red.h index 3319f16b3be..b72a3b83393 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -116,7 +116,7 @@ struct red_parms { u32 qR; /* Cached random number */ unsigned long qavg; /* Average queue length: A scaled */ - psched_time_t qidlestart; /* Start of current idle period */ + ktime_t qidlestart; /* Start of current idle period */ }; static inline u32 red_rmask(u8 Plog) @@ -148,17 +148,17 @@ static inline void red_set_parms(struct red_parms *p, static inline int red_is_idling(struct red_parms *p) { - return p->qidlestart != PSCHED_PASTPERFECT; + return p->qidlestart.tv64 != 0; } static inline void red_start_of_idle_period(struct red_parms *p) { - p->qidlestart = psched_get_time(); + p->qidlestart = ktime_get(); } static inline void red_end_of_idle_period(struct red_parms *p) { - p->qidlestart = PSCHED_PASTPERFECT; + p->qidlestart.tv64 = 0; } static inline void red_restart(struct red_parms *p) @@ -170,13 +170,10 @@ static inline void red_restart(struct red_parms *p) static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p) { - psched_time_t now; - long us_idle; + s64 delta = ktime_us_delta(ktime_get(), p->qidlestart); + long us_idle = min_t(s64, delta, p->Scell_max); int shift; - now = psched_get_time(); - us_idle = psched_tdiff_bounded(now, p->qidlestart, p->Scell_max); - /* * The problem: ideally, average length queue recalcultion should * be done over constant clock intervals. This is too expensive, so -- cgit v1.2.3 From 50d224d483a7dbecf84beffff9f815ac104ee5e8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 1 Dec 2011 11:06:34 +0000 Subject: sch_red: fix red_change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 1ee5fa1e9970a16036e37c7b9d5ce81c778252fc ] Le mercredi 30 novembre 2011 à 14:36 -0800, Stephen Hemminger a écrit : > (Almost) nobody uses RED because they can't figure it out. > According to Wikipedia, VJ says that: > "there are not one, but two bugs in classic RED." RED is useful for high throughput routers, I doubt many linux machines act as such devices. I was considering adding Adaptative RED (Sally Floyd, Ramakrishna Gummadi, Scott Shender), August 2001 In this version, maxp is dynamic (from 1% to 50%), and user only have to setup min_th (target average queue size) (max_th and wq (burst in linux RED) are automatically setup) By the way it seems we have a small bug in red_change() if (skb_queue_empty(&sch->q)) red_end_of_idle_period(&q->parms); First, if queue is empty, we should call red_start_of_idle_period(&q->parms); Second, since we dont use anymore sch->q, but q->qdisc, the test is meaningless. Oh well... [PATCH] sch_red: fix red_change() Now RED is classful, we must check q->qdisc->q.qlen, and if queue is empty, we start an idle period, not end it. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_red.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 6649463da1b..d617161f8dd 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -209,8 +209,8 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) ctl->Plog, ctl->Scell_log, nla_data(tb[TCA_RED_STAB])); - if (skb_queue_empty(&sch->q)) - red_end_of_idle_period(&q->parms); + if (!q->qdisc->q.qlen) + red_start_of_idle_period(&q->parms); sch_tree_unlock(sch); return 0; -- cgit v1.2.3 From caf4b0430be8296bf644199bf3ed3056c02420c7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 9 Dec 2011 08:57:05 -0800 Subject: Linux 3.1.5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7f8a93b1c37..94ab2adfab1 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 1 -SUBLEVEL = 4 +SUBLEVEL = 5 EXTRAVERSION = NAME = "Divemaster Edition" -- cgit v1.2.3