From 98d338a7028dbcfc98a7d64856798882b4fbcc21 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 25 Oct 2009 15:37:58 +0100 Subject: [PATCH 001/670] signal: Fix alternate signal stack check commit 2a855dd01bc1539111adb7233f587c5c468732ac upstream. All architectures in the kernel increment/decrement the stack pointer before storing values on the stack. On architectures which have the stack grow down sas_ss_sp == sp is not on the alternate signal stack while sas_ss_sp + sas_ss_size == sp is on the alternate signal stack. On architectures which have the stack grow up sas_ss_sp == sp is on the alternate signal stack while sas_ss_sp + sas_ss_size == sp is not on the alternate signal stack. The current implementation fails for architectures which have the stack grow down on the corner case where sas_ss_sp == sp.This was reported as Debian bug #544905 on AMD64. Simplified test case: http://download.breakpoint.cc/tc-sig-stack.c The test case creates the following stack scenario: 0xn0300 stack top 0xn0200 alt stack pointer top (when switching to alt stack) 0xn01ff alt stack end 0xn0100 alt stack start == stack pointer If the signal is sent the stack pointer is pointing to the base address of the alt stack and the kernel erroneously decides that it has already switched to the alternate stack because of the current check for "sp - sas_ss_sp < sas_ss_size" On parisc (stack grows up) the scenario would be: 0xn0200 stack pointer 0xn01ff alt stack end 0xn0100 alt stack start = alt stack pointer base (when switching to alt stack) 0xn0000 stack base This is handled correctly by the current implementation. [ tglx: Modified for archs which have the stack grow up (parisc) which would fail with the correct implementation for stack grows down. Added a check for sp >= current->sas_ss_sp which is strictly not necessary but makes the code symetric for both variants ] Signed-off-by: Sebastian Andrzej Siewior Cc: Oleg Nesterov Cc: Roland McGrath Cc: Kyle McMartin LKML-Reference: <20091025143758.GA6653@Chamillionaire.breakpoint.cc> Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 75e6e60bf583..0f67914a43c9 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2086,11 +2086,18 @@ static inline int is_si_special(const struct siginfo *info) return info <= SEND_SIG_FORCED; } -/* True if we are on the alternate signal stack. */ - +/* + * True if we are on the alternate signal stack. + */ static inline int on_sig_stack(unsigned long sp) { - return (sp - current->sas_ss_sp < current->sas_ss_size); +#ifdef CONFIG_STACK_GROWSUP + return sp >= current->sas_ss_sp && + sp - current->sas_ss_sp < current->sas_ss_size; +#else + return sp > current->sas_ss_sp && + sp - current->sas_ss_sp <= current->sas_ss_size; +#endif } static inline int sas_ss_flags(unsigned long sp) From d888b1a2d5c7a9fbdc01e7395ea6a8d75cd729f5 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 5 Nov 2009 13:33:12 -0600 Subject: [PATCH 002/670] SCSI: scsi_lib_dma: fix bug with dma maps on nested scsi objects commit d139b9bd0e52dda14fd13412e7096e68b56d0076 upstream. Some of our virtual SCSI hosts don't have a proper bus parent at the top, which can be a problem for doing DMA on them This patch makes the host device cache a pointer to the physical bus device and provides an extra API for setting it (the normal API picks it up from the parent). This patch also modifies the qla2xxx and lpfc vport logic to use the new DMA host setting API. Acked-By: James Smart Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/hosts.c | 13 ++++++++++--- drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/qla2xxx/qla_attr.c | 3 ++- drivers/scsi/scsi_lib_dma.c | 4 ++-- include/scsi/scsi_host.h | 16 +++++++++++++++- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index c968cc31cd86..554626e18062 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -180,14 +180,20 @@ void scsi_remove_host(struct Scsi_Host *shost) EXPORT_SYMBOL(scsi_remove_host); /** - * scsi_add_host - add a scsi host + * scsi_add_host_with_dma - add a scsi host with dma device * @shost: scsi host pointer to add * @dev: a struct device of type scsi class + * @dma_dev: dma device for the host + * + * Note: You rarely need to worry about this unless you're in a + * virtualised host environments, so use the simpler scsi_add_host() + * function instead. * * Return value: * 0 on success / != 0 for error **/ -int scsi_add_host(struct Scsi_Host *shost, struct device *dev) +int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, + struct device *dma_dev) { struct scsi_host_template *sht = shost->hostt; int error = -EINVAL; @@ -207,6 +213,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) if (!shost->shost_gendev.parent) shost->shost_gendev.parent = dev ? dev : &platform_bus; + shost->dma_dev = dma_dev; error = device_add(&shost->shost_gendev); if (error) @@ -262,7 +269,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) fail: return error; } -EXPORT_SYMBOL(scsi_add_host); +EXPORT_SYMBOL(scsi_add_host_with_dma); static void scsi_host_dev_release(struct device *dev) { diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 562d8cee874b..f913f1e93635 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -2408,7 +2408,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) vport->els_tmofunc.function = lpfc_els_timeout; vport->els_tmofunc.data = (unsigned long)vport; - error = scsi_add_host(shost, dev); + error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev); if (error) goto out_put_shost; diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index fbcb82a2f7f4..21e2bc4d7401 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1654,7 +1654,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); } - if (scsi_add_host(vha->host, &fc_vport->dev)) { + if (scsi_add_host_with_dma(vha->host, &fc_vport->dev, + &ha->pdev->dev)) { DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n", vha->host_no, vha->vp_idx)); goto vport_create_failed_2; diff --git a/drivers/scsi/scsi_lib_dma.c b/drivers/scsi/scsi_lib_dma.c index ac6855cd2657..dcd128583b89 100644 --- a/drivers/scsi/scsi_lib_dma.c +++ b/drivers/scsi/scsi_lib_dma.c @@ -23,7 +23,7 @@ int scsi_dma_map(struct scsi_cmnd *cmd) int nseg = 0; if (scsi_sg_count(cmd)) { - struct device *dev = cmd->device->host->shost_gendev.parent; + struct device *dev = cmd->device->host->dma_dev; nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd), cmd->sc_data_direction); @@ -41,7 +41,7 @@ EXPORT_SYMBOL(scsi_dma_map); void scsi_dma_unmap(struct scsi_cmnd *cmd) { if (scsi_sg_count(cmd)) { - struct device *dev = cmd->device->host->shost_gendev.parent; + struct device *dev = cmd->device->host->dma_dev; dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd), cmd->sc_data_direction); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 47941fc5aba7..0b4babaabe32 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -676,6 +676,12 @@ struct Scsi_Host { */ void *shost_data; + /* + * Points to the physical bus device we'd use to do DMA + * Needed just in case we have virtual hosts. + */ + struct device *dma_dev; + /* * We should ensure that this is aligned, both for better performance * and also because some compilers (m68k) don't automatically force @@ -720,7 +726,9 @@ extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *); extern void scsi_flush_work(struct Scsi_Host *); extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int); -extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *); +extern int __must_check scsi_add_host_with_dma(struct Scsi_Host *, + struct device *, + struct device *); extern void scsi_scan_host(struct Scsi_Host *); extern void scsi_rescan_device(struct device *); extern void scsi_remove_host(struct Scsi_Host *); @@ -731,6 +739,12 @@ extern const char *scsi_host_state_name(enum scsi_host_state); extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *); +static inline int __must_check scsi_add_host(struct Scsi_Host *host, + struct device *dev) +{ + return scsi_add_host_with_dma(host, dev, dev); +} + static inline struct device *scsi_get_device(struct Scsi_Host *shost) { return shost->shost_gendev.parent; From 79daedf8b665473f5adf6d0d80b4f2c6ff524bca Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Mon, 16 Nov 2009 20:49:25 +0200 Subject: [PATCH 003/670] SCSI: osd_protocol.h: Add missing #include commit 0899638688f223fd9e9fee60d662665e11693d12 upstream. include/scsi/osd_protocol.h uses ALIGN() without an #include , leading to: | include/scsi/osd_protocol.h:362: error: implicit declaration of function 'ALIGN' Signed-off-by: Martin Michlmayr Signed-off-by: Boaz Harrosh Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- include/scsi/osd_protocol.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h index 2cc8e8b1cc19..685661283540 100644 --- a/include/scsi/osd_protocol.h +++ b/include/scsi/osd_protocol.h @@ -17,6 +17,7 @@ #define __OSD_PROTOCOL_H__ #include +#include #include #include From d10a8f05208b66c0b29562a9601601b9a7b5d9ac Mon Sep 17 00:00:00 2001 From: "Yang, Bo" Date: Tue, 6 Oct 2009 14:52:20 -0600 Subject: [PATCH 004/670] SCSI: megaraid_sas: fix 64 bit sense pointer truncation commit 7b2519afa1abd1b9f63aa1e90879307842422dae upstream. The current sense pointer is cast to a u32 pointer, which can truncate on 64 bits. Fix by using unsigned long instead. Signed-off-by Bo Yang Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/megaraid/megaraid_sas.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index a39addc3a596..507ccc682046 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -3032,7 +3032,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, int error = 0, i; void *sense = NULL; dma_addr_t sense_handle; - u32 *sense_ptr; + unsigned long *sense_ptr; memset(kbuff_arr, 0, sizeof(kbuff_arr)); @@ -3109,7 +3109,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, } sense_ptr = - (u32 *) ((unsigned long)cmd->frame + ioc->sense_off); + (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); *sense_ptr = sense_handle; } @@ -3140,8 +3140,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, * sense_ptr points to the location that has the user * sense buffer address */ - sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw + - ioc->sense_off); + sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw + + ioc->sense_off); if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), sense, ioc->sense_len)) { From 6662a8d03104516c53170257b837d8a03e86db39 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 23 Nov 2009 07:25:49 -0500 Subject: [PATCH 005/670] ext4: fix potential buffer head leak when add_dirent_to_buf() returns ENOSPC (cherry picked from commit 2de770a406b06dfc619faabbf5d85c835ed3f2e1) Previously add_dirent_to_buf() did not free its passed-in buffer head in the case of ENOSPC, since in some cases the caller still needed it. However, this led to potential buffer head leaks since not all callers dealt with this correctly. Fix this by making simplifying the freeing convention; now add_dirent_to_buf() *never* frees the passed-in buffer head, and leaves that to the responsibility of its caller. This makes things cleaner and easier to prove that the code is neither leaking buffer heads or calling brelse() one time too many. Signed-off-by: "Theodore Ts'o" Cc: Curt Wohlgemuth Signed-off-by: Greg Kroah-Hartman --- fs/ext4/namei.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 6d2c1b897fc7..fde08c919d12 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1292,9 +1292,6 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, * add_dirent_to_buf will attempt search the directory block for * space. It will return -ENOSPC if no space is available, and -EIO * and -EEXIST if directory entry already exists. - * - * NOTE! bh is NOT released in the case where ENOSPC is returned. In - * all other cases bh is released. */ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, struct inode *inode, struct ext4_dir_entry_2 *de, @@ -1315,14 +1312,10 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, top = bh->b_data + blocksize - reclen; while ((char *) de <= top) { if (!ext4_check_dir_entry("ext4_add_entry", dir, de, - bh, offset)) { - brelse(bh); + bh, offset)) return -EIO; - } - if (ext4_match(namelen, name, de)) { - brelse(bh); + if (ext4_match(namelen, name, de)) return -EEXIST; - } nlen = EXT4_DIR_REC_LEN(de->name_len); rlen = ext4_rec_len_from_disk(de->rec_len, blocksize); if ((de->inode? rlen - nlen: rlen) >= reclen) @@ -1337,7 +1330,6 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, err = ext4_journal_get_write_access(handle, bh); if (err) { ext4_std_error(dir->i_sb, err); - brelse(bh); return err; } @@ -1377,7 +1369,6 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, err = ext4_handle_dirty_metadata(handle, dir, bh); if (err) ext4_std_error(dir->i_sb, err); - brelse(bh); return 0; } @@ -1471,7 +1462,9 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, if (!(de)) return retval; - return add_dirent_to_buf(handle, dentry, inode, de, bh); + retval = add_dirent_to_buf(handle, dentry, inode, de, bh); + brelse(bh); + return retval; } /* @@ -1514,8 +1507,10 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, if(!bh) return retval; retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh); - if (retval != -ENOSPC) + if (retval != -ENOSPC) { + brelse(bh); return retval; + } if (blocks == 1 && !dx_fallback && EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) @@ -1528,7 +1523,9 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, de = (struct ext4_dir_entry_2 *) bh->b_data; de->inode = 0; de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize); - return add_dirent_to_buf(handle, dentry, inode, de, bh); + retval = add_dirent_to_buf(handle, dentry, inode, de, bh); + brelse(bh); + return retval; } /* @@ -1561,10 +1558,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, goto journal_error; err = add_dirent_to_buf(handle, dentry, inode, NULL, bh); - if (err != -ENOSPC) { - bh = NULL; + if (err != -ENOSPC) goto cleanup; - } /* Block full, should compress but for now just split */ dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n", @@ -1657,7 +1652,6 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, if (!de) goto cleanup; err = add_dirent_to_buf(handle, dentry, inode, de, bh); - bh = NULL; goto cleanup; journal_error: From 8ed33ff5203300ac8878042bc4d4954e2f40c488 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 23 Nov 2009 07:24:46 -0500 Subject: [PATCH 006/670] ext4: avoid divide by zero when trying to mount a corrupted file system (cherry picked from commit 503358ae01b70ce6909d19dd01287093f6b6271c) If s_log_groups_per_flex is greater than 31, then groups_per_flex will will overflow and cause a divide by zero error. This can cause kernel BUG if such a file system is mounted. Thanks to Nageswara R Sastry for analyzing the failure and providing an initial patch. http://bugzilla.kernel.org/show_bug.cgi?id=14287 Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d4ca92aab514..8662b2e6e9f9 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1673,14 +1673,14 @@ static int ext4_fill_flex_info(struct super_block *sb) size_t size; int i; - if (!sbi->s_es->s_log_groups_per_flex) { + sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex; + groups_per_flex = 1 << sbi->s_log_groups_per_flex; + + if (groups_per_flex < 2) { sbi->s_log_groups_per_flex = 0; return 1; } - sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex; - groups_per_flex = 1 << sbi->s_log_groups_per_flex; - /* We allocate both existing and potentially added groups */ flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << From a4a87a7f39020ea18f220c9e9c8ab112ebd6764a Mon Sep 17 00:00:00 2001 From: Akira Fujita Date: Mon, 23 Nov 2009 07:25:48 -0500 Subject: [PATCH 007/670] ext4: fix the returned block count if EXT4_IOC_MOVE_EXT fails (cherry picked from commit f868a48d06f8886cb0367568a12367fa4f21ea0d) If the EXT4_IOC_MOVE_EXT ioctl fails, the number of blocks that were exchanged before the failure should be returned to the userspace caller. Unfortunately, currently if the block size is not the same as the page size, the returned block count that is returned is the page-aligned block count instead of the actual block count. This commit addresses this bug. Signed-off-by: Akira Fujita Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/move_extent.c | 139 ++++++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 66 deletions(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 25b6b1457360..83f8c9e47c60 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -661,6 +661,7 @@ mext_calc_swap_extents(struct ext4_extent *tmp_dext, * @donor_inode: donor inode * @from: block offset of orig_inode * @count: block count to be replaced + * @err: pointer to save return value * * Replace original inode extents and donor inode extents page by page. * We implement this replacement in the following three steps: @@ -671,19 +672,18 @@ mext_calc_swap_extents(struct ext4_extent *tmp_dext, * 3. Change the block information of donor inode to point at the saved * original inode blocks in the dummy extents. * - * Return 0 on success, or a negative error value on failure. + * Return replaced block count. */ static int mext_replace_branches(handle_t *handle, struct inode *orig_inode, struct inode *donor_inode, ext4_lblk_t from, - ext4_lblk_t count) + ext4_lblk_t count, int *err) { struct ext4_ext_path *orig_path = NULL; struct ext4_ext_path *donor_path = NULL; struct ext4_extent *oext, *dext; struct ext4_extent tmp_dext, tmp_oext; ext4_lblk_t orig_off = from, donor_off = from; - int err = 0; int depth; int replaced_count = 0; int dext_alen; @@ -691,13 +691,13 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, mext_double_down_write(orig_inode, donor_inode); /* Get the original extent for the block "orig_off" */ - err = get_ext_path(orig_inode, orig_off, &orig_path); - if (err) + *err = get_ext_path(orig_inode, orig_off, &orig_path); + if (*err) goto out; /* Get the donor extent for the head */ - err = get_ext_path(donor_inode, donor_off, &donor_path); - if (err) + *err = get_ext_path(donor_inode, donor_off, &donor_path); + if (*err) goto out; depth = ext_depth(orig_inode); oext = orig_path[depth].p_ext; @@ -707,9 +707,9 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, dext = donor_path[depth].p_ext; tmp_dext = *dext; - err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off, + *err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off, donor_off, count); - if (err) + if (*err) goto out; /* Loop for the donor extents */ @@ -718,7 +718,7 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, if (!dext) { ext4_error(donor_inode->i_sb, __func__, "The extent for donor must be found"); - err = -EIO; + *err = -EIO; goto out; } else if (donor_off != le32_to_cpu(tmp_dext.ee_block)) { ext4_error(donor_inode->i_sb, __func__, @@ -726,20 +726,20 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, "extent(%u) should be equal", donor_off, le32_to_cpu(tmp_dext.ee_block)); - err = -EIO; + *err = -EIO; goto out; } /* Set donor extent to orig extent */ - err = mext_leaf_block(handle, orig_inode, + *err = mext_leaf_block(handle, orig_inode, orig_path, &tmp_dext, &orig_off); - if (err < 0) + if (*err) goto out; /* Set orig extent to donor extent */ - err = mext_leaf_block(handle, donor_inode, + *err = mext_leaf_block(handle, donor_inode, donor_path, &tmp_oext, &donor_off); - if (err < 0) + if (*err) goto out; dext_alen = ext4_ext_get_actual_len(&tmp_dext); @@ -753,35 +753,25 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, if (orig_path) ext4_ext_drop_refs(orig_path); - err = get_ext_path(orig_inode, orig_off, &orig_path); - if (err) + *err = get_ext_path(orig_inode, orig_off, &orig_path); + if (*err) goto out; depth = ext_depth(orig_inode); oext = orig_path[depth].p_ext; - if (le32_to_cpu(oext->ee_block) + - ext4_ext_get_actual_len(oext) <= orig_off) { - err = 0; - goto out; - } tmp_oext = *oext; if (donor_path) ext4_ext_drop_refs(donor_path); - err = get_ext_path(donor_inode, donor_off, &donor_path); - if (err) + *err = get_ext_path(donor_inode, donor_off, &donor_path); + if (*err) goto out; depth = ext_depth(donor_inode); dext = donor_path[depth].p_ext; - if (le32_to_cpu(dext->ee_block) + - ext4_ext_get_actual_len(dext) <= donor_off) { - err = 0; - goto out; - } tmp_dext = *dext; - err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off, + *err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off, donor_off, count - replaced_count); - if (err) + if (*err) goto out; } @@ -796,7 +786,7 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, } mext_double_up_write(orig_inode, donor_inode); - return err; + return replaced_count; } /** @@ -808,16 +798,17 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, * @data_offset_in_page: block index where data swapping starts * @block_len_in_page: the number of blocks to be swapped * @uninit: orig extent is uninitialized or not + * @err: pointer to save return value * * Save the data in original inode blocks and replace original inode extents * with donor inode extents by calling mext_replace_branches(). - * Finally, write out the saved data in new original inode blocks. Return 0 - * on success, or a negative error value on failure. + * Finally, write out the saved data in new original inode blocks. Return + * replaced block count. */ static int move_extent_per_page(struct file *o_filp, struct inode *donor_inode, pgoff_t orig_page_offset, int data_offset_in_page, - int block_len_in_page, int uninit) + int block_len_in_page, int uninit, int *err) { struct inode *orig_inode = o_filp->f_dentry->d_inode; struct address_space *mapping = orig_inode->i_mapping; @@ -829,9 +820,11 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, long long offs = orig_page_offset << PAGE_CACHE_SHIFT; unsigned long blocksize = orig_inode->i_sb->s_blocksize; unsigned int w_flags = 0; - unsigned int tmp_data_len, data_len; + unsigned int tmp_data_size, data_size, replaced_size; void *fsdata; - int ret, i, jblocks; + int i, jblocks; + int err2 = 0; + int replaced_count = 0; int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits; /* @@ -841,8 +834,8 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, jblocks = ext4_writepage_trans_blocks(orig_inode) * 2; handle = ext4_journal_start(orig_inode, jblocks); if (IS_ERR(handle)) { - ret = PTR_ERR(handle); - return ret; + *err = PTR_ERR(handle); + return 0; } if (segment_eq(get_fs(), KERNEL_DS)) @@ -858,9 +851,9 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, * Just swap data blocks between orig and donor. */ if (uninit) { - ret = mext_replace_branches(handle, orig_inode, - donor_inode, orig_blk_offset, - block_len_in_page); + replaced_count = mext_replace_branches(handle, orig_inode, + donor_inode, orig_blk_offset, + block_len_in_page, err); /* Clear the inode cache not to refer to the old data */ ext4_ext_invalidate_cache(orig_inode); @@ -870,27 +863,28 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, offs = (long long)orig_blk_offset << orig_inode->i_blkbits; - /* Calculate data_len */ + /* Calculate data_size */ if ((orig_blk_offset + block_len_in_page - 1) == ((orig_inode->i_size - 1) >> orig_inode->i_blkbits)) { /* Replace the last block */ - tmp_data_len = orig_inode->i_size & (blocksize - 1); + tmp_data_size = orig_inode->i_size & (blocksize - 1); /* - * If data_len equal zero, it shows data_len is multiples of + * If data_size equal zero, it shows data_size is multiples of * blocksize. So we set appropriate value. */ - if (tmp_data_len == 0) - tmp_data_len = blocksize; + if (tmp_data_size == 0) + tmp_data_size = blocksize; - data_len = tmp_data_len + + data_size = tmp_data_size + ((block_len_in_page - 1) << orig_inode->i_blkbits); - } else { - data_len = block_len_in_page << orig_inode->i_blkbits; - } + } else + data_size = block_len_in_page << orig_inode->i_blkbits; - ret = a_ops->write_begin(o_filp, mapping, offs, data_len, w_flags, + replaced_size = data_size; + + *err = a_ops->write_begin(o_filp, mapping, offs, data_size, w_flags, &page, &fsdata); - if (unlikely(ret < 0)) + if (unlikely(*err < 0)) goto out; if (!PageUptodate(page)) { @@ -911,10 +905,17 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, /* Release old bh and drop refs */ try_to_release_page(page, 0); - ret = mext_replace_branches(handle, orig_inode, donor_inode, - orig_blk_offset, block_len_in_page); - if (ret < 0) - goto out; + replaced_count = mext_replace_branches(handle, orig_inode, donor_inode, + orig_blk_offset, block_len_in_page, + &err2); + if (err2) { + if (replaced_count) { + block_len_in_page = replaced_count; + replaced_size = + block_len_in_page << orig_inode->i_blkbits; + } else + goto out; + } /* Clear the inode cache not to refer to the old data */ ext4_ext_invalidate_cache(orig_inode); @@ -928,16 +929,16 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, bh = bh->b_this_page; for (i = 0; i < block_len_in_page; i++) { - ret = ext4_get_block(orig_inode, + *err = ext4_get_block(orig_inode, (sector_t)(orig_blk_offset + i), bh, 0); - if (ret < 0) + if (*err < 0) goto out; if (bh->b_this_page != NULL) bh = bh->b_this_page; } - ret = a_ops->write_end(o_filp, mapping, offs, data_len, data_len, + *err = a_ops->write_end(o_filp, mapping, offs, data_size, replaced_size, page, fsdata); page = NULL; @@ -951,7 +952,10 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, out2: ext4_journal_stop(handle); - return ret < 0 ? ret : 0; + if (err2) + *err = err2; + + return replaced_count; } /** @@ -1367,15 +1371,17 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, while (orig_page_offset <= seq_end_page) { /* Swap original branches with new branches */ - ret1 = move_extent_per_page(o_filp, donor_inode, + block_len_in_page = move_extent_per_page( + o_filp, donor_inode, orig_page_offset, data_offset_in_page, - block_len_in_page, uninit); - if (ret1 < 0) - goto out; - orig_page_offset++; + block_len_in_page, uninit, + &ret1); + /* Count how many blocks we have exchanged */ *moved_len += block_len_in_page; + if (ret1 < 0) + goto out; if (*moved_len > len) { ext4_error(orig_inode->i_sb, __func__, "We replaced blocks too much! " @@ -1385,6 +1391,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, goto out; } + orig_page_offset++; data_offset_in_page = 0; rest_blocks -= block_len_in_page; if (rest_blocks > blocks_per_page) From 52a4345d3d82b77bea320bf223716298468be3de Mon Sep 17 00:00:00 2001 From: Akira Fujita Date: Mon, 23 Nov 2009 07:24:43 -0500 Subject: [PATCH 008/670] ext4: fix lock order problem in ext4_move_extents() (cherry picked from commit fc04cb49a898c372a22b21fffc47f299d8710801) ext4_move_extents() checks the logical block contiguousness of original file with ext4_find_extent() and mext_next_extent(). Therefore the extent which ext4_ext_path structure indicates must not be changed between above functions. But in current implementation, there is no i_data_sem protection between ext4_ext_find_extent() and mext_next_extent(). So the extent which ext4_ext_path structure indicates may be overwritten by delalloc. As a result, ext4_move_extents() will exchange wrong blocks between original and donor files. I change the place where acquire/release i_data_sem to solve this problem. Moreover, I changed move_extent_per_page() to start transaction first, and then acquire i_data_sem. Without this change, there is a possibility of the deadlock between mmap() and ext4_move_extents(): * NOTE: "A", "B" and "C" mean different processes A-1: ext4_ext_move_extents() acquires i_data_sem of two inodes. B: do_page_fault() starts the transaction (T), and then tries to acquire i_data_sem. But process "A" is already holding it, so it is kept waiting. C: While "A" and "B" running, kjournald2 tries to commit transaction (T) but it is under updating, so kjournald2 waits for it. A-2: Call ext4_journal_start with holding i_data_sem, but transaction (T) is locked. Signed-off-by: Akira Fujita Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/move_extent.c | 117 +++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 64 deletions(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 83f8c9e47c60..a7410b34c5ed 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -77,12 +77,14 @@ static int mext_next_extent(struct inode *inode, struct ext4_ext_path *path, struct ext4_extent **extent) { + struct ext4_extent_header *eh; int ppos, leaf_ppos = path->p_depth; ppos = leaf_ppos; if (EXT_LAST_EXTENT(path[ppos].p_hdr) > path[ppos].p_ext) { /* leaf block */ *extent = ++path[ppos].p_ext; + path[ppos].p_block = ext_pblock(path[ppos].p_ext); return 0; } @@ -119,9 +121,18 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path, ext_block_hdr(path[cur_ppos+1].p_bh); } + path[leaf_ppos].p_ext = *extent = NULL; + + eh = path[leaf_ppos].p_hdr; + if (le16_to_cpu(eh->eh_entries) == 0) + /* empty leaf is found */ + return -ENODATA; + /* leaf block */ path[leaf_ppos].p_ext = *extent = EXT_FIRST_EXTENT(path[leaf_ppos].p_hdr); + path[leaf_ppos].p_block = + ext_pblock(path[leaf_ppos].p_ext); return 0; } } @@ -155,40 +166,15 @@ mext_check_null_inode(struct inode *inode1, struct inode *inode2, } /** - * mext_double_down_read - Acquire two inodes' read semaphore + * double_down_write_data_sem - Acquire two inodes' write lock of i_data_sem * * @orig_inode: original inode structure * @donor_inode: donor inode structure - * Acquire read semaphore of the two inodes (orig and donor) by i_ino order. + * Acquire write lock of i_data_sem of the two inodes (orig and donor) by + * i_ino order. */ static void -mext_double_down_read(struct inode *orig_inode, struct inode *donor_inode) -{ - struct inode *first = orig_inode, *second = donor_inode; - - /* - * Use the inode number to provide the stable locking order instead - * of its address, because the C language doesn't guarantee you can - * compare pointers that don't come from the same array. - */ - if (donor_inode->i_ino < orig_inode->i_ino) { - first = donor_inode; - second = orig_inode; - } - - down_read(&EXT4_I(first)->i_data_sem); - down_read(&EXT4_I(second)->i_data_sem); -} - -/** - * mext_double_down_write - Acquire two inodes' write semaphore - * - * @orig_inode: original inode structure - * @donor_inode: donor inode structure - * Acquire write semaphore of the two inodes (orig and donor) by i_ino order. - */ -static void -mext_double_down_write(struct inode *orig_inode, struct inode *donor_inode) +double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) { struct inode *first = orig_inode, *second = donor_inode; @@ -207,28 +193,14 @@ mext_double_down_write(struct inode *orig_inode, struct inode *donor_inode) } /** - * mext_double_up_read - Release two inodes' read semaphore + * double_up_write_data_sem - Release two inodes' write lock of i_data_sem * * @orig_inode: original inode structure to be released its lock first * @donor_inode: donor inode structure to be released its lock second - * Release read semaphore of two inodes (orig and donor). + * Release write lock of i_data_sem of two inodes (orig and donor). */ static void -mext_double_up_read(struct inode *orig_inode, struct inode *donor_inode) -{ - up_read(&EXT4_I(orig_inode)->i_data_sem); - up_read(&EXT4_I(donor_inode)->i_data_sem); -} - -/** - * mext_double_up_write - Release two inodes' write semaphore - * - * @orig_inode: original inode structure to be released its lock first - * @donor_inode: donor inode structure to be released its lock second - * Release write semaphore of two inodes (orig and donor). - */ -static void -mext_double_up_write(struct inode *orig_inode, struct inode *donor_inode) +double_up_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) { up_write(&EXT4_I(orig_inode)->i_data_sem); up_write(&EXT4_I(donor_inode)->i_data_sem); @@ -688,8 +660,6 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, int replaced_count = 0; int dext_alen; - mext_double_down_write(orig_inode, donor_inode); - /* Get the original extent for the block "orig_off" */ *err = get_ext_path(orig_inode, orig_off, &orig_path); if (*err) @@ -785,7 +755,6 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, kfree(donor_path); } - mext_double_up_write(orig_inode, donor_inode); return replaced_count; } @@ -851,6 +820,11 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, * Just swap data blocks between orig and donor. */ if (uninit) { + /* + * Protect extent trees against block allocations + * via delalloc + */ + double_down_write_data_sem(orig_inode, donor_inode); replaced_count = mext_replace_branches(handle, orig_inode, donor_inode, orig_blk_offset, block_len_in_page, err); @@ -858,6 +832,7 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, /* Clear the inode cache not to refer to the old data */ ext4_ext_invalidate_cache(orig_inode); ext4_ext_invalidate_cache(donor_inode); + double_up_write_data_sem(orig_inode, donor_inode); goto out2; } @@ -905,6 +880,8 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, /* Release old bh and drop refs */ try_to_release_page(page, 0); + /* Protect extent trees against block allocations via delalloc */ + double_down_write_data_sem(orig_inode, donor_inode); replaced_count = mext_replace_branches(handle, orig_inode, donor_inode, orig_blk_offset, block_len_in_page, &err2); @@ -913,14 +890,18 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, block_len_in_page = replaced_count; replaced_size = block_len_in_page << orig_inode->i_blkbits; - } else + } else { + double_up_write_data_sem(orig_inode, donor_inode); goto out; + } } /* Clear the inode cache not to refer to the old data */ ext4_ext_invalidate_cache(orig_inode); ext4_ext_invalidate_cache(donor_inode); + double_up_write_data_sem(orig_inode, donor_inode); + if (!page_has_buffers(page)) create_empty_buffers(page, 1 << orig_inode->i_blkbits, 0); @@ -1236,16 +1217,16 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, return -EINVAL; } - /* protect orig and donor against a truncate */ + /* Protect orig and donor inodes against a truncate */ ret1 = mext_inode_double_lock(orig_inode, donor_inode); if (ret1 < 0) return ret1; - mext_double_down_read(orig_inode, donor_inode); + /* Protect extent tree against block allocations via delalloc */ + double_down_write_data_sem(orig_inode, donor_inode); /* Check the filesystem environment whether move_extent can be done */ ret1 = mext_check_arguments(orig_inode, donor_inode, orig_start, donor_start, &len, *moved_len); - mext_double_up_read(orig_inode, donor_inode); if (ret1) goto out; @@ -1308,6 +1289,10 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, ext4_ext_get_actual_len(ext_cur), block_end + 1) - max(le32_to_cpu(ext_cur->ee_block), block_start); + /* Discard preallocations of two inodes */ + ext4_discard_preallocations(orig_inode); + ext4_discard_preallocations(donor_inode); + while (!last_extent && le32_to_cpu(ext_cur->ee_block) <= block_end) { seq_blocks += add_blocks; @@ -1359,14 +1344,14 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, seq_start = le32_to_cpu(ext_cur->ee_block); rest_blocks = seq_blocks; - /* Discard preallocations of two inodes */ - down_write(&EXT4_I(orig_inode)->i_data_sem); - ext4_discard_preallocations(orig_inode); - up_write(&EXT4_I(orig_inode)->i_data_sem); - - down_write(&EXT4_I(donor_inode)->i_data_sem); - ext4_discard_preallocations(donor_inode); - up_write(&EXT4_I(donor_inode)->i_data_sem); + /* + * Up semaphore to avoid following problems: + * a. transaction deadlock among ext4_journal_start, + * ->write_begin via pagefault, and jbd2_journal_commit + * b. racing with ->readpage, ->write_begin, and ext4_get_block + * in move_extent_per_page + */ + double_up_write_data_sem(orig_inode, donor_inode); while (orig_page_offset <= seq_end_page) { @@ -1381,14 +1366,14 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, /* Count how many blocks we have exchanged */ *moved_len += block_len_in_page; if (ret1 < 0) - goto out; + break; if (*moved_len > len) { ext4_error(orig_inode->i_sb, __func__, "We replaced blocks too much! " "sum of replaced: %llu requested: %llu", *moved_len, len); ret1 = -EIO; - goto out; + break; } orig_page_offset++; @@ -1400,6 +1385,10 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, block_len_in_page = rest_blocks; } + double_down_write_data_sem(orig_inode, donor_inode); + if (ret1 < 0) + break; + /* Decrease buffer counter */ if (holecheck_path) ext4_ext_drop_refs(holecheck_path); @@ -1429,7 +1418,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, ext4_ext_drop_refs(holecheck_path); kfree(holecheck_path); } - + double_up_write_data_sem(orig_inode, donor_inode); ret2 = mext_inode_double_unlock(orig_inode, donor_inode); if (ret1) From a752b960d4b57e0d307e1c40b1b47ab849832c0f Mon Sep 17 00:00:00 2001 From: Akira Fujita Date: Mon, 23 Nov 2009 07:24:41 -0500 Subject: [PATCH 009/670] ext4: fix possible recursive locking warning in EXT4_IOC_MOVE_EXT (cherry picked from commit 49bd22bc4d603a2a4fc2a6a60e156cbea52eb494) If CONFIG_PROVE_LOCKING is enabled, the double_down_write_data_sem() will trigger a false-positive warning of a recursive lock. Since we take i_data_sem for the two inodes ordered by their inode numbers, this isn't a problem. Use of down_write_nested() will notify the lock dependency checker machinery that there is no problem here. This problem was reported by Brian Rogers: http://marc.info/?l=linux-ext4&m=125115356928011&w=1 Reported-by: Brian Rogers Signed-off-by: Akira Fujita Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/move_extent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index a7410b34c5ed..2ca6aa3f34e6 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -189,7 +189,7 @@ double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) } down_write(&EXT4_I(first)->i_data_sem); - down_write(&EXT4_I(second)->i_data_sem); + down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); } /** From 21a4b3aaa2180ca6748446c4b06e91f3da244dca Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 14 Nov 2009 08:19:05 -0500 Subject: [PATCH 010/670] ext4: plug a buffer_head leak in an error path of ext4_iget() (cherry picked from commit 567f3e9a70d71e5c9be03701b8578be77857293b) One of the invalid error paths in ext4_iget() forgot to brelse() the inode buffer head. Fix it by adding a brelse() in the common error return path, which also simplifies function. Thanks to Andi Kleen reporting the problem. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 2c8caa51addb..554c6798597c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4781,7 +4781,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) struct ext4_iloc iloc; struct ext4_inode *raw_inode; struct ext4_inode_info *ei; - struct buffer_head *bh; struct inode *inode; long ret; int block; @@ -4793,11 +4792,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) return inode; ei = EXT4_I(inode); + iloc.bh = 0; ret = __ext4_get_inode_loc(inode, &iloc, 0); if (ret < 0) goto bad_inode; - bh = iloc.bh; raw_inode = ext4_raw_inode(&iloc); inode->i_mode = le16_to_cpu(raw_inode->i_mode); inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); @@ -4820,7 +4819,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) if (inode->i_mode == 0 || !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { /* this inode is deleted */ - brelse(bh); ret = -ESTALE; goto bad_inode; } @@ -4852,7 +4850,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > EXT4_INODE_SIZE(inode->i_sb)) { - brelse(bh); ret = -EIO; goto bad_inode; } @@ -4905,10 +4902,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) /* Validate block references which are part of inode */ ret = ext4_check_inode_blockref(inode); } - if (ret) { - brelse(bh); + if (ret) goto bad_inode; - } if (S_ISREG(inode->i_mode)) { inode->i_op = &ext4_file_inode_operations; @@ -4936,7 +4931,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) init_special_inode(inode, inode->i_mode, new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); } else { - brelse(bh); ret = -EIO; ext4_error(inode->i_sb, __func__, "bogus i_mode (%o) for inode=%lu", @@ -4949,6 +4943,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) return inode; bad_inode: + brelse(iloc.bh); iget_failed(inode); return ERR_PTR(ret); } From 0f9036c7eed145cdd8c8ed9e899c61f499278259 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 23 Nov 2009 07:17:34 -0500 Subject: [PATCH 011/670] ext4: make sure directory and symlink blocks are revoked (cherry picked from commit 50689696867d95b38d9c7be640a311494a04fb86) When an inode gets unlinked, the functions ext4_clear_blocks() and ext4_remove_blocks() call ext4_forget() for all the buffer heads corresponding to the deleted inode's data blocks. If the inode is a directory or a symlink, the is_metadata parameter must be non-zero so ext4_forget() will revoke them via jbd2_journal_revoke(). Otherwise, if these blocks are reused for a data file, and the system crashes before a journal checkpoint, the journal replay could end up corrupting these data blocks. Thanks to Curt Wohlgemuth for pointing out potential problems in this area. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/extents.c | 2 +- fs/ext4/inode.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 715264b4bae4..74dcff84c3a8 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2074,7 +2074,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, ext_debug("free last %u blocks starting %llu\n", num, start); for (i = 0; i < num; i++) { bh = sb_find_get_block(inode->i_sb, start + i); - ext4_forget(handle, 0, inode, bh, start + i); + ext4_forget(handle, metadata, inode, bh, start + i); } ext4_free_blocks(handle, inode, start, num, metadata); } else if (from == le32_to_cpu(ex->ee_block) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 554c6798597c..a8dd8028229a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4120,6 +4120,8 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode, __le32 *last) { __le32 *p; + int is_metadata = S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode); + if (try_to_extend_transaction(handle, inode)) { if (bh) { BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); @@ -4150,11 +4152,11 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode, *p = 0; tbh = sb_find_get_block(inode->i_sb, nr); - ext4_forget(handle, 0, inode, tbh, nr); + ext4_forget(handle, is_metadata, inode, tbh, nr); } } - ext4_free_blocks(handle, inode, block_to_free, count, 0); + ext4_free_blocks(handle, inode, block_to_free, count, is_metadata); } /** From 70095d96ced4dbe2ebc7cc0d248313e507dda31a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 15 Nov 2009 15:30:58 -0500 Subject: [PATCH 012/670] ext4: fix i_flags access in ext4_da_writepages_trans_blocks() (cherry picked from commit 30c6e07a92ea4cb87160d32ffa9bce172576ae4c) We need to be testing the i_flags field in the ext4 specific portion of the inode, instead of the (confusingly aliased) i_flags field in the generic struct inode. Signed-off-by: Julia Lawall Signed-off-by: "Theodore Ts'o" 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 a8dd8028229a..1842a72b72b1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2788,7 +2788,7 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) * number of contiguous block. So we will limit * number of contiguous block to a sane value */ - if (!(inode->i_flags & EXT4_EXTENTS_FL) && + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) && (max_blocks > EXT4_MAX_TRANS_DATA)) max_blocks = EXT4_MAX_TRANS_DATA; From 023c1d20ed1d29d5f5e40e79fde1f8f6b6a42e6f Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sun, 15 Nov 2009 15:30:52 -0500 Subject: [PATCH 013/670] ext4: journal all modifications in ext4_xattr_set_handle (cherry picked from commit 86ebfd08a1930ccedb8eac0aeb1ed4b8b6a41dbc) ext4_xattr_set_handle() was zeroing out an inode outside of journaling constraints; this is one of the accesses that was causing the crc errors in journal replay as seen in kernel.org bugzilla #14354. Reviewed-by: Andreas Dilger Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/xattr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index fed5b01d7a8d..025701926f9a 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -988,6 +988,10 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, if (error) goto cleanup; + error = ext4_journal_get_write_access(handle, is.iloc.bh); + if (error) + goto cleanup; + if (EXT4_I(inode)->i_state & EXT4_STATE_NEW) { struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc); memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size); @@ -1013,9 +1017,6 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, if (flags & XATTR_CREATE) goto cleanup; } - error = ext4_journal_get_write_access(handle, is.iloc.bh); - if (error) - goto cleanup; if (!value) { if (!is.s.not_found) error = ext4_xattr_ibody_set(handle, inode, &i, &is); From 9e9ddddfe74189e2f2514ed2d8eb9ef3f015118f Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 23 Nov 2009 07:24:52 -0500 Subject: [PATCH 014/670] ext4: don't update the superblock in ext4_statfs() (cherry picked from commit 3f8fb9490efbd300887470a2a880a64e04dcc3f5) commit a71ce8c6c9bf269b192f352ea555217815cf027e updated ext4_statfs() to update the on-disk superblock counters, but modified this buffer directly without any journaling of the change. This is one of the accesses that was causing the crc errors in journal replay as seen in kernel.org bugzilla #14354. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 8662b2e6e9f9..3cd519b8fb1c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3668,13 +3668,11 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); - ext4_free_blocks_count_set(es, buf->f_bfree); buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); if (buf->f_bfree < ext4_r_blocks_count(es)) buf->f_bavail = 0; buf->f_files = le32_to_cpu(es->s_inodes_count); buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter); - es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); buf->f_namelen = EXT4_NAME_LEN; fsid = le64_to_cpup((void *)es->s_uuid) ^ le64_to_cpup((void *)es->s_uuid + sizeof(u64)); From 58ffefbe7bf2bdfc6f91b79eef9d670df6eab4d3 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 23 Nov 2009 07:24:38 -0500 Subject: [PATCH 015/670] ext4: fix uninit block bitmap initialization when s_meta_first_bg is non-zero (cherry picked from commit 8dadb198cb70ef811916668fe67eeec82e8858dd) The number of old-style block group descriptor blocks is s_meta_first_bg when the meta_bg feature flag is set. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/balloc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 1d0418980f8d..f3032c919a22 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -761,7 +761,13 @@ static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb, static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, ext4_group_t group) { - return ext4_bg_has_super(sb, group) ? EXT4_SB(sb)->s_gdb_count : 0; + if (!ext4_bg_has_super(sb, group)) + return 0; + + if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG)) + return le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg); + else + return EXT4_SB(sb)->s_gdb_count; } /** From 31299e22be94e77b6df41d022e8f0bd075537d58 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 15 Nov 2009 15:29:56 -0500 Subject: [PATCH 016/670] ext4: fix block validity checks so they work correctly with meta_bg (cherry picked from commit 1032988c71f3f85483b2b4319684d1205a704c02) The block validity checks used by ext4_data_block_valid() wasn't correctly written to check file systems with the meta_bg feature. Fix this. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/block_validity.c | 2 +- fs/ext4/inode.c | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index 50784ef07563..dc79b75d8f70 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c @@ -160,7 +160,7 @@ int ext4_setup_system_zone(struct super_block *sb) if (ext4_bg_has_super(sb, i) && ((i < 5) || ((i % flex_size) == 0))) add_system_zone(sbi, ext4_group_first_block_no(sb, i), - sbi->s_gdb_count + 1); + ext4_bg_num_gdb(sb, i) + 1); gdp = ext4_get_group_desc(sb, i, NULL); ret = add_system_zone(sbi, ext4_block_bitmap(sb, gdp), 1); if (ret) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 1842a72b72b1..68c9055a4d91 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4883,10 +4883,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ret = 0; if (ei->i_file_acl && - ((ei->i_file_acl < - (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) + - EXT4_SB(sb)->s_gdb_count)) || - (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) { + !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) { ext4_error(sb, __func__, "bad extended attribute block %llu in inode #%lu", ei->i_file_acl, inode->i_ino); From 43e932d3116f3a74f1b5ff0a38cca5e0bac1099a Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 23 Nov 2009 07:24:57 -0500 Subject: [PATCH 017/670] ext4: avoid issuing unnecessary barriers (cherry picked from commit 6b17d902fdd241adfa4ce780df20547b28bf5801) We don't to issue an I/O barrier on an error or if we force commit because we are doing data journaling. Signed-off-by: "Theodore Ts'o" Cc: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/ext4/fsync.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 2b1531266ee2..a3c25076aef1 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -60,7 +60,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) ret = flush_aio_dio_completed_IO(inode); if (ret < 0) - goto out; + return ret; /* * data=writeback: * The caller's filemap_fdatawrite()/wait will sync the data. @@ -79,10 +79,8 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ - if (ext4_should_journal_data(inode)) { - ret = ext4_force_commit(inode->i_sb); - goto out; - } + if (ext4_should_journal_data(inode)) + return ext4_force_commit(inode->i_sb); if (!journal) ret = sync_mapping_buffers(inode->i_mapping); From cd9c823a6830d6c84f50fe7dabaf281c542d13ef Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 23 Nov 2009 07:24:48 -0500 Subject: [PATCH 018/670] ext4: fix error handling in ext4_ind_get_blocks() (cherry picked from commit 2bba702d4f88d7b010ec37e2527b552588404ae7) When an error happened in ext4_splice_branch we failed to notice that in ext4_ind_get_blocks and mapped the buffer anyway. Fix the problem by checking for error properly. Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" 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 68c9055a4d91..c27816a2c4fd 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1021,7 +1021,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, if (!err) err = ext4_splice_branch(handle, inode, iblock, partial, indirect_blks, count); - else + if (err) goto cleanup; set_buffer_new(bh_result); From feac39ba7f50e851f4e20466e5d390f046932287 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 19 Nov 2009 14:25:42 -0500 Subject: [PATCH 019/670] ext4: make trim/discard optional (and off by default) (cherry picked from commit 5328e635315734d42080de9a5a1ee87bf4cae0a4) It is anticipated that when sb_issue_discard starts doing real work on trim-capable devices, we may see issues. Make this mount-time optional, and default it to off until we know that things are working out OK. Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/ext4.txt | 6 ++++++ fs/ext4/ext4.h | 1 + fs/ext4/mballoc.c | 19 ++++++++++++------- fs/ext4/super.c | 14 +++++++++++++- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 6d94e0696f8c..26904ff6d61b 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt @@ -353,6 +353,12 @@ noauto_da_alloc replacing existing files via patterns such as system crashes before the delayed allocation blocks are forced to disk. +discard Controls whether ext4 should issue discard/TRIM +nodiscard(*) commands to the underlying block device when + blocks are freed. This is useful for SSD devices + and sparse/thinly-provisioned LUNs, but it is off + by default until sufficient testing has been done. + Data Mode ========= There are 3 different data modes: diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 8825515eeddd..05ce38b981cb 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -750,6 +750,7 @@ struct ext4_inode_info { #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ +#define EXT4_MOUNT_DISCARD 0x40000000 /* Issue DISCARD requests */ #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt #define set_opt(o, opt) o |= EXT4_MOUNT_##opt diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index bba12824defa..6e5a23a2cc25 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2529,7 +2529,6 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) struct ext4_group_info *db; int err, count = 0, count2 = 0; struct ext4_free_data *entry; - ext4_fsblk_t discard_block; struct list_head *l, *ltmp; list_for_each_safe(l, ltmp, &txn->t_private_list) { @@ -2559,13 +2558,19 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) page_cache_release(e4b.bd_bitmap_page); } ext4_unlock_group(sb, entry->group); - discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb) - + entry->start_blk - + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); - trace_ext4_discard_blocks(sb, (unsigned long long)discard_block, - entry->count); - sb_issue_discard(sb, discard_block, entry->count); + if (test_opt(sb, DISCARD)) { + ext4_fsblk_t discard_block; + struct ext4_super_block *es = EXT4_SB(sb)->s_es; + discard_block = (ext4_fsblk_t)entry->group * + EXT4_BLOCKS_PER_GROUP(sb) + + entry->start_blk + + le32_to_cpu(es->s_first_data_block); + trace_ext4_discard_blocks(sb, + (unsigned long long)discard_block, + entry->count); + sb_issue_discard(sb, discard_block, entry->count); + } kmem_cache_free(ext4_free_ext_cachep, entry); ext4_mb_release_desc(&e4b); } diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 3cd519b8fb1c..86edc41a8284 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -899,6 +899,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) if (test_opt(sb, NO_AUTO_DA_ALLOC)) seq_puts(seq, ",noauto_da_alloc"); + if (test_opt(sb, DISCARD)) + seq_puts(seq, ",discard"); + ext4_show_quota_options(seq, sb); return 0; @@ -1079,7 +1082,8 @@ enum { Opt_usrquota, Opt_grpquota, Opt_i_version, Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_block_validity, Opt_noblock_validity, - Opt_inode_readahead_blks, Opt_journal_ioprio + Opt_inode_readahead_blks, Opt_journal_ioprio, + Opt_discard, Opt_nodiscard, }; static const match_table_t tokens = { @@ -1144,6 +1148,8 @@ static const match_table_t tokens = { {Opt_auto_da_alloc, "auto_da_alloc=%u"}, {Opt_auto_da_alloc, "auto_da_alloc"}, {Opt_noauto_da_alloc, "noauto_da_alloc"}, + {Opt_discard, "discard"}, + {Opt_nodiscard, "nodiscard"}, {Opt_err, NULL}, }; @@ -1565,6 +1571,12 @@ static int parse_options(char *options, struct super_block *sb, else set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC); break; + case Opt_discard: + set_opt(sbi->s_mount_opt, DISCARD); + break; + case Opt_nodiscard: + clear_opt(sbi->s_mount_opt, DISCARD); + break; default: ext4_msg(sb, KERN_ERR, "Unrecognized mount option \"%s\" " From 6011d0baad8d5229445b1e0f7b6bdfcaf9cbff26 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 19 Nov 2009 14:28:50 -0500 Subject: [PATCH 020/670] ext4: make "norecovery" an alias for "noload" (cherry picked from commit e3bb52ae2bb9573e84c17b8e3560378d13a5c798) Users on the linux-ext4 list recently complained about differences across filesystems w.r.t. how to mount without a journal replay. In the discussion it was noted that xfs's "norecovery" option is perhaps more descriptively accurate than "noload," so let's make that an alias for ext4. Also show this status in /proc/mounts Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/ext4.txt | 4 ++-- fs/ext4/super.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 26904ff6d61b..af6885c3c821 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt @@ -153,8 +153,8 @@ journal_dev=devnum When the external journal device's major/minor numbers identified through its new major/minor numbers encoded in devnum. -noload Don't load the journal on mounting. Note that - if the filesystem was not unmounted cleanly, +norecovery Don't load the journal on mounting. Note that +noload if the filesystem was not unmounted cleanly, skipping the journal replay will lead to the filesystem containing inconsistencies that can lead to any number of problems. diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 86edc41a8284..dad64a1a23aa 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -902,6 +902,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) if (test_opt(sb, DISCARD)) seq_puts(seq, ",discard"); + if (test_opt(sb, NOLOAD)) + seq_puts(seq, ",norecovery"); + ext4_show_quota_options(seq, sb); return 0; @@ -1108,6 +1111,7 @@ static const match_table_t tokens = { {Opt_acl, "acl"}, {Opt_noacl, "noacl"}, {Opt_noload, "noload"}, + {Opt_noload, "norecovery"}, {Opt_nobh, "nobh"}, {Opt_bh, "bh"}, {Opt_commit, "commit=%u"}, From 74920c74ad3802bc81f5ccbb737d351073dd3ff9 Mon Sep 17 00:00:00 2001 From: Akira Fujita Date: Tue, 24 Nov 2009 10:19:57 -0500 Subject: [PATCH 021/670] ext4: Fix double-free of blocks with EXT4_IOC_MOVE_EXT (cherry picked from commit 94d7c16cbbbd0e03841fcf272bcaf0620ad39618) At the beginning of ext4_move_extent(), we call ext4_discard_preallocations() to discard inode PAs of orig and donor inodes. But in the following case, blocks can be double freed, so move ext4_discard_preallocations() to the end of ext4_move_extents(). 1. Discard inode PAs of orig and donor inodes with ext4_discard_preallocations() in ext4_move_extents(). orig : [ DATA1 ] donor: [ DATA2 ] 2. While data blocks are exchanging between orig and donor inodes, new inode PAs is created to orig by other process's block allocation. (Since there are semaphore gaps in ext4_move_extents().) And new inode PAs is used partially (2-1). 2-1 Create new inode PAs to orig inode orig : [ DATA1 | used PA1 | free PA1 ] donor: [ DATA2 ] 3. Donor inode which has old orig inode's blocks is deleted after EXT4_IOC_MOVE_EXT finished (3-1, 3-2). So the block bitmap corresponds to old orig inode's blocks are freed. 3-1 After EXT4_IOC_MOVE_EXT finished orig : [ DATA2 | free PA1 ] donor: [ DATA1 | used PA1 ] 3-2 Delete donor inode orig : [ DATA2 | free PA1 ] donor: [ FREE SPACE(DATA1) | FREE SPACE(used PA1) ] 4. The double-free of blocks is occurred, when close() is called to orig inode. Because ext4_discard_preallocations() for orig inode frees used PA1 and free PA1, though used PA1 is already freed in 3. 4-1 Double-free of blocks is occurred orig : [ DATA2 | FREE SPACE(free PA1) ] donor: [ FREE SPACE(DATA1) | DOUBLE FREE(used PA1) ] Signed-off-by: Akira Fujita Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/move_extent.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 2ca6aa3f34e6..71a62312fff6 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -1289,10 +1289,6 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, ext4_ext_get_actual_len(ext_cur), block_end + 1) - max(le32_to_cpu(ext_cur->ee_block), block_start); - /* Discard preallocations of two inodes */ - ext4_discard_preallocations(orig_inode); - ext4_discard_preallocations(donor_inode); - while (!last_extent && le32_to_cpu(ext_cur->ee_block) <= block_end) { seq_blocks += add_blocks; @@ -1410,6 +1406,11 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, } out: + if (*moved_len) { + ext4_discard_preallocations(orig_inode); + ext4_discard_preallocations(donor_inode); + } + if (orig_path) { ext4_ext_drop_refs(orig_path); kfree(orig_path); From 3369cbb6bedae7e8c7600b33803a8e69b2a6e99f Mon Sep 17 00:00:00 2001 From: Kazuya Mio Date: Tue, 24 Nov 2009 10:28:48 -0500 Subject: [PATCH 022/670] ext4: initialize moved_len before calling ext4_move_extents() (cherry picked from commit 446aaa6e7e993b38a6f21c6acfa68f3f1af3dbe3) The move_extent.moved_len is used to pass back the number of exchanged blocks count to user space. Currently the caller must clear this field; but we spend more code space checking for this requirement than simply zeroing the field ourselves, so let's just make life easier for everyone all around. Signed-off-by: Kazuya Mio Signed-off-by: Akira Fujita Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ioctl.c | 1 + fs/ext4/move_extent.c | 14 +++----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index c1cdf613e725..31e5ee0c858f 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -239,6 +239,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } + me.moved_len = 0; err = ext4_move_extents(filp, donor_filp, me.orig_start, me.donor_start, me.len, &me.moved_len); fput(donor_filp); diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 71a62312fff6..5f3774232470 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -947,7 +947,6 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, * @orig_start: logical start offset in block for orig * @donor_start: logical start offset in block for donor * @len: the number of blocks to be moved - * @moved_len: moved block length * * Check the arguments of ext4_move_extents() whether the files can be * exchanged with each other. @@ -955,8 +954,8 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, */ static int mext_check_arguments(struct inode *orig_inode, - struct inode *donor_inode, __u64 orig_start, - __u64 donor_start, __u64 *len, __u64 moved_len) + struct inode *donor_inode, __u64 orig_start, + __u64 donor_start, __u64 *len) { ext4_lblk_t orig_blocks, donor_blocks; unsigned int blkbits = orig_inode->i_blkbits; @@ -1010,13 +1009,6 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } - if (moved_len) { - ext4_debug("ext4 move extent: moved_len should be 0 " - "[ino:orig %lu, donor %lu]\n", orig_inode->i_ino, - donor_inode->i_ino); - return -EINVAL; - } - if ((orig_start > EXT_MAX_BLOCK) || (donor_start > EXT_MAX_BLOCK) || (*len > EXT_MAX_BLOCK) || @@ -1226,7 +1218,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, double_down_write_data_sem(orig_inode, donor_inode); /* Check the filesystem environment whether move_extent can be done */ ret1 = mext_check_arguments(orig_inode, donor_inode, orig_start, - donor_start, &len, *moved_len); + donor_start, &len); if (ret1) goto out; From ce5cf38ef17272ad2641c723c6d0d8eaf1c34eab Mon Sep 17 00:00:00 2001 From: Akira Fujita Date: Tue, 24 Nov 2009 10:31:56 -0500 Subject: [PATCH 023/670] ext4: move_extent_per_page() cleanup (cherry picked from commit ac48b0a1d068887141581bea8285de5fcab182b0) Integrate duplicate lines (acquire/release semaphore and invalidate extent cache in move_extent_per_page()) into mext_replace_branches(), to reduce source and object code size. Signed-off-by: Akira Fujita Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/move_extent.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 5f3774232470..bcc41e63965c 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -660,6 +660,9 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, int replaced_count = 0; int dext_alen; + /* Protect extent trees against block allocations via delalloc */ + double_down_write_data_sem(orig_inode, donor_inode); + /* Get the original extent for the block "orig_off" */ *err = get_ext_path(orig_inode, orig_off, &orig_path); if (*err) @@ -755,6 +758,11 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, kfree(donor_path); } + ext4_ext_invalidate_cache(orig_inode); + ext4_ext_invalidate_cache(donor_inode); + + double_up_write_data_sem(orig_inode, donor_inode); + return replaced_count; } @@ -820,19 +828,9 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, * Just swap data blocks between orig and donor. */ if (uninit) { - /* - * Protect extent trees against block allocations - * via delalloc - */ - double_down_write_data_sem(orig_inode, donor_inode); replaced_count = mext_replace_branches(handle, orig_inode, donor_inode, orig_blk_offset, block_len_in_page, err); - - /* Clear the inode cache not to refer to the old data */ - ext4_ext_invalidate_cache(orig_inode); - ext4_ext_invalidate_cache(donor_inode); - double_up_write_data_sem(orig_inode, donor_inode); goto out2; } @@ -880,8 +878,6 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, /* Release old bh and drop refs */ try_to_release_page(page, 0); - /* Protect extent trees against block allocations via delalloc */ - double_down_write_data_sem(orig_inode, donor_inode); replaced_count = mext_replace_branches(handle, orig_inode, donor_inode, orig_blk_offset, block_len_in_page, &err2); @@ -890,18 +886,10 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode, block_len_in_page = replaced_count; replaced_size = block_len_in_page << orig_inode->i_blkbits; - } else { - double_up_write_data_sem(orig_inode, donor_inode); + } else goto out; - } } - /* Clear the inode cache not to refer to the old data */ - ext4_ext_invalidate_cache(orig_inode); - ext4_ext_invalidate_cache(donor_inode); - - double_up_write_data_sem(orig_inode, donor_inode); - if (!page_has_buffers(page)) create_empty_buffers(page, 1 << orig_inode->i_blkbits, 0); From 86d291a39650e05c9db7c0d849e48beaf39efcdd Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 1 Dec 2009 09:04:42 -0500 Subject: [PATCH 024/670] jbd2: Add ENOMEM checking in and for jbd2_journal_write_metadata_buffer() (cherry picked from commit e6ec116b67f46e0e7808276476554727b2e6240b) OOM happens. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/jbd2/commit.c | 4 ++++ fs/jbd2/journal.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index d4cfd6d2779e..8896c1d4febe 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -636,6 +636,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) JBUFFER_TRACE(jh, "ph3: write metadata"); flags = jbd2_journal_write_metadata_buffer(commit_transaction, jh, &new_jh, blocknr); + if (flags < 0) { + jbd2_journal_abort(journal, flags); + continue; + } set_bit(BH_JWrite, &jh2bh(new_jh)->b_state); wbuf[bufs++] = jh2bh(new_jh); diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index fed85388ee86..c974077915fa 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -358,6 +358,10 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction, jbd_unlock_bh_state(bh_in); tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS); + if (!tmp) { + jbd2_journal_put_journal_head(new_jh); + return -ENOMEM; + } jbd_lock_bh_state(bh_in); if (jh_in->b_frozen_data) { jbd2_free(tmp, bh_in->b_size); From 66c3a718335ccd37ac14c4f0f2d0a7551af562ed Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 7 Dec 2009 10:38:16 -0500 Subject: [PATCH 025/670] ext4: Return the PTR_ERR of the correct pointer in setup_new_group_blocks() (cherry picked from commit c09eef305dd43846360944ad072f051f964fa383) Signed-off-by: Roel Kluin Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/resize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 3cfc343c41b5..3b2c5541d8a6 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -247,7 +247,7 @@ static int setup_new_group_blocks(struct super_block *sb, goto exit_bh; if (IS_ERR(gdb = bclean(handle, sb, block))) { - err = PTR_ERR(bh); + err = PTR_ERR(gdb); goto exit_bh; } ext4_handle_dirty_metadata(handle, NULL, gdb); From 35a6f7824919816fca466997531885044d290b59 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 8 Dec 2009 21:24:33 -0500 Subject: [PATCH 026/670] ext4: Avoid data / filesystem corruption when write fails to copy data (cherry picked from commit b9a4207d5e911b938f73079a83cc2ae10524ec7f) When ext4_write_begin fails after allocating some blocks or generic_perform_write fails to copy data to write, we truncate blocks already instantiated beyond i_size. Although these blocks were never inside i_size, we have to truncate the pagecache of these blocks so that corresponding buffers get unmapped. Otherwise subsequent __block_prepare_write (called because we are retrying the write) will find the buffers mapped, not call ->get_block, and thus the page will be backed by already freed blocks leading to filesystem and data corruption. Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c27816a2c4fd..87406c61eca1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1534,6 +1534,16 @@ static int do_journal_get_write_access(handle_t *handle, return ext4_journal_get_write_access(handle, bh); } +/* + * Truncate blocks that were not used by write. We have to truncate the + * pagecache as well so that corresponding buffers get properly unmapped. + */ +static void ext4_truncate_failed_write(struct inode *inode) +{ + truncate_inode_pages(inode->i_mapping, inode->i_size); + ext4_truncate(inode); +} + static int ext4_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) @@ -1599,7 +1609,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, ext4_journal_stop(handle); if (pos + len > inode->i_size) { - ext4_truncate(inode); + ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might * still be on the orphan list; we need to @@ -1709,7 +1719,7 @@ static int ext4_ordered_write_end(struct file *file, ret = ret2; if (pos + len > inode->i_size) { - ext4_truncate(inode); + ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might still be * on the orphan list; we need to make sure the inode @@ -1751,7 +1761,7 @@ static int ext4_writeback_write_end(struct file *file, ret = ret2; if (pos + len > inode->i_size) { - ext4_truncate(inode); + ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might still be * on the orphan list; we need to make sure the inode @@ -1814,7 +1824,7 @@ static int ext4_journalled_write_end(struct file *file, if (!ret) ret = ret2; if (pos + len > inode->i_size) { - ext4_truncate(inode); + ext4_truncate_failed_write(inode); /* * If truncate failed early the inode might still be * on the orphan list; we need to make sure the inode @@ -3091,7 +3101,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, * i_size_read because we hold i_mutex. */ if (pos + len > inode->i_size) - ext4_truncate(inode); + ext4_truncate_failed_write(inode); } if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) From 1cd3f1980ce02bd814879ce1ac9cde5eaceb5f13 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 8 Dec 2009 21:48:58 -0500 Subject: [PATCH 027/670] ext4: wait for log to commit when umounting (cherry picked from commit d4edac314e9ad0b21ba20ba8bc61b61f186f79e1) There is a potential race when a transaction is committing right when the file system is being umounting. This could reduce in a race because EXT4_SB(sb)->s_group_info could be freed in ext4_put_super before the commit code calls a callback so the mballoc code can release freed blocks in the transaction, resulting in a panic trying to access the freed s_group_info. The fix is to wait for the transaction to finish committing before we shutdown the multiblock allocator. Signed-off-by: Josef Bacik Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/super.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index dad64a1a23aa..803fb252c111 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -603,10 +603,6 @@ static void ext4_put_super(struct super_block *sb) if (sb->s_dirt) ext4_commit_super(sb, 1); - ext4_release_system_zone(sb); - ext4_mb_release(sb); - ext4_ext_release(sb); - ext4_xattr_put_super(sb); if (sbi->s_journal) { err = jbd2_journal_destroy(sbi->s_journal); sbi->s_journal = NULL; @@ -614,6 +610,12 @@ static void ext4_put_super(struct super_block *sb) ext4_abort(sb, __func__, "Couldn't clean up the journal"); } + + ext4_release_system_zone(sb); + ext4_mb_release(sb); + ext4_ext_release(sb); + ext4_xattr_put_super(sb); + if (!(sb->s_flags & MS_RDONLY)) { EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); es->s_state = cpu_to_le16(sbi->s_mount_state); From 637b13106b744398b530fe916eb1556aeb7f6bca Mon Sep 17 00:00:00 2001 From: Curt Wohlgemuth Date: Tue, 8 Dec 2009 22:18:25 -0500 Subject: [PATCH 028/670] ext4: remove blocks from inode prealloc list on failure (cherry picked from commit b844167edc7fcafda9623955c05e4c1b3c32ebc7) This fixes a leak of blocks in an inode prealloc list if device failures cause ext4_mb_mark_diskspace_used() to fail. Signed-off-by: Curt Wohlgemuth Acked-by: Aneesh Kumar K.V Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/mballoc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 6e5a23a2cc25..7d7114818f8d 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3010,6 +3010,24 @@ static void ext4_mb_collect_stats(struct ext4_allocation_context *ac) trace_ext4_mballoc_prealloc(ac); } +/* + * Called on failure; free up any blocks from the inode PA for this + * context. We don't need this for MB_GROUP_PA because we only change + * pa_free in ext4_mb_release_context(), but on failure, we've already + * zeroed out ac->ac_b_ex.fe_len, so group_pa->pa_free is not changed. + */ +static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac) +{ + struct ext4_prealloc_space *pa = ac->ac_pa; + int len; + + if (pa && pa->pa_type == MB_INODE_PA) { + len = ac->ac_b_ex.fe_len; + pa->pa_free += len; + } + +} + /* * use blocks preallocated to inode */ @@ -4295,6 +4313,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, ac->ac_status = AC_STATUS_CONTINUE; goto repeat; } else if (*errp) { + ext4_discard_allocated_blocks(ac); ac->ac_b_ex.fe_len = 0; ar->len = 0; ext4_mb_show_ac(ac); From 6798788a72ee430761aa41c02f770ee3afb9c212 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Tue, 8 Dec 2009 22:41:52 -0500 Subject: [PATCH 029/670] ext4: ext4_get_reserved_space() must return bytes instead of blocks (cherry picked from commit 8aa6790f876e81f5a2211fe1711a5fe3fe2d7b20) Signed-off-by: Dmitry Monakhov Reviewed-by: Eric Sandeen Acked-by: Mingming Cao Signed-off-by: "Theodore Ts'o" 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 87406c61eca1..86469775cca4 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1052,7 +1052,7 @@ qsize_t ext4_get_reserved_space(struct inode *inode) EXT4_I(inode)->i_reserved_meta_blocks; spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); - return total; + return (total << inode->i_blkbits); } /* * Calculate the number of metadata blocks need to reserve From da2068b384bbfaae98ff55f1424be88c65bf801b Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Tue, 8 Dec 2009 22:42:15 -0500 Subject: [PATCH 030/670] ext4: quota macros cleanup (cherry picked from commit 5aca07eb7d8f14d90c740834d15ca15277f4820c) Currently all quota block reservation macros contains hard-coded "2" aka MAXQUOTAS value. This is no good because in some places it is not obvious to understand what does this digit represent. Let's introduce new macro with self descriptive name. Signed-off-by: Dmitry Monakhov Acked-by: Mingming Cao Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ext4_jbd2.h | 8 ++++++-- fs/ext4/extents.c | 2 +- fs/ext4/inode.c | 2 +- fs/ext4/migrate.c | 4 ++-- fs/ext4/namei.c | 8 ++++---- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index a2865980342f..404ab6c824d3 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -49,7 +49,7 @@ #define EXT4_DATA_TRANS_BLOCKS(sb) (EXT4_SINGLEDATA_TRANS_BLOCKS(sb) + \ EXT4_XATTR_TRANS_BLOCKS - 2 + \ - 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) + EXT4_MAXQUOTAS_TRANS_BLOCKS(sb)) /* * Define the number of metadata blocks we need to account to modify data. @@ -57,7 +57,7 @@ * This include super block, inode block, quota blocks and xattr blocks */ #define EXT4_META_TRANS_BLOCKS(sb) (EXT4_XATTR_TRANS_BLOCKS + \ - 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) + EXT4_MAXQUOTAS_TRANS_BLOCKS(sb)) /* Delete operations potentially hit one directory's namespace plus an * entire inode, plus arbitrary amounts of bitmap/indirection data. Be @@ -92,6 +92,7 @@ * but inode, sb and group updates are done only once */ #define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\ (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0) + #define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\ (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0) #else @@ -99,6 +100,9 @@ #define EXT4_QUOTA_INIT_BLOCKS(sb) 0 #define EXT4_QUOTA_DEL_BLOCKS(sb) 0 #endif +#define EXT4_MAXQUOTAS_TRANS_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_TRANS_BLOCKS(sb)) +#define EXT4_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb)) +#define EXT4_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb)) int ext4_mark_iloc_dirty(handle_t *handle, diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 74dcff84c3a8..499d6bb9be94 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2167,7 +2167,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, correct_index = 1; credits += (ext_depth(inode)) + 1; } - credits += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); + credits += EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb); err = ext4_ext_truncate_extend_restart(handle, inode, credits); if (err) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 86469775cca4..e08e81b4f7d1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5231,7 +5231,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) /* (user+group)*(old+new) structure, inode write (sb, * inode block, ? - but truncate inode update has it) */ - handle = ext4_journal_start(inode, 2*(EXT4_QUOTA_INIT_BLOCKS(inode->i_sb)+ + handle = ext4_journal_start(inode, (EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)+ EXT4_QUOTA_DEL_BLOCKS(inode->i_sb))+3); if (IS_ERR(handle)) { error = PTR_ERR(handle); diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index a93d5b80f3e2..864614974536 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -238,7 +238,7 @@ static int extend_credit_for_blkdel(handle_t *handle, struct inode *inode) * So allocate a credit of 3. We may update * quota (user and group). */ - needed = 3 + 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); + needed = 3 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb); if (ext4_journal_extend(handle, needed) != 0) retval = ext4_journal_restart(handle, needed); @@ -477,7 +477,7 @@ int ext4_ext_migrate(struct inode *inode) handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + - 2 * EXT4_QUOTA_INIT_BLOCKS(inode->i_sb) + EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb) + 1); if (IS_ERR(handle)) { retval = PTR_ERR(handle); diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index fde08c919d12..17a17e10dd60 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1769,7 +1769,7 @@ static int ext4_create(struct inode *dir, struct dentry *dentry, int mode, retry: handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + - 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -1803,7 +1803,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry, retry: handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + - 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -1840,7 +1840,7 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode) retry: handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + - 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2253,7 +2253,7 @@ static int ext4_symlink(struct inode *dir, retry: handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) + EXT4_INDEX_EXTRA_TRANS_BLOCKS + 5 + - 2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb)); + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); From caa305aa349212c285ad9564b9ff2ffa040b193c Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Tue, 8 Dec 2009 22:42:28 -0500 Subject: [PATCH 031/670] ext4: fix incorrect block reservation on quota transfer. (cherry picked from commit 194074acacebc169ded90a4657193f5180015051) Inside ->setattr() call both ATTR_UID and ATTR_GID may be valid This means that we may end-up with transferring all quotas. Add we have to reserve QUOTA_DEL_BLOCKS for all quotas, as we do in case of QUOTA_INIT_BLOCKS. Signed-off-by: Dmitry Monakhov Reviewed-by: Mingming Cao Signed-off-by: "Theodore Ts'o" 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 e08e81b4f7d1..64086fb96e47 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5232,7 +5232,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) /* (user+group)*(old+new) structure, inode write (sb, * inode block, ? - but truncate inode update has it) */ handle = ext4_journal_start(inode, (EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)+ - EXT4_QUOTA_DEL_BLOCKS(inode->i_sb))+3); + EXT4_MAXQUOTAS_DEL_BLOCKS(inode->i_sb))+3); if (IS_ERR(handle)) { error = PTR_ERR(handle); goto err_out; From eebb744d30006474a8f63af098bc71f0cb209677 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 8 Dec 2009 23:51:10 -0500 Subject: [PATCH 032/670] ext4: Wait for proper transaction commit on fsync (cherry picked from commit b436b9bef84de6893e86346d8fbf7104bc520645) We cannot rely on buffer dirty bits during fsync because pdflush can come before fsync is called and clear dirty bits without forcing a transaction commit. What we do is that we track which transaction has last changed the inode and which transaction last changed allocation and force it to disk on fsync. Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ext4.h | 7 +++++++ fs/ext4/ext4_jbd2.h | 13 +++++++++++++ fs/ext4/extents.c | 14 ++++++++++++-- fs/ext4/fsync.c | 46 +++++++++++++++++---------------------------- fs/ext4/inode.c | 29 ++++++++++++++++++++++++++++ fs/ext4/super.c | 2 ++ fs/jbd2/journal.c | 1 + 7 files changed, 81 insertions(+), 31 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 05ce38b981cb..bd2a9dd1464c 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -703,6 +703,13 @@ struct ext4_inode_info { struct list_head i_aio_dio_complete_list; /* current io_end structure for async DIO write*/ ext4_io_end_t *cur_aio_dio; + + /* + * Transactions that contain inode's metadata needed to complete + * fsync and fdatasync, respectively. + */ + tid_t i_sync_tid; + tid_t i_datasync_tid; }; /* diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index 404ab6c824d3..1892a7763426 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -258,6 +258,19 @@ static inline int ext4_jbd2_file_inode(handle_t *handle, struct inode *inode) return 0; } +static inline void ext4_update_inode_fsync_trans(handle_t *handle, + struct inode *inode, + int datasync) +{ + struct ext4_inode_info *ei = EXT4_I(inode); + + if (ext4_handle_valid(handle)) { + ei->i_sync_tid = handle->h_transaction->t_tid; + if (datasync) + ei->i_datasync_tid = handle->h_transaction->t_tid; + } +} + /* super.c */ int ext4_force_commit(struct super_block *sb); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 499d6bb9be94..43c04ff653c6 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3064,6 +3064,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) { ret = ext4_convert_unwritten_extents_dio(handle, inode, path); + if (ret >= 0) + ext4_update_inode_fsync_trans(handle, inode, 1); goto out2; } /* buffered IO case */ @@ -3091,6 +3093,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, ret = ext4_ext_convert_to_initialized(handle, inode, path, iblock, max_blocks); + if (ret >= 0) + ext4_update_inode_fsync_trans(handle, inode, 1); out: if (ret <= 0) { err = ret; @@ -3329,10 +3333,16 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, allocated = ext4_ext_get_actual_len(&newex); set_buffer_new(bh_result); - /* Cache only when it is _not_ an uninitialized extent */ - if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) + /* + * Cache the extent and update transaction to commit on fdatasync only + * when it is _not_ an uninitialized extent. + */ + if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) { ext4_ext_put_in_cache(inode, iblock, allocated, newblock, EXT4_EXT_CACHE_EXTENT); + ext4_update_inode_fsync_trans(handle, inode, 1); + } else + ext4_update_inode_fsync_trans(handle, inode, 0); out: if (allocated > max_blocks) allocated = max_blocks; diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index a3c25076aef1..d6049e40b161 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -51,25 +51,30 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; + struct ext4_inode_info *ei = EXT4_I(inode); journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; - int err, ret = 0; + int ret; + tid_t commit_tid; J_ASSERT(ext4_journal_current_handle() == NULL); trace_ext4_sync_file(file, dentry, datasync); + if (inode->i_sb->s_flags & MS_RDONLY) + return 0; + ret = flush_aio_dio_completed_IO(inode); if (ret < 0) return ret; + + if (!journal) + return simple_fsync(file, dentry, datasync); + /* - * data=writeback: + * data=writeback,ordered: * The caller's filemap_fdatawrite()/wait will sync the data. - * sync_inode() will sync the metadata - * - * data=ordered: - * The caller's filemap_fdatawrite() will write the data and - * sync_inode() will write the inode if it is dirty. Then the caller's - * filemap_fdatawait() will wait on the pages. + * Metadata is in the journal, we wait for proper transaction to + * commit here. * * data=journal: * filemap_fdatawrite won't do anything (the buffers are clean). @@ -82,27 +87,10 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) if (ext4_should_journal_data(inode)) return ext4_force_commit(inode->i_sb); - if (!journal) - ret = sync_mapping_buffers(inode->i_mapping); - - if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) - goto out; - - /* - * The VFS has written the file data. If the inode is unaltered - * then we need not start a commit. - */ - if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) { - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = 0, /* sys_fsync did this */ - }; - err = sync_inode(inode, &wbc); - if (ret == 0) - ret = err; - } -out: - if (journal && (journal->j_flags & JBD2_BARRIER)) + commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; + if (jbd2_log_start_commit(journal, commit_tid)) + jbd2_log_wait_commit(journal, commit_tid); + else if (journal->j_flags & JBD2_BARRIER) blkdev_issue_flush(inode->i_sb->s_bdev, NULL); return ret; } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 64086fb96e47..1dae9a4dbb03 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1025,6 +1025,8 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, goto cleanup; set_buffer_new(bh_result); + + ext4_update_inode_fsync_trans(handle, inode, 1); got_it: map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); if (count > blocks_to_boundary) @@ -4794,6 +4796,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) struct ext4_inode *raw_inode; struct ext4_inode_info *ei; struct inode *inode; + journal_t *journal = EXT4_SB(sb)->s_journal; long ret; int block; @@ -4858,6 +4861,31 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ei->i_data[block] = raw_inode->i_block[block]; INIT_LIST_HEAD(&ei->i_orphan); + /* + * Set transaction id's of transactions that have to be committed + * to finish f[data]sync. We set them to currently running transaction + * as we cannot be sure that the inode or some of its metadata isn't + * part of the transaction - the inode could have been reclaimed and + * now it is reread from disk. + */ + if (journal) { + transaction_t *transaction; + tid_t tid; + + spin_lock(&journal->j_state_lock); + if (journal->j_running_transaction) + transaction = journal->j_running_transaction; + else + transaction = journal->j_committing_transaction; + if (transaction) + tid = transaction->t_tid; + else + tid = journal->j_commit_sequence; + spin_unlock(&journal->j_state_lock); + ei->i_sync_tid = tid; + ei->i_datasync_tid = tid; + } + if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > @@ -5112,6 +5140,7 @@ static int ext4_do_update_inode(handle_t *handle, err = rc; ei->i_state &= ~EXT4_STATE_NEW; + ext4_update_inode_fsync_trans(handle, inode, 0); out_brelse: brelse(bh); ext4_std_error(inode->i_sb, err); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 803fb252c111..9ae521749b90 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -706,6 +706,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) spin_lock_init(&(ei->i_block_reservation_lock)); INIT_LIST_HEAD(&ei->i_aio_dio_complete_list); ei->cur_aio_dio = NULL; + ei->i_sync_tid = 0; + ei->i_datasync_tid = 0; return &ei->vfs_inode; } diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index c974077915fa..82c295d2a7c5 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -78,6 +78,7 @@ EXPORT_SYMBOL(jbd2_journal_errno); EXPORT_SYMBOL(jbd2_journal_ack_err); EXPORT_SYMBOL(jbd2_journal_clear_err); EXPORT_SYMBOL(jbd2_log_wait_commit); +EXPORT_SYMBOL(jbd2_log_start_commit); EXPORT_SYMBOL(jbd2_journal_start_commit); EXPORT_SYMBOL(jbd2_journal_force_commit_nested); EXPORT_SYMBOL(jbd2_journal_wipe); From 0fd023ecf102ab0bd070d5affd73b18e6704ff0f Mon Sep 17 00:00:00 2001 From: Akira Fujita Date: Sun, 6 Dec 2009 23:38:31 -0500 Subject: [PATCH 033/670] ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT (cherry picked from commit 4a58579b9e4e2a35d57e6c9c8483e52f6f1b7fd6) This patch fixes three problems in the handling of the EXT4_IOC_MOVE_EXT ioctl: 1. In current EXT4_IOC_MOVE_EXT, there are read access mode checks for original and donor files, but they allow the illegal write access to donor file, since donor file is overwritten by original file data. To fix this problem, change access mode checks of original (r->r/w) and donor (r->w) files. 2. Disallow the use of donor files that have a setuid or setgid bits. 3. Call mnt_want_write() and mnt_drop_write() before and after ext4_move_extents() calling to get write access to a mount. Signed-off-by: Akira Fujita Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ioctl.c | 30 ++++++++++++++++++------------ fs/ext4/move_extent.c | 7 +++++++ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 31e5ee0c858f..b63d193126db 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -221,32 +221,38 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct file *donor_filp; int err; + if (!(filp->f_mode & FMODE_READ) || + !(filp->f_mode & FMODE_WRITE)) + return -EBADF; + if (copy_from_user(&me, (struct move_extent __user *)arg, sizeof(me))) return -EFAULT; + me.moved_len = 0; donor_filp = fget(me.donor_fd); if (!donor_filp) return -EBADF; - if (!capable(CAP_DAC_OVERRIDE)) { - if ((current->real_cred->fsuid != inode->i_uid) || - !(inode->i_mode & S_IRUSR) || - !(donor_filp->f_dentry->d_inode->i_mode & - S_IRUSR)) { - fput(donor_filp); - return -EACCES; - } + if (!(donor_filp->f_mode & FMODE_WRITE)) { + err = -EBADF; + goto mext_out; } - me.moved_len = 0; + err = mnt_want_write(filp->f_path.mnt); + if (err) + goto mext_out; + err = ext4_move_extents(filp, donor_filp, me.orig_start, me.donor_start, me.len, &me.moved_len); - fput(donor_filp); + mnt_drop_write(filp->f_path.mnt); + if (me.moved_len > 0) + file_remove_suid(donor_filp); if (copy_to_user((struct move_extent *)arg, &me, sizeof(me))) - return -EFAULT; - + err = -EFAULT; +mext_out: + fput(donor_filp); return err; } diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index bcc41e63965c..f5b03a132a2a 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -957,6 +957,13 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } + if (donor_inode->i_mode & (S_ISUID|S_ISGID)) { + ext4_debug("ext4 move extent: suid or sgid is set" + " to donor file [ino:orig %lu, donor %lu]\n", + orig_inode->i_ino, donor_inode->i_ino); + return -EINVAL; + } + /* Ext4 move extent does not support swapfile */ if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) { ext4_debug("ext4 move extent: The argument files should " From abb247066f9769e90df87ab65e5c2bb4dbdb529c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 9 Dec 2009 21:30:02 -0500 Subject: [PATCH 034/670] ext4: Fix potential fiemap deadlock (mmap_sem vs. i_data_sem) (cherry picked from commit fab3a549e204172236779f502eccb4f9bf0dc87d) Fix the following potential circular locking dependency between mm->mmap_sem and ei->i_data_sem: ======================================================= [ INFO: possible circular locking dependency detected ] 2.6.32-04115-gec044c5 #37 ------------------------------------------------------- ureadahead/1855 is trying to acquire lock: (&mm->mmap_sem){++++++}, at: [] might_fault+0x5c/0xac but task is already holding lock: (&ei->i_data_sem){++++..}, at: [] ext4_fiemap+0x11b/0x159 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&ei->i_data_sem){++++..}: [] __lock_acquire+0xb67/0xd0f [] lock_acquire+0xdc/0x102 [] down_read+0x51/0x84 [] ext4_get_blocks+0x50/0x2a5 [] ext4_get_block+0xab/0xef [] do_mpage_readpage+0x198/0x48d [] mpage_readpages+0xd0/0x114 [] ext4_readpages+0x1d/0x1f [] __do_page_cache_readahead+0x12f/0x1bc [] ra_submit+0x21/0x25 [] filemap_fault+0x19f/0x32c [] __do_fault+0x55/0x3a2 [] handle_mm_fault+0x327/0x734 [] do_page_fault+0x292/0x2aa [] page_fault+0x25/0x30 [] clear_user+0x38/0x3c [] padzero+0x20/0x31 [] load_elf_binary+0x8bc/0x17ed [] search_binary_handler+0xc2/0x259 [] load_script+0x1b8/0x1cc [] search_binary_handler+0xc2/0x259 [] do_execve+0x1ce/0x2cf [] sys_execve+0x43/0x5a [] stub_execve+0x6a/0xc0 -> #0 (&mm->mmap_sem){++++++}: [] __lock_acquire+0xa11/0xd0f [] lock_acquire+0xdc/0x102 [] might_fault+0x89/0xac [] fiemap_fill_next_extent+0x95/0xda [] ext4_ext_fiemap_cb+0x138/0x157 [] ext4_ext_walk_space+0x178/0x1f1 [] ext4_fiemap+0x13c/0x159 [] do_vfs_ioctl+0x348/0x4d6 [] sys_ioctl+0x56/0x79 [] system_call_fastpath+0x16/0x1b other info that might help us debug this: 1 lock held by ureadahead/1855: #0: (&ei->i_data_sem){++++..}, at: [] ext4_fiemap+0x11b/0x159 stack backtrace: Pid: 1855, comm: ureadahead Not tainted 2.6.32-04115-gec044c5 #37 Call Trace: [] print_circular_bug+0xa8/0xb7 [] __lock_acquire+0xa11/0xd0f [] ? sched_clock+0x9/0xd [] lock_acquire+0xdc/0x102 [] ? might_fault+0x5c/0xac [] might_fault+0x89/0xac [] ? might_fault+0x5c/0xac [] ? __kmalloc+0x13b/0x18c [] fiemap_fill_next_extent+0x95/0xda [] ext4_ext_fiemap_cb+0x138/0x157 [] ? ext4_ext_fiemap_cb+0x0/0x157 [] ext4_ext_walk_space+0x178/0x1f1 [] ext4_fiemap+0x13c/0x159 [] ? might_fault+0x5c/0xac [] do_vfs_ioctl+0x348/0x4d6 [] ? __up_read+0x8d/0x95 [] ? retint_swapgs+0x13/0x1b [] sys_ioctl+0x56/0x79 [] system_call_fastpath+0x16/0x1b Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/extents.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 43c04ff653c6..8b8bae4c0cf4 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1761,7 +1761,9 @@ int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block, while (block < last && block != EXT_MAX_BLOCK) { num = last - block; /* find extent for this block */ + down_read(&EXT4_I(inode)->i_data_sem); path = ext4_ext_find_extent(inode, block, path); + up_read(&EXT4_I(inode)->i_data_sem); if (IS_ERR(path)) { err = PTR_ERR(path); path = NULL; @@ -3730,10 +3732,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, * Walk the extent tree gathering extent information. * ext4_ext_fiemap_cb will push extents back to user. */ - down_read(&EXT4_I(inode)->i_data_sem); error = ext4_ext_walk_space(inode, start_blk, len_blks, ext4_ext_fiemap_cb, fieinfo); - up_read(&EXT4_I(inode)->i_data_sem); } return error; From acb34e4d6b5d0601530e1dd10121a1ae209e3a44 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 14 Dec 2009 09:47:25 -0800 Subject: [PATCH 035/670] Linux 2.6.32.1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f5cdb72ba2ce..d0d7e9c7abec 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = +EXTRAVERSION = .1 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* From 5a2ec9e5ec191d610d56433f3801b7fb9e250872 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 7 Dec 2009 16:47:43 -0500 Subject: [PATCH 036/670] USB: usb-storage: fix bug in fill_inquiry commit f3f6faa9edf67c1018270793e0547b0f81abb47e upstream. This patch (as1312) fixes a minor bug in usb-storage. The fill_inquiry() routine neglects to pre-load the inquiry data buffer with spaces. As a result, if the vendor name is shorter than 8 characters or the product name is shorter than 16, the remainder will be filled with garbage. The patch also removes some unnecessary calls to strlen(). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 8060b85fe1a3..11876c3b9000 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -228,6 +228,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data, if (data_len<36) // You lose. return; + memset(data+8, ' ', 28); if(data[0]&0x20) { /* USB device currently not connected. Return peripheral qualifier 001b ("...however, the physical device is not currently connected @@ -237,15 +238,15 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data, device, it may return zeros or ASCII spaces (20h) in those fields until the data is available from the device."). */ - memset(data+8,0,28); } else { u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice); - memcpy(data+8, us->unusual_dev->vendorName, - strlen(us->unusual_dev->vendorName) > 8 ? 8 : - strlen(us->unusual_dev->vendorName)); - memcpy(data+16, us->unusual_dev->productName, - strlen(us->unusual_dev->productName) > 16 ? 16 : - strlen(us->unusual_dev->productName)); + int n; + + n = strlen(us->unusual_dev->vendorName); + memcpy(data+8, us->unusual_dev->vendorName, min(8, n)); + n = strlen(us->unusual_dev->productName); + memcpy(data+16, us->unusual_dev->productName, min(16, n)); + data[32] = 0x30 + ((bcdDevice>>12) & 0x0F); data[33] = 0x30 + ((bcdDevice>>8) & 0x0F); data[34] = 0x30 + ((bcdDevice>>4) & 0x0F); From be58b8712a2309b71d1c99ae648bca2d34c55781 Mon Sep 17 00:00:00 2001 From: "zhao.ming9@zte.com.cn" Date: Mon, 7 Dec 2009 11:36:34 +0800 Subject: [PATCH 037/670] USB: option: add pid for ZTE commit 8d87cacda7c8db5c131bfcaaa1d90bfe918c2ebc upstream. This patch adds ZTE modem devices. Signed-off-by: Ming Zhao Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 0577e4b61114..3ea517e0fb4f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -580,12 +580,48 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0106, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0108, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, From e39b7b492b646e803941117e5d879e49f40bb92f Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Fri, 11 Dec 2009 14:23:58 -0500 Subject: [PATCH 038/670] firewire: ohci: handle receive packets with a data length of zero commit 8c0c0cc2d9f4c523fde04bdfe41e4380dec8ee54 upstream. Queueing to receive an ISO packet with a payload length of zero silently does nothing in dualbuffer mode, and crashes the kernel in packet-per-buffer mode. Return an error in dualbuffer mode, because the DMA controller won't let us do what we want, and work correctly in packet-per-buffer mode. Signed-off-by: Jay Fenlason Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman --- drivers/firewire/ohci.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 94260aa76aa3..1e504de739e5 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2209,6 +2209,13 @@ static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, page = payload >> PAGE_SHIFT; offset = payload & ~PAGE_MASK; rest = p->payload_length; + /* + * The controllers I've tested have not worked correctly when + * second_req_count is zero. Rather than do something we know won't + * work, return an error + */ + if (rest == 0) + return -EINVAL; /* FIXME: make packet-per-buffer/dual-buffer a context option */ while (rest > 0) { @@ -2262,7 +2269,7 @@ static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, unsigned long payload) { struct iso_context *ctx = container_of(base, struct iso_context, base); - struct descriptor *d = NULL, *pd = NULL; + struct descriptor *d, *pd; struct fw_iso_packet *p = packet; dma_addr_t d_bus, page_bus; u32 z, header_z, rest; @@ -2300,8 +2307,9 @@ static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d))); rest = payload_per_buffer; + pd = d; for (j = 1; j < z; j++) { - pd = d + j; + pd++; pd->control = cpu_to_le16(DESCRIPTOR_STATUS | DESCRIPTOR_INPUT_MORE); From 1aab3863fee66343b420cb1e5d268c3ee8da27a6 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 2 Nov 2009 13:52:27 -0800 Subject: [PATCH 039/670] rcu: Prepare for synchronization fixes: clean up for non-NO_HZ handling of ->completed counter commit 281d150c5f8892f158747594ab49ce2823fd8b8c upstream. Impose a clear locking design on non-NO_HZ handling of the ->completed counter. This increases the distance between the RCU and the CPU-hotplug mechanisms. Signed-off-by: Paul E. McKenney Cc: laijs@cn.fujitsu.com Cc: dipankar@in.ibm.com Cc: mathieu.desnoyers@polymtl.ca Cc: josh@joshtriplett.org Cc: dvhltc@us.ibm.com Cc: niv@us.ibm.com Cc: peterz@infradead.org Cc: rostedt@goodmis.org Cc: Valdis.Kletnieks@vt.edu Cc: dhowells@redhat.com LKML-Reference: <12571987491353-git-send-email-> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/rcutree.c | 67 ++++++++++++++++++++++-------------------------- kernel/rcutree.h | 8 +++--- 2 files changed, 34 insertions(+), 41 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index f3077c0ab181..bd3ee488947a 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -176,8 +176,28 @@ static struct rcu_node *rcu_get_root(struct rcu_state *rsp) return &rsp->node[0]; } +/* + * Record the specified "completed" value, which is later used to validate + * dynticks counter manipulations and CPU-offline checks. Specify + * "rsp->completed - 1" to unconditionally invalidate any future dynticks + * manipulations and CPU-offline checks. Such invalidation is useful at + * the beginning of a grace period. + */ +static void dyntick_record_completed(struct rcu_state *rsp, long comp) +{ + rsp->dynticks_completed = comp; +} + #ifdef CONFIG_SMP +/* + * Recall the previously recorded value of the completion for dynticks. + */ +static long dyntick_recall_completed(struct rcu_state *rsp) +{ + return rsp->dynticks_completed; +} + /* * If the specified CPU is offline, tell the caller that it is in * a quiescent state. Otherwise, whack it with a reschedule IPI. @@ -335,27 +355,8 @@ void rcu_irq_exit(void) set_need_resched(); } -/* - * Record the specified "completed" value, which is later used to validate - * dynticks counter manipulations. Specify "rsp->completed - 1" to - * unconditionally invalidate any future dynticks manipulations (which is - * useful at the beginning of a grace period). - */ -static void dyntick_record_completed(struct rcu_state *rsp, long comp) -{ - rsp->dynticks_completed = comp; -} - #ifdef CONFIG_SMP -/* - * Recall the previously recorded value of the completion for dynticks. - */ -static long dyntick_recall_completed(struct rcu_state *rsp) -{ - return rsp->dynticks_completed; -} - /* * Snapshot the specified CPU's dynticks counter so that we can later * credit them with an implicit quiescent state. Return 1 if this CPU @@ -419,24 +420,8 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) #else /* #ifdef CONFIG_NO_HZ */ -static void dyntick_record_completed(struct rcu_state *rsp, long comp) -{ -} - #ifdef CONFIG_SMP -/* - * If there are no dynticks, then the only way that a CPU can passively - * be in a quiescent state is to be offline. Unlike dynticks idle, which - * is a point in time during the prior (already finished) grace period, - * an offline CPU is always in a quiescent state, and thus can be - * unconditionally applied. So just return the current value of completed. - */ -static long dyntick_recall_completed(struct rcu_state *rsp) -{ - return rsp->completed; -} - static int dyntick_save_progress_counter(struct rcu_data *rdp) { return 0; @@ -1144,6 +1129,7 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) long lastcomp; struct rcu_node *rnp = rcu_get_root(rsp); u8 signaled; + u8 forcenow; if (!rcu_gp_in_progress(rsp)) return; /* No grace period in progress, nothing to force. */ @@ -1180,16 +1166,23 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) if (rcu_process_dyntick(rsp, lastcomp, dyntick_save_progress_counter)) goto unlock_ret; + /* fall into next case. */ + + case RCU_SAVE_COMPLETED: /* Update state, record completion counter. */ + forcenow = 0; spin_lock(&rnp->lock); if (lastcomp == rsp->completed && - rsp->signaled == RCU_SAVE_DYNTICK) { + rsp->signaled == signaled) { rsp->signaled = RCU_FORCE_QS; dyntick_record_completed(rsp, lastcomp); + forcenow = signaled == RCU_SAVE_COMPLETED; } spin_unlock(&rnp->lock); - break; + if (!forcenow) + break; + /* fall into next case. */ case RCU_FORCE_QS: diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 1899023b0962..8a4c1650ad8d 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -204,11 +204,12 @@ struct rcu_data { #define RCU_GP_IDLE 0 /* No grace period in progress. */ #define RCU_GP_INIT 1 /* Grace period being initialized. */ #define RCU_SAVE_DYNTICK 2 /* Need to scan dyntick state. */ -#define RCU_FORCE_QS 3 /* Need to force quiescent state. */ +#define RCU_SAVE_COMPLETED 3 /* Need to save rsp->completed. */ +#define RCU_FORCE_QS 4 /* Need to force quiescent state. */ #ifdef CONFIG_NO_HZ #define RCU_SIGNAL_INIT RCU_SAVE_DYNTICK #else /* #ifdef CONFIG_NO_HZ */ -#define RCU_SIGNAL_INIT RCU_FORCE_QS +#define RCU_SIGNAL_INIT RCU_SAVE_COMPLETED #endif /* #else #ifdef CONFIG_NO_HZ */ #define RCU_JIFFIES_TILL_FORCE_QS 3 /* for rsp->jiffies_force_qs */ @@ -274,9 +275,8 @@ struct rcu_state { unsigned long jiffies_stall; /* Time at which to check */ /* for CPU stalls. */ #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ -#ifdef CONFIG_NO_HZ long dynticks_completed; /* Value of completed @ snap. */ -#endif /* #ifdef CONFIG_NO_HZ */ + /* Protected by fqslock. */ }; #ifdef RCU_TREE_NONCORE From 1a0d7df3352d775ae3e034b1f2658ea493055a30 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 2 Nov 2009 13:52:28 -0800 Subject: [PATCH 040/670] rcu: Fix synchronization for rcu_process_gp_end() uses of ->completed counter commit d09b62dfa336447c52a5ec9bb88adbc479b0f3b8 upstream. Impose a clear locking design on the rcu_process_gp_end() function's use of the ->completed counter. This is done by creating a ->completed field in the rcu_node structure, which can safely be accessed under the protection of that structure's lock. Performance and scalability are maintained by using a form of double-checked locking, so that rcu_process_gp_end() only acquires the leaf rcu_node structure's ->lock if a grace period has recently ended. This fix reduces rcutorture failure rate by at least two orders of magnitude under heavy stress with force_quiescent_state() being invoked artificially often. Without this fix, unsynchronized access to the ->completed field can cause rcu_process_gp_end() to advance callbacks whose grace period has not yet expired. (Bad idea!) Signed-off-by: Paul E. McKenney Cc: laijs@cn.fujitsu.com Cc: dipankar@in.ibm.com Cc: mathieu.desnoyers@polymtl.ca Cc: josh@joshtriplett.org Cc: dvhltc@us.ibm.com Cc: niv@us.ibm.com Cc: peterz@infradead.org Cc: rostedt@goodmis.org Cc: Valdis.Kletnieks@vt.edu Cc: dhowells@redhat.com LKML-Reference: <12571987494069-git-send-email-> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/rcutree.c | 128 +++++++++++++++++++++++++++++------------------ kernel/rcutree.h | 3 ++ 2 files changed, 83 insertions(+), 48 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index bd3ee488947a..b4780892de92 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -567,6 +567,76 @@ check_for_new_grace_period(struct rcu_state *rsp, struct rcu_data *rdp) return ret; } +/* + * Advance this CPU's callbacks, but only if the current grace period + * has ended. This may be called only from the CPU to whom the rdp + * belongs. In addition, the corresponding leaf rcu_node structure's + * ->lock must be held by the caller, with irqs disabled. + */ +static void +__rcu_process_gp_end(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp) +{ + /* Did another grace period end? */ + if (rdp->completed != rnp->completed) { + + /* Advance callbacks. No harm if list empty. */ + rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[RCU_WAIT_TAIL]; + rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_READY_TAIL]; + rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + + /* Remember that we saw this grace-period completion. */ + rdp->completed = rnp->completed; + } +} + +/* + * Advance this CPU's callbacks, but only if the current grace period + * has ended. This may be called only from the CPU to whom the rdp + * belongs. + */ +static void +rcu_process_gp_end(struct rcu_state *rsp, struct rcu_data *rdp) +{ + unsigned long flags; + struct rcu_node *rnp; + + local_irq_save(flags); + rnp = rdp->mynode; + if (rdp->completed == ACCESS_ONCE(rnp->completed) || /* outside lock. */ + !spin_trylock(&rnp->lock)) { /* irqs already off, retry later. */ + local_irq_restore(flags); + return; + } + __rcu_process_gp_end(rsp, rnp, rdp); + spin_unlock_irqrestore(&rnp->lock, flags); +} + +/* + * Do per-CPU grace-period initialization for running CPU. The caller + * must hold the lock of the leaf rcu_node structure corresponding to + * this CPU. + */ +static void +rcu_start_gp_per_cpu(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp) +{ + /* Prior grace period ended, so advance callbacks for current CPU. */ + __rcu_process_gp_end(rsp, rnp, rdp); + + /* + * Because this CPU just now started the new grace period, we know + * that all of its callbacks will be covered by this upcoming grace + * period, even the ones that were registered arbitrarily recently. + * Therefore, advance all outstanding callbacks to RCU_WAIT_TAIL. + * + * Other CPUs cannot be sure exactly when the grace period started. + * Therefore, their recently registered callbacks must pass through + * an additional RCU_NEXT_READY stage, so that they will be handled + * by the next RCU grace period. + */ + rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; +} + /* * Start a new RCU grace period if warranted, re-initializing the hierarchy * in preparation for detecting the next grace period. The caller must hold @@ -594,26 +664,14 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) dyntick_record_completed(rsp, rsp->completed - 1); note_new_gpnum(rsp, rdp); - /* - * Because this CPU just now started the new grace period, we know - * that all of its callbacks will be covered by this upcoming grace - * period, even the ones that were registered arbitrarily recently. - * Therefore, advance all outstanding callbacks to RCU_WAIT_TAIL. - * - * Other CPUs cannot be sure exactly when the grace period started. - * Therefore, their recently registered callbacks must pass through - * an additional RCU_NEXT_READY stage, so that they will be handled - * by the next RCU grace period. - */ - rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; - rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; - /* Special-case the common single-level case. */ if (NUM_RCU_NODES == 1) { rcu_preempt_check_blocked_tasks(rnp); rnp->qsmask = rnp->qsmaskinit; rnp->gpnum = rsp->gpnum; + rnp->completed = rsp->completed; rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state OK. */ + rcu_start_gp_per_cpu(rsp, rnp, rdp); spin_unlock_irqrestore(&rnp->lock, flags); return; } @@ -646,6 +704,9 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) rcu_preempt_check_blocked_tasks(rnp); rnp->qsmask = rnp->qsmaskinit; rnp->gpnum = rsp->gpnum; + rnp->completed = rsp->completed; + if (rnp == rdp->mynode) + rcu_start_gp_per_cpu(rsp, rnp, rdp); spin_unlock(&rnp->lock); /* irqs remain disabled. */ } @@ -656,34 +717,6 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) spin_unlock_irqrestore(&rsp->onofflock, flags); } -/* - * Advance this CPU's callbacks, but only if the current grace period - * has ended. This may be called only from the CPU to whom the rdp - * belongs. - */ -static void -rcu_process_gp_end(struct rcu_state *rsp, struct rcu_data *rdp) -{ - long completed_snap; - unsigned long flags; - - local_irq_save(flags); - completed_snap = ACCESS_ONCE(rsp->completed); /* outside of lock. */ - - /* Did another grace period end? */ - if (rdp->completed != completed_snap) { - - /* Advance callbacks. No harm if list empty. */ - rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[RCU_WAIT_TAIL]; - rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_READY_TAIL]; - rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; - - /* Remember that we saw this grace-period completion. */ - rdp->completed = completed_snap; - } - local_irq_restore(flags); -} - /* * Clean up after the prior grace period and let rcu_start_gp() start up * the next grace period if one is needed. Note that the caller must @@ -695,7 +728,6 @@ static void cpu_quiet_msk_finish(struct rcu_state *rsp, unsigned long flags) WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); rsp->completed = rsp->gpnum; rsp->signaled = RCU_GP_IDLE; - rcu_process_gp_end(rsp, rsp->rda[smp_processor_id()]); rcu_start_gp(rsp, flags); /* releases root node's rnp->lock. */ } @@ -1537,21 +1569,16 @@ static void __cpuinit rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable) { unsigned long flags; - long lastcomp; unsigned long mask; struct rcu_data *rdp = rsp->rda[cpu]; struct rcu_node *rnp = rcu_get_root(rsp); /* Set up local state, ensuring consistent view of global state. */ spin_lock_irqsave(&rnp->lock, flags); - lastcomp = rsp->completed; - rdp->completed = lastcomp; - rdp->gpnum = lastcomp; rdp->passed_quiesc = 0; /* We could be racing with new GP, */ rdp->qs_pending = 1; /* so set up to respond to current GP. */ rdp->beenonline = 1; /* We have now been online. */ rdp->preemptable = preemptable; - rdp->passed_quiesc_completed = lastcomp - 1; rdp->qlen_last_fqs_check = 0; rdp->n_force_qs_snap = rsp->n_force_qs; rdp->blimit = blimit; @@ -1573,6 +1600,11 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable) spin_lock(&rnp->lock); /* irqs already disabled. */ rnp->qsmaskinit |= mask; mask = rnp->grpmask; + if (rnp == rdp->mynode) { + rdp->gpnum = rnp->completed; /* if GP in progress... */ + rdp->completed = rnp->completed; + rdp->passed_quiesc_completed = rnp->completed - 1; + } spin_unlock(&rnp->lock); /* irqs already disabled. */ rnp = rnp->parent; } while (rnp != NULL && !(rnp->qsmaskinit & mask)); diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 8a4c1650ad8d..c1891c3cae63 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -84,6 +84,9 @@ struct rcu_node { long gpnum; /* Current grace period for this node. */ /* This will either be equal to or one */ /* behind the root rcu_node's gpnum. */ + long completed; /* Last grace period completed for this node. */ + /* This will either be equal to or one */ + /* behind the root rcu_node's gpnum. */ unsigned long qsmask; /* CPUs or groups that need to switch in */ /* order for current grace period to proceed.*/ /* In leaf rcu_node, each bit corresponds to */ From c541f7c75c5d41c9a3f2c7599ee425547cc49a42 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 2 Nov 2009 13:52:29 -0800 Subject: [PATCH 041/670] rcu: Fix note_new_gpnum() uses of ->gpnum commit 9160306e6f5b68bb64630c9031c517ca1cf463db upstream. Impose a clear locking design on the note_new_gpnum() function's use of the ->gpnum counter. This is done by updating rdp->gpnum only from the corresponding leaf rcu_node structure's rnp->gpnum field, and even then only under the protection of that same rcu_node structure's ->lock field. Performance and scalability are maintained using a form of double-checked locking, and excessive spinning is avoided by use of the spin_trylock() function. The use of spin_trylock() is safe due to the fact that CPUs who fail to acquire this lock will try again later. The hierarchical nature of the rcu_node data structure limits contention (which could be limited further if need be using the RCU_FANOUT kernel parameter). Without this patch, obscure but quite possible races could result in a quiescent state that occurred during one grace period to be accounted to the following grace period, causing this following grace period to end prematurely. Not good! Signed-off-by: Paul E. McKenney Cc: laijs@cn.fujitsu.com Cc: dipankar@in.ibm.com Cc: mathieu.desnoyers@polymtl.ca Cc: josh@joshtriplett.org Cc: dvhltc@us.ibm.com Cc: niv@us.ibm.com Cc: peterz@infradead.org Cc: rostedt@goodmis.org Cc: Valdis.Kletnieks@vt.edu Cc: dhowells@redhat.com LKML-Reference: <12571987492350-git-send-email-> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/rcutree.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index b4780892de92..683c4f3b87e0 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -538,13 +538,33 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) /* * Update CPU-local rcu_data state to record the newly noticed grace period. * This is used both when we started the grace period and when we notice - * that someone else started the grace period. + * that someone else started the grace period. The caller must hold the + * ->lock of the leaf rcu_node structure corresponding to the current CPU, + * and must have irqs disabled. */ +static void __note_new_gpnum(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp) +{ + if (rdp->gpnum != rnp->gpnum) { + rdp->qs_pending = 1; + rdp->passed_quiesc = 0; + rdp->gpnum = rnp->gpnum; + } +} + static void note_new_gpnum(struct rcu_state *rsp, struct rcu_data *rdp) { - rdp->qs_pending = 1; - rdp->passed_quiesc = 0; - rdp->gpnum = rsp->gpnum; + unsigned long flags; + struct rcu_node *rnp; + + local_irq_save(flags); + rnp = rdp->mynode; + if (rdp->gpnum == ACCESS_ONCE(rnp->gpnum) || /* outside lock. */ + !spin_trylock(&rnp->lock)) { /* irqs already off, retry later. */ + local_irq_restore(flags); + return; + } + __note_new_gpnum(rsp, rnp, rdp); + spin_unlock_irqrestore(&rnp->lock, flags); } /* @@ -635,6 +655,9 @@ rcu_start_gp_per_cpu(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_dat */ rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + + /* Set state so that this CPU will detect the next quiescent state. */ + __note_new_gpnum(rsp, rnp, rdp); } /* @@ -662,7 +685,6 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; record_gp_stall_check_time(rsp); dyntick_record_completed(rsp, rsp->completed - 1); - note_new_gpnum(rsp, rdp); /* Special-case the common single-level case. */ if (NUM_RCU_NODES == 1) { From b87444a84534cba3ba85536cabfcaf364c0fa940 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 10 Nov 2009 13:37:19 -0800 Subject: [PATCH 042/670] rcu: Remove inline from forward-referenced functions commit dbe01350fa8ce0c11948ab7d6be71a4d901be151 upstream. Some variants of gcc are reputed to dislike forward references to functions declared "inline". Remove the "inline" keyword from such functions. Signed-off-by: Paul E. McKenney Cc: laijs@cn.fujitsu.com Cc: dipankar@in.ibm.com Cc: mathieu.desnoyers@polymtl.ca Cc: josh@joshtriplett.org Cc: dvhltc@us.ibm.com Cc: niv@us.ibm.com Cc: peterz@infradead.org Cc: rostedt@goodmis.org Cc: Valdis.Kletnieks@vt.edu Cc: dhowells@redhat.com Cc: Benjamin Gilbert LKML-Reference: <12578890422402-git-send-email-> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/rcutree.h | 2 +- kernel/rcutree_plugin.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/rcutree.h b/kernel/rcutree.h index c1891c3cae63..ddb79ece05eb 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -301,7 +301,7 @@ DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data); #else /* #ifdef RCU_TREE_NONCORE */ /* Forward declarations for rcutree_plugin.h */ -static inline void rcu_bootup_announce(void); +static void rcu_bootup_announce(void); long rcu_batches_completed(void); static void rcu_preempt_note_context_switch(int cpu); static int rcu_preempted_readers(struct rcu_node *rnp); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index ef2a58c2b9d5..c03edf766357 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -33,7 +33,7 @@ DEFINE_PER_CPU(struct rcu_data, rcu_preempt_data); /* * Tell them what RCU they are running. */ -static inline void rcu_bootup_announce(void) +static void rcu_bootup_announce(void) { printk(KERN_INFO "Experimental preemptable hierarchical RCU implementation.\n"); @@ -481,7 +481,7 @@ void exit_rcu(void) /* * Tell them what RCU they are running. */ -static inline void rcu_bootup_announce(void) +static void rcu_bootup_announce(void) { printk(KERN_INFO "Hierarchical RCU implementation.\n"); } From c64d2a3d2c5f192d859374e943968439afb0f995 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 13 Nov 2009 21:47:33 -0800 Subject: [PATCH 043/670] perf_event: Fix invalid type in ioctl definition commit 4c49b12853fbb5eff4849b7b6a1e895776f027a1 upstream. u64 is invalid in userspace headers, including ioctl definitions; use __u64 instead Signed-off-by: Arjan van de Ven LKML-Reference: <20091113214733.7cd76be9@infradead.org> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/linux/perf_event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 9e7012689a84..81c9689a6948 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -219,7 +219,7 @@ struct perf_event_attr { #define PERF_EVENT_IOC_DISABLE _IO ('$', 1) #define PERF_EVENT_IOC_REFRESH _IO ('$', 2) #define PERF_EVENT_IOC_RESET _IO ('$', 3) -#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, u64) +#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64) #define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) enum perf_event_ioc_flags { From b7b4aef82aeef0d9408951c8d1e7a2a6dd359921 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Tue, 1 Dec 2009 17:30:08 +0800 Subject: [PATCH 044/670] perf_event: Initialize data.period in perf_swevent_hrtimer() commit 59d069eb5ae9b033ed1c124c92e1532c4a958991 upstream. In current code in perf_swevent_hrtimer(), data.period is not initialized, The result is obvious wrong: # ./perf record -f -e cpu-clock make # ./perf report # Samples: 1740 # # Overhead Command ...... # ........ ........ .......................................... # 1025422183050275328.00% sh libc-2.9.90.so ... 1025422183050275328.00% perl libperl.so ... 1025422168240043264.00% perl [kernel] ... 1025422030011210752.00% perl [kernel] ... Signed-off-by: Xiao Guangrong Acked-by: Peter Zijlstra Cc: Frederic Weisbecker LKML-Reference: <4B14E220.2050107@cn.fujitsu.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/perf_event.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 7f29643c8985..d16999c30ad2 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -3949,6 +3949,7 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer) event->pmu->read(event); data.addr = 0; + data.period = event->hw.last_period; regs = get_irq_regs(); /* * In case we exclude kernel IPs or are somehow not in interrupt From 9f3bb2b1e8f891b008ab3d74d789444cab5ef695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 1 Dec 2009 15:05:01 -0500 Subject: [PATCH 045/670] perf: Don't free perf_mmap_data until work has been done MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ec70ccd806111ba3caf596def91a8580138b12db upstream. In the CONFIG_PERF_USE_VMALLOC case, perf_mmap_data_free() only schedules the cleanup of the perf_mmap_data struct. In that case we have to wait until the work has been done before we free data. Signed-off-by: Kristian Høgsberg Cc: David S. Miller Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Frederic Weisbecker LKML-Reference: <1259697901-1747-1-git-send-email-krh@bitplanet.net> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/perf_event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index d16999c30ad2..61c35f583b90 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -2174,6 +2174,7 @@ static void perf_mmap_data_free(struct perf_mmap_data *data) perf_mmap_free_page((unsigned long)data->user_page); for (i = 0; i < data->nr_pages; i++) perf_mmap_free_page((unsigned long)data->data_pages[i]); + kfree(data); } #else @@ -2214,6 +2215,7 @@ static void perf_mmap_data_free_work(struct work_struct *work) perf_mmap_unmark_page(base + (i * PAGE_SIZE)); vfree(base); + kfree(data); } static void perf_mmap_data_free(struct perf_mmap_data *data) @@ -2319,7 +2321,6 @@ static void perf_mmap_data_free_rcu(struct rcu_head *rcu_head) data = container_of(rcu_head, struct perf_mmap_data, rcu_head); perf_mmap_data_free(data); - kfree(data); } static void perf_mmap_data_release(struct perf_event *event) From 7f112f35f0da073a10d4d3bfdfcef2955555e4f7 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 3 Dec 2009 20:21:21 +0100 Subject: [PATCH 046/670] PM / Runtime: Fix lockdep warning in __pm_runtime_set_status() commit bab636b921017f0db6e0c2979438f50b898a9808 upstream. Lockdep complains about taking the parent lock in __pm_runtime_set_status(), so mark it as nested. Signed-off-by: Rafael J. Wysocki Reported-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 846d89e3d122..0a4b75f834c0 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -777,7 +777,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status) } if (parent) { - spin_lock(&parent->power.lock); + spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING); /* * It is invalid to put an active child under a parent that is From c2f1953231c6e99777633761c3bc0d2ca7ead20a Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Tue, 27 Oct 2009 15:35:38 +0100 Subject: [PATCH 047/670] sched: Check for an idle shared cache in select_task_rq_fair() commit a1f84a3ab8e002159498814eaa7e48c33752b04b upstream. When waking affine, check for an idle shared cache, and if found, wake to that CPU/sibling instead of the waker's CPU. This improves pgsql+oltp ramp up by roughly 8%. Possibly more for other loads, depending on overlap. The trade-off is a roughly 1% peak downturn if tasks are truly synchronous. Signed-off-by: Mike Galbraith Cc: Arjan van de Ven Cc: Peter Zijlstra LKML-Reference: <1256654138.17752.7.camel@marge.simson.net> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched_fair.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 37087a7fac22..32f06ed871b4 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1398,11 +1398,36 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag want_sd = 0; } - if (want_affine && (tmp->flags & SD_WAKE_AFFINE) && - cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) { + if (want_affine && (tmp->flags & SD_WAKE_AFFINE)) { + int candidate = -1, i; - affine_sd = tmp; - want_affine = 0; + if (cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) + candidate = cpu; + + /* + * Check for an idle shared cache. + */ + if (tmp->flags & SD_PREFER_SIBLING) { + if (candidate == cpu) { + if (!cpu_rq(prev_cpu)->cfs.nr_running) + candidate = prev_cpu; + } + + if (candidate == -1 || candidate == cpu) { + for_each_cpu(i, sched_domain_span(tmp)) { + if (!cpu_rq(i)->cfs.nr_running) { + candidate = i; + break; + } + } + } + } + + if (candidate >= 0) { + affine_sd = tmp; + want_affine = 0; + cpu = candidate; + } } if (!want_sd && !want_affine) From ece125459cc4ea8ec5344a2d12cee4b42602b822 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 5 Nov 2009 10:57:46 +0100 Subject: [PATCH 048/670] sched: Fix affinity logic in select_task_rq_fair() commit fd210738f6601d0fb462df9a2fe5a41896ff6a8f upstream. Ingo Molnar reported: [ 26.804000] BUG: using smp_processor_id() in preemptible [00000000] code: events/1/10 [ 26.808000] caller is vmstat_update+0x26/0x70 [ 26.812000] Pid: 10, comm: events/1 Not tainted 2.6.32-rc5 #6887 [ 26.816000] Call Trace: [ 26.820000] [] ? printk+0x28/0x3c [ 26.824000] [] debug_smp_processor_id+0xf0/0x110 [ 26.824000] mount used greatest stack depth: 1464 bytes left [ 26.828000] [] vmstat_update+0x26/0x70 [ 26.832000] [] worker_thread+0x188/0x310 [ 26.836000] [] ? worker_thread+0x127/0x310 [ 26.840000] [] ? autoremove_wake_function+0x0/0x60 [ 26.844000] [] ? worker_thread+0x0/0x310 [ 26.848000] [] kthread+0x7c/0x90 [ 26.852000] [] ? kthread+0x0/0x90 [ 26.856000] [] kernel_thread_helper+0x7/0x10 [ 26.860000] BUG: using smp_processor_id() in preemptible [00000000] code: events/1/10 [ 26.864000] caller is vmstat_update+0x3c/0x70 Because this commit: a1f84a3: sched: Check for an idle shared cache in select_task_rq_fair() broke ->cpus_allowed. Signed-off-by: Mike Galbraith Cc: Peter Zijlstra Cc: arjan@infradead.org LKML-Reference: <1257415066.12867.1.camel@marge.simson.net> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched_fair.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 32f06ed871b4..5488a5d3bc0e 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1415,6 +1415,8 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag if (candidate == -1 || candidate == cpu) { for_each_cpu(i, sched_domain_span(tmp)) { + if (!cpumask_test_cpu(i, &p->cpus_allowed)) + continue; if (!cpu_rq(i)->cfs.nr_running) { candidate = i; break; From 37ed2d7007a65874850f3e357c095806c3756330 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Wed, 4 Nov 2009 17:53:50 +0100 Subject: [PATCH 049/670] sched: Rate-limit newidle commit 1b9508f6831e10d53256825de8904caa22d1ca2c upstream. Rate limit newidle to migration_cost. It's a win for all stages of sysbench oltp tests. Signed-off-by: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 22 +++++++++++++++++++++- kernel/sched_debug.c | 4 ++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index 3c11ae0a948d..88acc79f5897 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -591,6 +591,8 @@ struct rq { u64 rt_avg; u64 age_stamp; + u64 idle_stamp; + u64 avg_idle; #endif /* calc_load related fields */ @@ -2384,6 +2386,17 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, if (rq != orig_rq) update_rq_clock(rq); + if (rq->idle_stamp) { + u64 delta = rq->clock - rq->idle_stamp; + u64 max = 2*sysctl_sched_migration_cost; + + if (delta > max) + rq->avg_idle = max; + else + update_avg(&rq->avg_idle, delta); + rq->idle_stamp = 0; + } + WARN_ON(p->state != TASK_WAKING); cpu = task_cpu(p); @@ -4429,6 +4442,11 @@ static void idle_balance(int this_cpu, struct rq *this_rq) int pulled_task = 0; unsigned long next_balance = jiffies + HZ; + this_rq->idle_stamp = this_rq->clock; + + if (this_rq->avg_idle < sysctl_sched_migration_cost) + return; + for_each_domain(this_cpu, sd) { unsigned long interval; @@ -4443,8 +4461,10 @@ static void idle_balance(int this_cpu, struct rq *this_rq) interval = msecs_to_jiffies(sd->balance_interval); if (time_after(next_balance, sd->last_balance + interval)) next_balance = sd->last_balance + interval; - if (pulled_task) + if (pulled_task) { + this_rq->idle_stamp = 0; break; + } } if (pulled_task || time_after(jiffies, this_rq->next_balance)) { /* diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index efb84409bc43..6988cf08f705 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -285,12 +285,16 @@ static void print_cpu(struct seq_file *m, int cpu) #ifdef CONFIG_SCHEDSTATS #define P(n) SEQ_printf(m, " .%-30s: %d\n", #n, rq->n); +#define P64(n) SEQ_printf(m, " .%-30s: %Ld\n", #n, rq->n); P(yld_count); P(sched_switch); P(sched_count); P(sched_goidle); +#ifdef CONFIG_SMP + P64(avg_idle); +#endif P(ttwu_count); P(ttwu_local); From 35c1ee3e78766d5666f418af638def9c67e63ecb Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Tue, 10 Nov 2009 03:50:02 +0100 Subject: [PATCH 050/670] sched: Fix and clean up rate-limit newidle code commit eae0c9dfb534cb3449888b9601228efa6480fdb5 upstream. Commit 1b9508f, "Rate-limit newidle" has been confirmed to fix the netperf UDP loopback regression reported by Alex Shi. This is a cleanup and a fix: - moved to a more out of the way spot - fix to ensure that balancing doesn't try to balance runqueues which haven't gone online yet, which can mess up CPU enumeration during boot. Reported-by: Alex Shi Reported-by: Zhang, Yanmin Signed-off-by: Mike Galbraith Acked-by: Peter Zijlstra LKML-Reference: <1257821402.5648.17.camel@marge.simson.net> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 88acc79f5897..d079a9f64a8e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2386,17 +2386,6 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, if (rq != orig_rq) update_rq_clock(rq); - if (rq->idle_stamp) { - u64 delta = rq->clock - rq->idle_stamp; - u64 max = 2*sysctl_sched_migration_cost; - - if (delta > max) - rq->avg_idle = max; - else - update_avg(&rq->avg_idle, delta); - rq->idle_stamp = 0; - } - WARN_ON(p->state != TASK_WAKING); cpu = task_cpu(p); @@ -2453,6 +2442,17 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, #ifdef CONFIG_SMP if (p->sched_class->task_wake_up) p->sched_class->task_wake_up(rq, p); + + if (unlikely(rq->idle_stamp)) { + u64 delta = rq->clock - rq->idle_stamp; + u64 max = 2*sysctl_sched_migration_cost; + + if (delta > max) + rq->avg_idle = max; + else + update_avg(&rq->avg_idle, delta); + rq->idle_stamp = 0; + } #endif out: task_rq_unlock(rq, &flags); @@ -4139,7 +4139,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, unsigned long flags; struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask); - cpumask_setall(cpus); + cpumask_copy(cpus, cpu_online_mask); /* * When power savings policy is enabled for the parent domain, idle @@ -4302,7 +4302,7 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd) int all_pinned = 0; struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask); - cpumask_setall(cpus); + cpumask_copy(cpus, cpu_online_mask); /* * When power savings policy is enabled for the parent domain, idle @@ -9542,6 +9542,8 @@ void __init sched_init(void) rq->cpu = i; rq->online = 0; rq->migration_thread = NULL; + rq->idle_stamp = 0; + rq->avg_idle = 2*sysctl_sched_migration_cost; INIT_LIST_HEAD(&rq->migration_queue); rq_attach_root(rq, &def_root_domain); #endif From 430b6ab743b6448873d4d9382af6c3f860dfdbb4 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 23 Nov 2009 12:50:00 +0100 Subject: [PATCH 051/670] x86/amd-iommu: attach devices to pre-allocated domains early commit be831297716036de5b24308447ecb69f1706a846 upstream. For some devices the ACPI table may define unity map requirements which must me met when the IOMMU is enabled. So we need to attach devices to their domains as early as possible so that these mappings are in place when needed. This patch assigns the domains right after they are allocated. Otherwise this can result in I/O page faults before a driver binds to a device and BIOS is still using it. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/amd_iommu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 0285521e0a99..90b9b559e7a4 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -2047,10 +2047,10 @@ static void prealloc_protection_domains(void) struct pci_dev *dev = NULL; struct dma_ops_domain *dma_dom; struct amd_iommu *iommu; - u16 devid; + u16 devid, __devid; while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - devid = calc_devid(dev->bus->number, dev->devfn); + __devid = devid = calc_devid(dev->bus->number, dev->devfn); if (devid > amd_iommu_last_bdf) continue; devid = amd_iommu_alias_table[devid]; @@ -2065,6 +2065,10 @@ static void prealloc_protection_domains(void) init_unity_mappings_for_device(dma_dom, devid); dma_dom->target_dev = devid; + attach_device(iommu, &dma_dom->domain, devid); + if (__devid != devid) + attach_device(iommu, &dma_dom->domain, __devid); + list_add_tail(&dma_dom->list, &iommu_pd_list); } } From e81ccb78036da2a31adc51ed676dbf2f158374f7 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 23 Nov 2009 12:45:25 +0100 Subject: [PATCH 052/670] x86/amd-iommu: un__init iommu_setup_msi commit 9f800de38b05d84809e89f16671d636a140eede7 upstream. This function may be called on the resume path and can not be dropped after booting. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/amd_iommu_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index c20001e4f556..e0b3130a1286 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -925,7 +925,7 @@ static int __init init_iommu_all(struct acpi_table_header *table) * ****************************************************************************/ -static int __init iommu_setup_msi(struct amd_iommu *iommu) +static int iommu_setup_msi(struct amd_iommu *iommu) { int r; From 7da88e8e91d39462ca08393de81b78b9507f8281 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 2 Dec 2009 15:05:56 -0800 Subject: [PATCH 053/670] x86, Calgary IOMMU quirk: Find nearest matching Calgary while walking up the PCI tree commit 4528752f49c1f4025473d12bc5fa9181085c3f22 upstream. On a multi-node x3950M2 system, there's a slight oddity in the PCI device tree for all secondary nodes: 30:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev e1) \-33:00.0 PCI bridge: IBM CalIOC2 PCI-E Root Port (rev 01) \-34:00.0 RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS 1078 (rev 04) ...as compared to the primary node: 00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev e1) \-01:00.0 VGA compatible controller: ATI Technologies Inc ES1000 (rev 02) 03:00.0 PCI bridge: IBM CalIOC2 PCI-E Root Port (rev 01) \-04:00.0 RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS 1078 (rev 04) In both nodes, the LSI RAID controller hangs off a CalIOC2 device, but on the secondary nodes, the BIOS hides the VGA device and substitutes the device tree ending with the disk controller. It would seem that Calgary devices don't necessarily appear at the top of the PCI tree, which means that the current code to find the Calgary IOMMU that goes with a particular device is buggy. Rather than walk all the way to the top of the PCI device tree and try to match bus number with Calgary descriptor, the code needs to examine each parent of the particular device; if it encounters a Calgary with a matching bus number, simply use that. Otherwise, we BUG() when the bus number of the Calgary doesn't match the bus number of whatever's at the top of the device tree. Extra note: This patch appears to work correctly for the x3950 that came before the x3950 M2. Signed-off-by: Darrick J. Wong Acked-by: Muli Ben-Yehuda Cc: FUJITA Tomonori Cc: Joerg Roedel Cc: Yinghai Lu Cc: Jon D. Mason Cc: Corinna Schultz LKML-Reference: <20091202230556.GG10295@tux1.beaverton.ibm.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/pci-calgary_64.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 971a3bec47a8..e6ec8a2df1c3 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -318,13 +318,15 @@ static inline struct iommu_table *find_iommu_table(struct device *dev) pdev = to_pci_dev(dev); + /* search up the device tree for an iommu */ pbus = pdev->bus; - - /* is the device behind a bridge? Look for the root bus */ - while (pbus->parent) + do { + tbl = pci_iommu(pbus); + if (tbl && tbl->it_busno == pbus->number) + break; + tbl = NULL; pbus = pbus->parent; - - tbl = pci_iommu(pbus); + } while (pbus); BUG_ON(tbl && (tbl->it_busno != pbus->number)); From 704c528bee45fc37546542bf578181cec0845a67 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 26 Oct 2009 15:41:46 +0100 Subject: [PATCH 054/670] x86: Fix iommu=nodac parameter handling commit 2ae8bb75db1f3de422eb5898f2a063c46c36dba8 upstream. iommu=nodac should forbid dac instead of enabling it. Fix it. Signed-off-by: Tejun Heo Acked-by: FUJITA Tomonori Cc: Matteo Frigo LKML-Reference: <4AE5B52A.4050408@kernel.org> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/pci-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index a6e804d16c35..6ac3931160d7 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -214,7 +214,7 @@ static __init int iommu_setup(char *p) if (!strncmp(p, "allowdac", 8)) forbid_dac = 0; if (!strncmp(p, "nodac", 5)) - forbid_dac = -1; + forbid_dac = 1; if (!strncmp(p, "usedac", 6)) { forbid_dac = -1; return 1; From 900f42a14f80f9bbb8e8695bb2fe38c310af656e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 9 Nov 2009 17:58:50 -0800 Subject: [PATCH 055/670] x86: GART: pci-gart_64.c: Use correct length in strncmp commit 41855b77547fa18d90ed6a5d322983d3fdab1959 upstream. Signed-off-by: Joe Perches LKML-Reference: <1257818330.12852.72.camel@Joe-Laptop.home> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/pci-gart_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index a7f1b64f86e0..fcc0b5c022c1 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -856,7 +856,7 @@ void __init gart_parse_options(char *p) #endif if (isdigit(*p) && get_option(&p, &arg)) iommu_size = arg; - if (!strncmp(p, "fullflush", 8)) + if (!strncmp(p, "fullflush", 9)) iommu_fullflush = 1; if (!strncmp(p, "nofullflush", 11)) iommu_fullflush = 0; From 78a794f462df2a701b754fd17415a88b8bf1bc61 Mon Sep 17 00:00:00 2001 From: Leann Ogasawara Date: Fri, 4 Dec 2009 15:42:22 -0800 Subject: [PATCH 056/670] x86: ASUS P4S800 reboot=bios quirk commit 4832ddda2ec4df96ea1eed334ae2dbd65fc1f541 upstream. Bug reporter noted their system with an ASUS P4S800 motherboard would hang when rebooting unless reboot=b was specified. Their dmidecode didn't contain descriptive System Information for Manufacturer or Product Name, so I used their Base Board Information to create a reboot quirk patch. The bug reporter confirmed this patch resolves the reboot hang. Handle 0x0001, DMI type 1, 25 bytes System Information Manufacturer: System Manufacturer Product Name: System Name Version: System Version Serial Number: SYS-1234567890 UUID: E0BFCD8B-7948-D911-A953-E486B4EEB67F Wake-up Type: Power Switch Handle 0x0002, DMI type 2, 8 bytes Base Board Information Manufacturer: ASUSTeK Computer INC. Product Name: P4S800 Version: REV 1.xx Serial Number: xxxxxxxxxxx BugLink: http://bugs.launchpad.net/bugs/366682 ASUS P4S800 will hang when rebooting unless reboot=b is specified. Add a quirk to reboot through the bios. Signed-off-by: Leann Ogasawara LKML-Reference: <1259972107.4629.275.camel@emiko> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/reboot.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index f93078746e00..6caf26010970 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -259,6 +259,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"), }, }, + { /* Handle problems with rebooting on ASUS P4S800 */ + .callback = set_bios_reboot, + .ident = "ASUS P4S800", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "P4S800"), + }, + }, { } }; From 8224532f94891bab12398b06c6359f0ce148a285 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Thu, 3 Dec 2009 15:52:44 +0100 Subject: [PATCH 057/670] x86, apic: Enable lapic nmi watchdog on AMD Family 11h commit 7d1849aff6687a135a8da3a75e32a00e3137a5e2 upstream. The x86 lapic nmi watchdog does not recognize AMD Family 11h, resulting in: NMI watchdog: CPU not supported As far as I can see from available documentation (the BKDM), family 11h looks identical to family 10h as far as the PMU is concerned. Extending the check to accept family 11h results in: Testing NMI watchdog ... OK. I've been running with this change on a Turion X2 Ultra ZM-82 laptop for a couple of weeks now without problems. Signed-off-by: Mikael Pettersson Cc: Andreas Herrmann Cc: Joerg Roedel LKML-Reference: <19223.53436.931768.278021@pilspetsen.it.uu.se> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/perfctr-watchdog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index fab786f60ed6..898df9719afb 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -712,7 +712,7 @@ static void probe_nmi_watchdog(void) switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 && - boot_cpu_data.x86 != 16) + boot_cpu_data.x86 != 16 && boot_cpu_data.x86 != 17) return; wd_ops = &k7_wd_ops; break; From ee17dd1efa301f6d113f461db7e2b9c06655f3fb Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 23 Nov 2009 20:58:06 +0100 Subject: [PATCH 058/670] ssb: Fix range check in sprom write commit e33761e6f23881de9f3ee77cc2204ab2e26f3d9a upstream. The range check in the sprom image parser hex2sprom() is broken. One sprom word is 4 hex characters. This fixes the check and also adds much better sanity checks to the code. We better make sure the image is OK by doing some sanity checks to avoid bricking the device by accident. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/ssb/sprom.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c index 8943015a3eef..eb708431cb96 100644 --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c @@ -13,6 +13,8 @@ #include "ssb_private.h" +#include + static const struct ssb_sprom *fallback_sprom; @@ -33,17 +35,27 @@ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, static int hex2sprom(u16 *sprom, const char *dump, size_t len, size_t sprom_size_words) { - char tmp[5] = { 0 }; - int cnt = 0; + char c, tmp[5] = { 0 }; + int err, cnt = 0; unsigned long parsed; - if (len < sprom_size_words * 2) + /* Strip whitespace at the end. */ + while (len) { + c = dump[len - 1]; + if (!isspace(c) && c != '\0') + break; + len--; + } + /* Length must match exactly. */ + if (len != sprom_size_words * 4) return -EINVAL; while (cnt < sprom_size_words) { memcpy(tmp, dump, 4); dump += 4; - parsed = simple_strtoul(tmp, NULL, 16); + err = strict_strtoul(tmp, 16, &parsed); + if (err) + return err; sprom[cnt++] = swab16((u16)parsed); } From f0da7d9ab2ab222669e51f0404dc9b4e2fef9944 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 16 Nov 2009 08:30:29 -0500 Subject: [PATCH 059/670] ath5k: allow setting txpower to 0 commit 2eb2fa67e5462a36e98172fb92c78bc405b3035f upstream. As a holdover from earlier code when we used to set the power limit to '0' after a reset to configure the default transmit power, ath5k interprets txpower=0 as 12.5 dBm. Fix that by just passing 0 through. This fixes http://bugzilla.kernel.org/show_bug.cgi?id=14567 Reported-by: Daniel Folkers Tested-by: Daniel Folkers Signed-off-by: Bob Copeland Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath5k/phy.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 1a039f2bd732..9d676474839d 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -2954,8 +2954,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); return -EINVAL; } - if (txpower == 0) - txpower = AR5K_TUNE_DEFAULT_TXPOWER; /* Reset TX power values */ memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); From 8bf3d79bc401ca417ccf9fc076d3295d1a71dbf5 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 25 Nov 2009 17:23:26 -0500 Subject: [PATCH 060/670] ath5k: enable EEPROM checksum check commit 512414b0bed0d376ac4d5ec1dd6f0b1a3551febc upstream. Without this we have no gaurantee of the integrity of the EEPROM and are likely to encounter a lot of bogus bug reports due to actual issues on the EEPROM. With the EEPROM checksum check in place we can easily rule those issues out. If you run patch during a revert *you* have a card with a busted EEPROM and only older kernel will support that concoction. This patch is a trade off between not accepitng bogus EEPROMs and avoiding bogus bug reports allowing developers to focus instead on real concrete issues. If stable keeps bogus bug reports because of a possibly busted EEPROM feel free to apply this there too. Tested on an AR5414 Cc: jirislaby@gmail.com Cc: akpm@linux-foundation.org Cc: rjw@sisk.pl Cc: me@bobcopeland.com Cc: david.quan@atheros.com Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath5k/eeprom.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 644962adda97..791885262602 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -97,6 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; int ret; u16 val; + u32 cksum, offset; /* * Read values from EEPROM and store them in the capability structure @@ -111,7 +112,6 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) return 0; -#ifdef notyet /* * Validate the checksum of the EEPROM date. There are some * devices with invalid EEPROMs. @@ -124,7 +124,6 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); return -EIO; } -#endif AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), ee_ant_gain); From 630d0a27ad4eabede5defec0595b8a703d5b6b71 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Thu, 3 Sep 2009 16:32:53 +0800 Subject: [PATCH 061/670] hrtimer: Fix /proc/timer_list regression commit 8629ea2eaba8ca0de2e38ce1b4a825e16255976e upstream. commit 507e1231 (timer stats: Optimize by adding quick check to avoid function calls) introduced a regression in /proc/timer_list. /proc/timer_list shows now #0: , tick_sched_timer, S:01, <(null)>, /-1 instead of #0: , tick_sched_timer, S:01, hrtimer_start, swapper/0 Revert the hrtimer quick check for now. The optimization needs more thought, but this is neither 2.6.32-rc7 nor stable material. [ tglx: - Removed unrelated changes from the original patch - Prevent unneccesary call to timer_stats_update_stats - massaged the changelog ] Signed-off-by: Feng Tang LKML-Reference: Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- include/linux/hrtimer.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index ff037f0b1b4e..9bace4b9f4fe 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -446,7 +446,7 @@ extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf, static inline void timer_stats_account_hrtimer(struct hrtimer *timer) { - if (likely(!timer->start_site)) + if (likely(!timer_stats_active)) return; timer_stats_update_stats(timer, timer->start_pid, timer->start_site, timer->function, timer->start_comm, 0); @@ -457,8 +457,6 @@ extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) { - if (likely(!timer_stats_active)) - return; __timer_stats_hrtimer_set_start_info(timer, __builtin_return_address(0)); } From f6f725781c331351cdcaaec322706d342e285122 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 11 Dec 2009 12:51:05 +0100 Subject: [PATCH 062/670] ALSA: hrtimer - Fix lock-up commit fcfdebe70759c74e2e701f69aaa7f0e5e32cf5a6 upstream. The timer stop callback can be called from snd_timer_interrupt(), which is called from the hrtimer callback. Since hrtimer_cancel() waits for the callback completion, this eventually results in a lock-up. This patch fixes the problem by just toggling a flag at stop callback and call hrtimer_cancel() later. Reported-and-tested-by: Wojtek Zabolotny Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/hrtimer.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index 34c7d48f5061..7f4d744ae40a 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -37,14 +37,22 @@ static unsigned int resolution; struct snd_hrtimer { struct snd_timer *timer; struct hrtimer hrt; + atomic_t running; }; static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) { struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt); struct snd_timer *t = stime->timer; + + if (!atomic_read(&stime->running)) + return HRTIMER_NORESTART; + hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution)); snd_timer_interrupt(stime->timer, t->sticks); + + if (!atomic_read(&stime->running)) + return HRTIMER_NORESTART; return HRTIMER_RESTART; } @@ -58,6 +66,7 @@ static int snd_hrtimer_open(struct snd_timer *t) hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); stime->timer = t; stime->hrt.function = snd_hrtimer_callback; + atomic_set(&stime->running, 0); t->private_data = stime; return 0; } @@ -78,16 +87,18 @@ static int snd_hrtimer_start(struct snd_timer *t) { struct snd_hrtimer *stime = t->private_data; + atomic_set(&stime->running, 0); + hrtimer_cancel(&stime->hrt); hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), HRTIMER_MODE_REL); + atomic_set(&stime->running, 1); return 0; } static int snd_hrtimer_stop(struct snd_timer *t) { struct snd_hrtimer *stime = t->private_data; - - hrtimer_cancel(&stime->hrt); + atomic_set(&stime->running, 0); return 0; } From 7cb056b8203edc77c0b69431cf1312805a008484 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 9 Dec 2009 10:44:47 +0100 Subject: [PATCH 063/670] ALSA: hda - Terradici HDA controllers does not support 64-bit mode commit 396087eaead95fcb29eb36f1e59517aeb58c545e upstream. Confirmed from vendor and tests in RedHat bugzilla #536782 . Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_intel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 6517f589d01d..7e4ee4e89737 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2436,6 +2436,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } } + /* disable 64bit DMA address for Teradici */ + /* it does not work with device 6549:1200 subsys e4a2:040b */ + if (chip->driver_type == AZX_DRIVER_TERA) + gcap &= ~ICH6_GCAP_64OK; + /* allow 64bit DMA address if supported by H/W */ if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); From b63569376aeca6300e10bf9e5ccfc49758407dbf Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 24 Nov 2009 15:20:15 +0200 Subject: [PATCH 064/670] KVM: x86 emulator: limit instructions to 15 bytes commit eb3c79e64a70fb8f7473e30fa07e89c1ecc2c9bb upstream. While we are never normally passed an instruction that exceeds 15 bytes, smp games can cause us to attempt to interpret one, which will cause large latencies in non-preempt hosts. Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/kvm_emulate.h | 2 +- arch/x86/kvm/emulate.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index b7ed2c423116..7c18e1230f54 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -129,7 +129,7 @@ struct decode_cache { u8 seg_override; unsigned int d; unsigned long regs[NR_VCPU_REGS]; - unsigned long eip; + unsigned long eip, eip_orig; /* modrm */ u8 modrm; u8 modrm_mod; diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 1be5cd640e93..e02dbb670d5b 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -613,6 +613,9 @@ static int do_insn_fetch(struct x86_emulate_ctxt *ctxt, { int rc = 0; + /* x86 instructions are limited to 15 bytes. */ + if (eip + size - ctxt->decode.eip_orig > 15) + return X86EMUL_UNHANDLEABLE; eip += ctxt->cs_base; while (size--) { rc = do_fetch_insn_byte(ctxt, ops, eip++, dest++); @@ -871,7 +874,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) /* Shadow copy of register state. Committed on successful emulation. */ memset(c, 0, sizeof(struct decode_cache)); - c->eip = kvm_rip_read(ctxt->vcpu); + c->eip = c->eip_orig = kvm_rip_read(ctxt->vcpu); ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS); memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs); From f7b0fd208527e8f755e06411821efb5cc89c0868 Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Mon, 30 Nov 2009 17:14:41 +0100 Subject: [PATCH 065/670] KVM: s390: Fix prefix register checking in arch/s390/kvm/sigp.c commit f50146bd7bdb75435638e60d4960edd9bcdf88b8 upstream. This patch corrects the checking of the new address for the prefix register. On s390, the prefix register is used to address the cpu's lowcore (address 0...8k). This check is supposed to verify that the memory is readable and present. copy_from_guest is a helper function, that can be used to read from guest memory. It applies prefixing, adds the start address of the guest memory in user, and then calls copy_from_user. Previous code was obviously broken for two reasons: - prefixing should not be applied here. The current prefix register is going to be updated soon, and the address we're looking for will be 0..8k after we've updated the register - we're adding the guest origin (gmsor) twice: once in subject code and once in copy_from_guest With kuli, we did not hit this problem because (a) we were lucky with previous prefix register content, and (b) our guest memory was mmaped very low into user address space. Signed-off-by: Carsten Otte Reported-by: Alexander Graf Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- arch/s390/kvm/sigp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 40c8c6748cfe..15ee1111de58 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -188,9 +188,9 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, /* make sure that the new value is valid memory */ address = address & 0x7fffe000u; - if ((copy_from_guest(vcpu, &tmp, - (u64) (address + vcpu->arch.sie_block->gmsor) , 1)) || - (copy_from_guest(vcpu, &tmp, (u64) (address + + if ((copy_from_user(&tmp, (void __user *) + (address + vcpu->arch.sie_block->gmsor) , 1)) || + (copy_from_user(&tmp, (void __user *)(address + vcpu->arch.sie_block->gmsor + PAGE_SIZE), 1))) { *reg |= SIGP_STAT_INVALID_PARAMETER; return 1; /* invalid parameter */ From fff7d05d83d41107dd1c8740cfbfd50fe3ce87e8 Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Thu, 19 Nov 2009 14:21:16 +0100 Subject: [PATCH 066/670] KVM: s390: Make psw available on all exits, not just a subset commit d7b0b5eb3000c6fb902f08c619fcd673a23d8fab upstream. This patch moves s390 processor status word into the base kvm_run struct and keeps it up-to date on all userspace exits. The userspace ABI is broken by this, however there are no applications in the wild using this. A capability check is provided so users can verify the updated API exists. Signed-off-by: Carsten Otte Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- arch/s390/include/asm/kvm.h | 3 ++- arch/s390/kvm/kvm-s390.c | 25 +++++++++++++++++-------- include/linux/kvm.h | 8 ++++++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/arch/s390/include/asm/kvm.h b/arch/s390/include/asm/kvm.h index 3dfcaeb5d7f4..82b32a100c7d 100644 --- a/arch/s390/include/asm/kvm.h +++ b/arch/s390/include/asm/kvm.h @@ -1,6 +1,5 @@ #ifndef __LINUX_KVM_S390_H #define __LINUX_KVM_S390_H - /* * asm-s390/kvm.h - KVM s390 specific structures and definitions * @@ -15,6 +14,8 @@ */ #include +#define __KVM_S390 + /* for KVM_GET_REGS and KVM_SET_REGS */ struct kvm_regs { /* general purpose regs for s390 */ diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 07ced89740d7..ca2d31277b3b 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -116,10 +116,16 @@ long kvm_arch_dev_ioctl(struct file *filp, int kvm_dev_ioctl_check_extension(long ext) { + int r; + switch (ext) { + case KVM_CAP_S390_PSW: + r = 1; + break; default: - return 0; + r = 0; } + return r; } /* Section: vm related */ @@ -419,8 +425,10 @@ static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw) vcpu_load(vcpu); if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING) rc = -EBUSY; - else - vcpu->arch.sie_block->gpsw = psw; + else { + vcpu->run->psw_mask = psw.mask; + vcpu->run->psw_addr = psw.addr; + } vcpu_put(vcpu); return rc; } @@ -508,9 +516,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) switch (kvm_run->exit_reason) { case KVM_EXIT_S390_SIEIC: - vcpu->arch.sie_block->gpsw.mask = kvm_run->s390_sieic.mask; - vcpu->arch.sie_block->gpsw.addr = kvm_run->s390_sieic.addr; - break; case KVM_EXIT_UNKNOWN: case KVM_EXIT_INTR: case KVM_EXIT_S390_RESET: @@ -519,6 +524,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) BUG(); } + vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask; + vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr; + might_fault(); do { @@ -538,8 +546,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) /* intercept cannot be handled in-kernel, prepare kvm-run */ kvm_run->exit_reason = KVM_EXIT_S390_SIEIC; kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode; - kvm_run->s390_sieic.mask = vcpu->arch.sie_block->gpsw.mask; - kvm_run->s390_sieic.addr = vcpu->arch.sie_block->gpsw.addr; kvm_run->s390_sieic.ipa = vcpu->arch.sie_block->ipa; kvm_run->s390_sieic.ipb = vcpu->arch.sie_block->ipb; rc = 0; @@ -551,6 +557,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) rc = 0; } + kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask; + kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr; + if (vcpu->sigset_active) sigprocmask(SIG_SETMASK, &sigsaved, NULL); diff --git a/include/linux/kvm.h b/include/linux/kvm.h index f8f8900fc5ec..8908dd6cd343 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -116,6 +116,11 @@ struct kvm_run { __u64 cr8; __u64 apic_base; +#ifdef __KVM_S390 + /* the processor status word for s390 */ + __u64 psw_mask; /* psw upper half */ + __u64 psw_addr; /* psw lower half */ +#endif union { /* KVM_EXIT_UNKNOWN */ struct { @@ -167,8 +172,6 @@ struct kvm_run { /* KVM_EXIT_S390_SIEIC */ struct { __u8 icptcode; - __u64 mask; /* psw upper half */ - __u64 addr; /* psw lower half */ __u16 ipa; __u32 ipb; } s390_sieic; @@ -474,6 +477,7 @@ struct kvm_irq_routing { }; #endif +#define KVM_CAP_S390_PSW 42 #ifdef KVM_CAP_MCE /* x86 MCE */ From 310c1a04807321c666445292db4b9147f1174c08 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Sat, 17 Oct 2009 22:47:23 -0300 Subject: [PATCH 067/670] KVM: fix irq_source_id size verification commit cd5a2685de4a642fd0bd763e8c19711ef08dbe27 upstream. find_first_zero_bit works with bit numbers, not bytes. Fixes https://sourceforge.net/tracker/?func=detail&aid=2847560&group_id=180599&atid=893831 Reported-by: "Xu, Jiajun" Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- virt/kvm/irq_comm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index 001663ff401a..03e5b217e88b 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -205,10 +205,9 @@ int kvm_request_irq_source_id(struct kvm *kvm) int irq_source_id; mutex_lock(&kvm->irq_lock); - irq_source_id = find_first_zero_bit(bitmap, - sizeof(kvm->arch.irq_sources_bitmap)); + irq_source_id = find_first_zero_bit(bitmap, BITS_PER_LONG); - if (irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) { + if (irq_source_id >= BITS_PER_LONG) { printk(KERN_WARNING "kvm: exhaust allocatable IRQ sources!\n"); return -EFAULT; } @@ -228,7 +227,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) mutex_lock(&kvm->irq_lock); if (irq_source_id < 0 || - irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) { + irq_source_id >= BITS_PER_LONG) { printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); return; } From a55770ccda90d9c1ed3b2408ea93f346278e6522 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Tue, 6 Oct 2009 13:24:50 -0400 Subject: [PATCH 068/670] KVM: x86: include pvclock MSRs in msrs_to_save commit e3267cbbbfbcbe9c18833e89b10beabb1117cb55 upstream. For a while now, we are issuing a rdmsr instruction to find out which msrs in our save list are really supported by the underlying machine. However, it fails to account for kvm-specific msrs, such as the pvclock ones. This patch moves then to the beginning of the list, and skip testing them. Signed-off-by: Glauber Costa Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ae07d261527c..97b31fa63088 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -484,16 +484,19 @@ static inline u32 bit(int bitno) * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST. * * This list is modified at module load time to reflect the - * capabilities of the host cpu. + * capabilities of the host cpu. This capabilities test skips MSRs that are + * kvm-specific. Those are put in the beginning of the list. */ + +#define KVM_SAVE_MSRS_BEGIN 2 static u32 msrs_to_save[] = { + MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, MSR_K6_STAR, #ifdef CONFIG_X86_64 MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, #endif - MSR_IA32_TSC, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, - MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA + MSR_IA32_TSC, MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA }; static unsigned num_msrs_to_save; @@ -2433,7 +2436,8 @@ static void kvm_init_msr_list(void) u32 dummy[2]; unsigned i, j; - for (i = j = 0; i < ARRAY_SIZE(msrs_to_save); i++) { + /* skip the first msrs in the list. KVM-specific */ + for (i = j = KVM_SAVE_MSRS_BEGIN; i < ARRAY_SIZE(msrs_to_save); i++) { if (rdmsr_safe(msrs_to_save[i], &dummy[0], &dummy[1]) < 0) continue; if (j < i) From 8de7f4a42cbdaa15a05b22fcfa01d38b6f8e0f5b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 20 Nov 2009 12:01:43 +0100 Subject: [PATCH 069/670] x86: Prevent GCC 4.4.x (pentium-mmx et al) function prologue wreckage commit 746357d6a526d6da9d89a2ec645b28406e959c2e upstream. When the kernel is compiled with -pg for tracing GCC 4.4.x inserts stack alignment of a function _before_ the mcount prologue if the -march=pentium-mmx is set and -mtune=generic is not set. This breaks the assumption of the function graph tracer which expects that the mcount prologue push %ebp mov %esp, %ebp is the first stack operation in a function because it needs to modify the function return address on the stack to trap into the tracer before returning to the real caller. The generated code is: push %edi lea 0x8(%esp),%edi and $0xfffffff0,%esp pushl -0x4(%edi) push %ebp mov %esp,%ebp so the tracer modifies the copy of the return address which is stored after the stack alignment and therefor does not trap the return which in turn breaks the call chain logic of the tracer and leads to a kernel panic. Aside of the fact that the generated code is horrible for no good reason other -march -mtune options generate the expected: push %ebp mov %esp,%ebp and $0xfffffff0,%esp which does the same and keeps everything intact. After some experimenting we found out that this problem is restricted to gcc4.4.x and to the following -march settings: i586, pentium, pentium-mmx, k6, k6-2, k6-3, winchip-c6, winchip2, c3, geode By adding -mtune=generic the code generator produces always the expected code. So forcing -mtune=generic when CONFIG_FUNCTION_GRAPH_TRACER=y is not pretty, but at the moment the only way to prevent that the kernel trips over gcc-shrooms induced code madness. Most distro kernels have CONFIG_X86_GENERIC=y anyway which forces -mtune=generic as well so it will not impact those. References: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42109 http://lkml.org/lkml/2009/11/19/17 Signed-off-by: Thomas Gleixner LKML-Reference: Cc: Linus Torvalds Cc: Andrew Morton Cc: Ingo Molnar Cc: Peter Zijlstra Cc: H. Peter Anvin Cc: Steven Rostedt Cc: Frederic Weisbecker , Cc: Jeff Law Cc: gcc@gcc.gnu.org Cc: David Daney Cc: Andrew Haley Cc: Richard Guenther Signed-off-by: Greg Kroah-Hartman --- arch/x86/Makefile_32.cpu | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/Makefile_32.cpu b/arch/x86/Makefile_32.cpu index 30e9a264f69d..76e199fc77ac 100644 --- a/arch/x86/Makefile_32.cpu +++ b/arch/x86/Makefile_32.cpu @@ -46,6 +46,12 @@ cflags-$(CONFIG_MGEODEGX1) += -march=pentium-mmx # cpu entries cflags-$(CONFIG_X86_GENERIC) += $(call tune,generic,$(call tune,i686)) +# Work around the pentium-mmx code generator madness of gcc4.4.x which +# does stack alignment by generating horrible code _before_ the mcount +# prologue (push %ebp, mov %esp, %ebp) which breaks the function graph +# tracer assumptions +cflags-$(CONFIG_FUNCTION_GRAPH_TRACER) += $(call cc-option,-mtune=generic) + # Bug fix for binutils: this option is required in order to keep # binutils from generating NOPL instructions against our will. ifneq ($(CONFIG_X86_P6_NOP),y) From ceb9c79365c6eb4971effbb28c118874ae83410e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sat, 28 Nov 2009 15:03:03 +0100 Subject: [PATCH 070/670] x86: Use -maccumulate-outgoing-args for sane mcount prologues commit b8b7d791a8ff01d2380089279a69afa99115fb23 upstream. commit 746357d (x86: Prevent GCC 4.4.x (pentium-mmx et al) function prologue wreckage) uses -mtune=generic to work around the function prologue problem with mcount on -march=pentium-mmx and others. Jakub pointed out that we can use -maccumulate-outgoing-args instead which is selected by -mtune=generic and prevents the problem without losing the -march specific optimizations. Pointed-out-by: Jakub Jelinek Signed-off-by: Thomas Gleixner Cc: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/Makefile_32.cpu | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/Makefile_32.cpu b/arch/x86/Makefile_32.cpu index 76e199fc77ac..1937226fd502 100644 --- a/arch/x86/Makefile_32.cpu +++ b/arch/x86/Makefile_32.cpu @@ -49,8 +49,9 @@ cflags-$(CONFIG_X86_GENERIC) += $(call tune,generic,$(call tune,i686)) # Work around the pentium-mmx code generator madness of gcc4.4.x which # does stack alignment by generating horrible code _before_ the mcount # prologue (push %ebp, mov %esp, %ebp) which breaks the function graph -# tracer assumptions -cflags-$(CONFIG_FUNCTION_GRAPH_TRACER) += $(call cc-option,-mtune=generic) +# tracer assumptions. For i686, generic, core2 this is set by the +# compiler anyway +cflags-$(CONFIG_FUNCTION_GRAPH_TRACER) += $(call cc-option,-maccumulate-outgoing-args) # Bug fix for binutils: this option is required in order to keep # binutils from generating NOPL instructions against our will. From 05217134d25f399adb7bb3db195e7dc64ad77289 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Thu, 3 Dec 2009 11:33:08 +0900 Subject: [PATCH 071/670] x86, mce: don't restart timer if disabled commit fe5ed91ddce85a0ed0e4f92c10b099873ef62167 upstream. Even it is in error path unlikely taken, add_timer_on() at CPU_DOWN_FAILED* needs to be skipped if mce_timer is disabled. Signed-off-by: Hidetoshi Seto Cc: Andi Kleen Cc: Huang Ying Cc: Jan Beulich Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 721a77ca8115..4825a3d6eb40 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1991,9 +1991,11 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) break; case CPU_DOWN_FAILED: case CPU_DOWN_FAILED_FROZEN: - t->expires = round_jiffies(jiffies + + if (!mce_ignore_ce && check_interval) { + t->expires = round_jiffies(jiffies + __get_cpu_var(mce_next_interval)); - add_timer_on(t, cpu); + add_timer_on(t, cpu); + } smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); break; case CPU_POST_DEAD: From e8aab284380017e1aee419ab45e87d89eff8cf00 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 8 Dec 2009 11:21:37 +0900 Subject: [PATCH 072/670] x86/mce: Set up timer unconditionally commit bc09effabf0c5c6c7021e5ef9af15a23579b32a8 upstream. mce_timer must be passed to setup_timer() in all cases, no matter whether it is going to be actually used. Otherwise, when the CPU gets brought down, its call to del_timer_sync() will never return, as the timer won't have a base associated, and hence lock_timer_base() will loop infinitely. Signed-off-by: Jan Beulich Signed-off-by: Hidetoshi Seto LKML-Reference: <4B1DB831.2030801@jp.fujitsu.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/mce.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 4825a3d6eb40..0f16a2bfd6a9 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1374,13 +1374,14 @@ static void mce_init_timer(void) struct timer_list *t = &__get_cpu_var(mce_timer); int *n = &__get_cpu_var(mce_next_interval); + setup_timer(t, mcheck_timer, smp_processor_id()); + if (mce_ignore_ce) return; *n = check_interval * HZ; if (!*n) return; - setup_timer(t, mcheck_timer, smp_processor_id()); t->expires = round_jiffies(jiffies + *n); add_timer_on(t, smp_processor_id()); } From 3715cace63b4751445181cefcb2eba77b30d8525 Mon Sep 17 00:00:00 2001 From: Cliff Wickman Date: Thu, 19 Nov 2009 17:12:43 -0600 Subject: [PATCH 073/670] x86: SGI UV: Fix BAU initialization commit e38e2af1c57c3eb5211331a5b4fcaae0c4a2a918 upstream. A memory mapped register that affects the SGI UV Broadcast Assist Unit's interrupt handling may sometimes be unintialized. Remove the condition on its initialization, as that condition can be randomly satisfied by a hardware reset. Signed-off-by: Cliff Wickman LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/tlb_uv.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 1740c85e24bb..364d015efebc 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -817,10 +817,8 @@ static int __init uv_init_blade(int blade) */ apicid = blade_to_first_apicid(blade); pa = uv_read_global_mmr64(pnode, UVH_BAU_DATA_CONFIG); - if ((pa & 0xff) != UV_BAU_MESSAGE) { - uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, + uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, ((apicid << 32) | UV_BAU_MESSAGE)); - } return 0; } From cf8b14f356f1ab35c88209c7efb3050bbb473946 Mon Sep 17 00:00:00 2001 From: Cliff Wickman Date: Fri, 11 Dec 2009 11:36:18 -0600 Subject: [PATCH 074/670] x86: Fix duplicated UV BAU interrupt vector commit 1d865fb728bd6bbcdfbd6ec1e2b8ade3b4805641 upstream. Interrupt vector 0xec has been doubly defined in irq_vectors.h It seems arbitrary whether LOCAL_PENDING_VECTOR or UV_BAU_MESSAGE is the higher number. As long as they are unique. If they are not unique we'll hit a BUG in alloc_system_vector(). Signed-off-by: Cliff Wickman LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/irq_vectors.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 5b21f0ec3df2..6e90a049c960 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h @@ -113,7 +113,7 @@ */ #define LOCAL_PENDING_VECTOR 0xec -#define UV_BAU_MESSAGE 0xec +#define UV_BAU_MESSAGE 0xea /* * Self IPI vector for machine checks From 04071db2c1079698a87d371fd67aef4ad6cd6db1 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 10 Nov 2009 13:49:24 -0500 Subject: [PATCH 075/670] x86: Add new Intel CPU cache size descriptors commit 85160b92fbd35321104819283c91bfed2b553e3c upstream. The latest rev of Intel doc AP-485 details new cache descriptors that we don't yet support. 12MB, 18MB and 24MB 24-way assoc L3 caches. Signed-off-by: Dave Jones LKML-Reference: <20091110184924.GA20337@redhat.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/intel_cacheinfo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 804c40e2bc3e..14103924b627 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -102,6 +102,9 @@ static const struct _cache_table __cpuinitconst cache_table[] = { 0xe2, LVL_3, 2048 }, /* 16-way set assoc, 64 byte line size */ { 0xe3, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */ { 0xe4, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */ + { 0xea, LVL_3, 12288 }, /* 24-way set assoc, 64 byte line size */ + { 0xeb, LVL_3, 18432 }, /* 24-way set assoc, 64 byte line size */ + { 0xec, LVL_3, 24576 }, /* 24-way set assoc, 64 byte line size */ { 0x00, 0, 0} }; From dff8a48a124bd07016f5900061bdf6f4cef6a953 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 10 Nov 2009 15:01:20 -0500 Subject: [PATCH 076/670] x86: Fix typo in Intel CPU cache size descriptor commit e02e0e1a130b9ca37c5186d38ad4b3aaf58bb149 upstream. I double-checked the datasheet. One of the existing descriptors has a typo: it should be 2MB not 2038 KB. Signed-off-by: Dave Jones LKML-Reference: <20091110200120.GA27090@redhat.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/intel_cacheinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 14103924b627..8178d0352935 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -94,7 +94,7 @@ static const struct _cache_table __cpuinitconst cache_table[] = { 0xd1, LVL_3, 1024 }, /* 4-way set assoc, 64 byte line size */ { 0xd2, LVL_3, 2048 }, /* 4-way set assoc, 64 byte line size */ { 0xd6, LVL_3, 1024 }, /* 8-way set assoc, 64 byte line size */ - { 0xd7, LVL_3, 2038 }, /* 8-way set assoc, 64 byte line size */ + { 0xd7, LVL_3, 2048 }, /* 8-way set assoc, 64 byte line size */ { 0xd8, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */ { 0xdc, LVL_3, 2048 }, /* 12-way set assoc, 64 byte line size */ { 0xdd, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */ From effa97cc19cf828bc21c950c1c19e2deef11e874 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 27 Nov 2009 22:29:02 +0400 Subject: [PATCH 077/670] pata_hpt{37x|3x2n}: fix timing register masks (take 2) commit 5600c70e576199a7552e1c0fff43f3fe16f5566e upstream. These drivers inherited from the older 'hpt366' IDE driver the buggy timing register masks in their set_piomode() metods. As a result, too low command cycle active time is programmed for slow PIO modes. Quite fortunately, it's later "fixed up" by the set_dmamode() methods which also "helpfully" reprogram the command timings, usually to PIO mode 4; unfortunately, setting an UltraDMA mode #N also reprograms already set PIO data timings, usually to MWDMA mode # max(N, 2) timings... However, the drivers added some breakage of their own too: the bit that they set/clear to control the FIFO is sometimes wrong -- it's actually the MSB of the command cycle setup time; also, setting it in DMA mode is wrong as this bit is only for PIO actually and clearing it for PIO modes is not needed as no mode in any timing table has it set... Fix all this, inverting the masks while at it, like in the 'hpt366' and 'pata_hpt366' drivers; bump the drivers' versions, accounting for recent patches that forgot to do it... Signed-off-by: Sergei Shtylyov Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/pata_hpt37x.c | 32 +++++++++++++++----------------- drivers/ata/pata_hpt3x2n.c | 17 ++++++++--------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index d0a7df2e5ca7..ec07c5378461 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -24,7 +24,7 @@ #include #define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.6.12" +#define DRV_VERSION "0.6.14" struct hpt_clock { u8 xfer_speed; @@ -404,9 +404,8 @@ static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev) pci_read_config_dword(pdev, addr1, ®); mode = hpt37x_find_mode(ap, adev->pio_mode); - mode &= ~0x8000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ + mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ + reg &= ~0xCFC3FFFF; /* Strip timing bits */ pci_write_config_dword(pdev, addr1, reg | mode); } @@ -423,8 +422,7 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, mode, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -436,11 +434,12 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) fast |= 0x01; pci_write_config_byte(pdev, addr2, fast); + mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; + pci_read_config_dword(pdev, addr1, ®); mode = hpt37x_find_mode(ap, adev->dma_mode); - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ - mode &= ~0xC0000000; /* Leave config bits alone */ - reg &= 0xC0000000; /* Strip timing bits */ + mode &= mask; + reg &= ~mask; pci_write_config_dword(pdev, addr1, reg | mode); } @@ -508,9 +507,8 @@ static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) mode = hpt37x_find_mode(ap, adev->pio_mode); printk("Find mode for %d reports %X\n", adev->pio_mode, mode); - mode &= ~0x80000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ + mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ + reg &= ~0xCFC3FFFF; /* Strip timing bits */ pci_write_config_dword(pdev, addr1, reg | mode); } @@ -527,8 +525,7 @@ static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, mode, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -539,12 +536,13 @@ static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev) fast &= ~0x07; pci_write_config_byte(pdev, addr2, fast); + mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; + pci_read_config_dword(pdev, addr1, ®); mode = hpt37x_find_mode(ap, adev->dma_mode); printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode); - mode &= ~0xC0000000; /* Leave config bits alone */ - mode |= 0x80000000; /* FIFO in MWDMA or UDMA */ - reg &= 0xC0000000; /* Strip timing bits */ + mode &= mask; + reg &= ~mask; pci_write_config_dword(pdev, addr1, reg | mode); } diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index 3d59fe0a408d..21c5bd6084fa 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -25,7 +25,7 @@ #include #define DRV_NAME "pata_hpt3x2n" -#define DRV_VERSION "0.3.4" +#define DRV_VERSION "0.3.7" enum { HPT_PCI_FAST = (1 << 31), @@ -185,9 +185,8 @@ static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev) pci_read_config_dword(pdev, addr1, ®); mode = hpt3x2n_find_mode(ap, adev->pio_mode); - mode &= ~0x8000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ + mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ + reg &= ~0xCFC3FFFF; /* Strip timing bits */ pci_write_config_dword(pdev, addr1, reg | mode); } @@ -204,8 +203,7 @@ static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, mode, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -216,11 +214,12 @@ static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev) fast &= ~0x07; pci_write_config_byte(pdev, addr2, fast); + mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; + pci_read_config_dword(pdev, addr1, ®); mode = hpt3x2n_find_mode(ap, adev->dma_mode); - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ - mode &= ~0xC0000000; /* Leave config bits alone */ - reg &= 0xC0000000; /* Strip timing bits */ + mode &= mask; + reg &= ~mask; pci_write_config_dword(pdev, addr1, reg | mode); } From ea76a1295e44ace82062690bca71436f03b26c39 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Mon, 7 Dec 2009 12:44:42 +0100 Subject: [PATCH 078/670] s390: clear high-order bits of registers after sam64 commit cf87b7439ec81b9374e7772e44e9cb2eb9e57160 upstream. When the kernel is IPLed without the CLEAR option and switches to 64-bit, the high-order half of the registers might contain random values. This can cause addressing exceptions and the kernel enters an interrupt loop. Initialize the high-order half of the general purpose registers with zeros after switching to 64-bit mode. Signed-off-by: Hendrik Brueckner Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/head64.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 6a250808092b..d984a2a380c3 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -83,6 +83,8 @@ startup_continue: slr %r0,%r0 # set cpuid to zero sigp %r1,%r0,0x12 # switch to esame mode sam64 # switch to 64 bit mode + llgfr %r13,%r13 # clear high-order half of base reg + lmh %r0,%r15,.Lzero64-.LPG1(%r13) # clear high-order half lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area # move IPL device to lowcore @@ -127,6 +129,7 @@ startup_continue: .L4malign:.quad 0xffffffffffc00000 .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 .Lnop: .long 0x07000700 +.Lzero64:.fill 16,4,0x0 #ifdef CONFIG_ZFCPDUMP .Lcurrent_cpu: .long 0x0 From 839646ece349e6ac42ecae95200c9e950c14e4de Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 20 Nov 2009 15:34:13 -0300 Subject: [PATCH 079/670] V4L/DVB: Fix test in copy_reg_bits() commit c95a419a5604ec8a23cd73f61e9bb151e8cbe89b upstream. The reg_pair2[j].reg was tested twice. Signed-off-by: Roel Kluin Acked-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/common/tuners/mxl5007t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c index 2d02698d4f4f..7eb1bf75cd07 100644 --- a/drivers/media/common/tuners/mxl5007t.c +++ b/drivers/media/common/tuners/mxl5007t.c @@ -196,7 +196,7 @@ static void copy_reg_bits(struct reg_pair_t *reg_pair1, i = j = 0; while (reg_pair1[i].reg || reg_pair1[i].val) { - while (reg_pair2[j].reg || reg_pair2[j].reg) { + while (reg_pair2[j].reg || reg_pair2[j].val) { if (reg_pair1[i].reg != reg_pair2[j].reg) { j++; continue; From 220d5b50cab3a384584f767075b02bdfc53c8c77 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 14 Dec 2009 17:57:34 -0800 Subject: [PATCH 080/670] bsdacct: fix uid/gid misreporting commit 4b731d50ff3df6b9141a6c12b088e8eb0109e83c upstream. commit d8e180dcd5bbbab9cd3ff2e779efcf70692ef541 "bsdacct: switch credentials for writing to the accounting file" introduced credential switching during final acct data collecting. However, uid/gid pair continued to be collected from current which became credentials of who created acct file, not who exits. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=14676 Signed-off-by: Alexey Dobriyan Reported-by: Juho K. Juopperi Acked-by: Serge Hallyn Acked-by: David Howells Reviewed-by: Michal Schmidt Cc: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/acct.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/acct.c b/kernel/acct.c index 9a4715a2f6bf..a6605ca921b6 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -536,7 +536,8 @@ static void do_acct_process(struct bsd_acct_struct *acct, do_div(elapsed, AHZ); ac.ac_btime = get_seconds() - elapsed; /* we really need to bite the bullet and change layout */ - current_uid_gid(&ac.ac_uid, &ac.ac_gid); + ac.ac_uid = orig_cred->uid; + ac.ac_gid = orig_cred->gid; #if ACCT_VERSION==2 ac.ac_ahz = AHZ; #endif From 943e167cb3e8fb191894bde8a4a75db78531a7c8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 29 Nov 2009 19:46:02 +0100 Subject: [PATCH 081/670] UBI: flush wl before clearing update marker commit 6afaf8a484cbbfd2ccf58a4e5396d1f280469789 upstream. ubiupdatevol -t does the following: - ubi_start_update() - set_update_marker() - for all LEBs ubi_eba_unmap_leb() - clear_update_marker() - ubi_wl_flush() ubi_wl_flush() physically erases all PEB, once it returns all PEBs are empty. clear_update_marker() has the update marker written after return. If there is a power cut between the last two functions then the UBI volume has no longer the "update" marker set and may have some valid LEBs while some of them may be gone. If that volume in question happens to be a UBIFS volume, then mount will fail with |UBIFS error (pid 1361): ubifs_read_node: bad node type (255 but expected 6) |UBIFS error (pid 1361): ubifs_read_node: bad node at LEB 0:0 |Not a node, first 24 bytes: |00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff if there is at least one valid LEB and the wear-leveling worker managed to clear LEB 0. The patch waits for the wl worker to finish prior clearing the "update" marker on flash. The two new LEB which are scheduled for erasing after clear_update_marker() should not matter because they are only visible to UBI. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/upd.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 74fdc40c8627..c1d7b880c795 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -147,12 +147,14 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, } if (bytes == 0) { + err = ubi_wl_flush(ubi); + if (err) + return err; + err = clear_update_marker(ubi, vol, 0); if (err) return err; - err = ubi_wl_flush(ubi); - if (!err) - vol->updating = 0; + vol->updating = 0; } vol->upd_buf = vmalloc(ubi->leb_size); @@ -362,16 +364,16 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, ubi_assert(vol->upd_received <= vol->upd_bytes); if (vol->upd_received == vol->upd_bytes) { + err = ubi_wl_flush(ubi); + if (err) + return err; /* The update is finished, clear the update marker */ err = clear_update_marker(ubi, vol, vol->upd_bytes); if (err) return err; - err = ubi_wl_flush(ubi); - if (err == 0) { - vol->updating = 0; - err = to_write; - vfree(vol->upd_buf); - } + vol->updating = 0; + err = to_write; + vfree(vol->upd_buf); } return err; From b71a005bac02d0f68ba2d93f47cd58afcd563149 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 15 Nov 2009 15:31:37 -0500 Subject: [PATCH 082/670] jbd2: don't wipe the journal on a failed journal checksum commit e6a47428de84e19fda52f21ab73fde2906c40d09 upstream. If there is a failed journal checksum, don't reset the journal. This allows for userspace programs to decide how to recover from this situation. It may be that ignoring the journal checksum failure might be a better way of recovering the file system. Once we add per-block checksums, we can definitely do better. Until then, a system administrator can try backing up the file system image (or taking a snapshot) and and trying to determine experimentally whether ignoring the checksum failure or aborting the journal replay results in less data loss. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/jbd2/journal.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 82c295d2a7c5..b7ca3a92a4db 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1253,6 +1253,13 @@ int jbd2_journal_load(journal_t *journal) if (jbd2_journal_recover(journal)) goto recovery_error; + if (journal->j_failed_commit) { + printk(KERN_ERR "JBD2: journal transaction %u on %s " + "is corrupt.\n", journal->j_failed_commit, + journal->j_devname); + return -EIO; + } + /* OK, we've finished with the dynamic journal bits: * reinitialise the dynamic contents of the superblock in memory * and reset them on disk. */ From 7f0d909acd1644a1eb313c7f67f17f9aa58c9ac6 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 1 Dec 2009 10:37:07 -0800 Subject: [PATCH 083/670] USB: xhci: Add correct email and files to MAINTAINERS entry. commit 36d0344c254a7b333272757f858c403ea3a2d29f upstream. Add the xHCI driver files to its MAINTAINERS entry so that I'm Cc'd on cleanup patches. Update the email address to one I actually use for sending patches and responding to Linux mailing list emails. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4f96ac81089c..c57d3964e00c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5594,9 +5594,11 @@ S: Maintained F: drivers/net/wireless/rndis_wlan.c USB XHCI DRIVER -M: Sarah Sharp +M: Sarah Sharp L: linux-usb@vger.kernel.org S: Supported +F: drivers/usb/host/xhci* +F: drivers/usb/host/pci-quirks* USB ZC0301 DRIVER M: Luca Risolia From d25997311e1bf8c338db97558666b7642919b820 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 16 Nov 2009 16:24:05 +0530 Subject: [PATCH 084/670] USB: musb_gadget_ep0: fix unhandled endpoint 0 IRQs, again commit 196f1b7a387546f425df2f1fad26772e3d513aea upstream. Commit a5073b52833e4df8e16c93dc4cbb7e0c558c74a2 (musb_gadget: fix unhandled endpoint 0 IRQs) somehow missed its key change: "The gadget EP0 code routinely ignores an interrupt at end of the data phase because of musb_g_ep0_giveback() resetting the state machine to "idle, waiting for SETUP" phase prematurely." So, the majority of the cases of unhandled IRQs is still unfixed... Signed-off-by: Sergei Shtylyov Signed-off-by: Anand Gadiyar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget_ep0.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 522efb31b56b..1c44b975049c 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -199,7 +199,6 @@ service_in_request(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req) { musb_g_giveback(&musb->endpoints[0].ep_in, req, 0); - musb->ep0_state = MUSB_EP0_STAGE_SETUP; } /* From fdc28ded337a4eab23e4326924686f127d7a9cf8 Mon Sep 17 00:00:00 2001 From: Zhang Le Date: Tue, 17 Nov 2009 14:53:42 -0800 Subject: [PATCH 085/670] USB: option.c: add support for D-Link DWM-162-U5 commit 54a8e144acad6506920f385f4ef2779664f05b21 upstream. Add D-Link DWM-162-U5 device id 1e0e:ce16 into option driver. The device has 4 interfaces, of which 1 is handled by storage and the other 3 by option driver. The device appears first as CD-only 05c6:2100 device and must be switched to 1e0e:ce16 mode either by using "eject CD" or usb_modeswitch. The MessageContent for usb_modeswitch.conf is: "55534243e0c26a85000000000000061b000000020000000000000000000000" Signed-off-by: Zhang Le Signed-off-by: Andrew Morton 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 3ea517e0fb4f..dffc8a1e84d7 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -635,6 +635,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) }, { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, + { USB_DEVICE(ALINK_VENDOR_ID, 0xce16) }, { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, From f4c0cf18d2b21dd614662c3b95ce0ffd0a4aa881 Mon Sep 17 00:00:00 2001 From: Andre Herms Date: Thu, 19 Nov 2009 18:14:49 +0100 Subject: [PATCH 086/670] USB: usbtmc: repeat usb_bulk_msg until whole message is transfered commit ec412b92dbe3ea839716853eea058d1bcc5e6ca4 upstream. usb_bulk_msg() transfers only bytes up to the maximum packet size. It must be repeated by the usbtmc driver until all bytes of a TMC message are transfered. Without this patch, ETIMEDOUT is reported when writing TMC messages larger than the maximum USB bulk size and the transfer remains incomplete. The user will notice that the device hangs and must be reset by either closing the application or pulling the plug. Signed-off-by: Andre Herms Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 2473cf0c6b1d..d9461c91b8c9 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -562,10 +562,16 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, n_bytes = roundup(12 + this_part, 4); memset(buffer + 12 + this_part, 0, n_bytes - (12 + this_part)); - retval = usb_bulk_msg(data->usb_dev, - usb_sndbulkpipe(data->usb_dev, - data->bulk_out), - buffer, n_bytes, &actual, USBTMC_TIMEOUT); + do { + retval = usb_bulk_msg(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, + data->bulk_out), + buffer, n_bytes, + &actual, USBTMC_TIMEOUT); + if (retval != 0) + break; + n_bytes -= actual; + } while (n_bytes); data->bTag_last_write = data->bTag; data->bTag++; From 3d5536bccf57b761f41f0ac1d7453e9997b4fdbf Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 7 Dec 2009 16:39:16 -0500 Subject: [PATCH 087/670] USB: usb-storage: add BAD_SENSE flag commit a0bb108112a872c0b0c4b3ef4974f95fb75b155d upstream. This patch (as1311) fixes a problem in usb-storage: Some devices are pretty broken when it comes to reporting sense data. The information they send back indicates that they have more than 18 bytes of sense data available, but when the system asks for more than 18 they fail or hang. The symptom is that probing fails with multiple resets. The patch adds a new BAD_SENSE flag to indicate that usb-storage should never ask for more than 18 bytes of sense data. The flag can be set in an unusual_devs entry or via the "quirks=" module parameter, and it is set automatically whenever a REQUEST SENSE command for more than 18 bytes fails or times out. An unusual_devs entry is added for the Agfa photo frame, which uses a Prolific chip having this bug. Signed-off-by: Alan Stern Tested-by: Daniel Kukula Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 2 ++ drivers/usb/storage/transport.c | 17 +++++++++++++---- drivers/usb/storage/unusual_devs.h | 7 +++++++ drivers/usb/storage/usb.c | 3 +++ include/linux/usb_usual.h | 4 +++- 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 9107b387e91f..5bc4eaaa5b7f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2645,6 +2645,8 @@ and is between 256 and 4096 characters. It is defined in the file to a common usb-storage quirk flag as follows: a = SANE_SENSE (collect more than 18 bytes of sense data); + b = BAD_SENSE (don't collect more than 18 + bytes of sense data); c = FIX_CAPACITY (decrease the reported device capacity by one sector); h = CAPACITY_HEURISTICS (decrease the diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 589f6b4404f0..cc313d16d727 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -666,10 +666,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) * to wait for at least one CHECK_CONDITION to determine * SANE_SENSE support */ - if ((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && + if (unlikely((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && result == USB_STOR_TRANSPORT_GOOD && !(us->fflags & US_FL_SANE_SENSE) && - !(srb->cmnd[2] & 0x20)) { + !(us->fflags & US_FL_BAD_SENSE) && + !(srb->cmnd[2] & 0x20))) { US_DEBUGP("-- SAT supported, increasing auto-sense\n"); us->fflags |= US_FL_SANE_SENSE; } @@ -718,6 +719,12 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- auto-sense aborted\n"); srb->result = DID_ABORT << 16; + + /* If SANE_SENSE caused this problem, disable it */ + if (sense_size != US_SENSE_SIZE) { + us->fflags &= ~US_FL_SANE_SENSE; + us->fflags |= US_FL_BAD_SENSE; + } goto Handle_Errors; } @@ -727,10 +734,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) * (small) sense request. This fixes some USB GSM modems */ if (temp_result == USB_STOR_TRANSPORT_FAILED && - (us->fflags & US_FL_SANE_SENSE) && - sense_size != US_SENSE_SIZE) { + sense_size != US_SENSE_SIZE) { US_DEBUGP("-- auto-sense failure, retry small sense\n"); sense_size = US_SENSE_SIZE; + us->fflags &= ~US_FL_SANE_SENSE; + us->fflags |= US_FL_BAD_SENSE; goto Retry_Sense; } @@ -754,6 +762,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) */ if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) && !(us->fflags & US_FL_SANE_SENSE) && + !(us->fflags & US_FL_BAD_SENSE) && (srb->sense_buffer[0] & 0x7C) == 0x70) { US_DEBUGP("-- SANE_SENSE support enabled\n"); us->fflags |= US_FL_SANE_SENSE; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d4f034ebaa8a..64a0a2c27e12 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -818,6 +818,13 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Daniel Kukula */ +UNUSUAL_DEV( 0x067b, 0x1063, 0x0100, 0x0100, + "Prolific Technology, Inc.", + "Prolific Storage Gadget", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_BAD_SENSE ), + /* Reported by Rogerio Brito */ UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001, "Prolific Technology, Inc.", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 11876c3b9000..716c8d7885fa 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -460,6 +460,9 @@ static void adjust_quirks(struct us_data *us) case 'a': f |= US_FL_SANE_SENSE; break; + case 'b': + f |= US_FL_BAD_SENSE; + break; case 'c': f |= US_FL_FIX_CAPACITY; break; diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index 3d15fb9bc116..a4b947e470a5 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -56,7 +56,9 @@ US_FLAG(SANE_SENSE, 0x00008000) \ /* Sane Sense (> 18 bytes) */ \ US_FLAG(CAPACITY_OK, 0x00010000) \ - /* READ CAPACITY response is correct */ + /* READ CAPACITY response is correct */ \ + US_FLAG(BAD_SENSE, 0x00020000) \ + /* Bad Sense (never more than 18 bytes) */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; From 61039163321943e3279b89f18e7662e5e596c3d9 Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Mon, 14 Dec 2009 21:45:35 -0700 Subject: [PATCH 088/670] USB: Close usb_find_interface race v3 commit c2d284ee04ab6f6718de2ddcf1b43160e046c41d upstream. USB drivers that create character devices call usb_register_dev in their probe function. This associates the usb_interface device with that minor number and creates the character device and announces it to the world. However, the driver's probe function is called before the new usb_interface is added to the driver's klist_devices. This is a problem because userspace will respond to the character device creation announcement by opening the character device. The driver's open function will the call usb_find_interface to find the usb_interface associated with that minor number. usb_find_interface will walk the driver's list of devices and find the usb_interface with the matching minor number. Because the announcement happens before the usb_interface is added to the driver's klist_devices, a race condition exists. A straightforward fix is to walk the list of devices on usb_bus_type instead since the device is added to that list before the announcement occurs. bus_find_device calls get_device to bump the reference count on the found device. It is arguable that the reference count should be dropped by the caller of usb_find_interface instead of usb_find_interface, however, the current users of usb_find_interface do not expect this. The original version of this patch only matched against minor number instead of driver and minor number. This version matches against both. Signed-off-by: Russ Dill Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/usb.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b1b85abb9a2d..52e5e31cdea7 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -132,7 +132,7 @@ EXPORT_SYMBOL_GPL(usb_altnum_to_altsetting); struct find_interface_arg { int minor; - struct usb_interface *interface; + struct device_driver *drv; }; static int __find_interface(struct device *dev, void *data) @@ -143,12 +143,10 @@ static int __find_interface(struct device *dev, void *data) if (!is_usb_interface(dev)) return 0; + if (dev->driver != arg->drv) + return 0; intf = to_usb_interface(dev); - if (intf->minor != -1 && intf->minor == arg->minor) { - arg->interface = intf; - return 1; - } - return 0; + return intf->minor == arg->minor; } /** @@ -156,21 +154,24 @@ static int __find_interface(struct device *dev, void *data) * @drv: the driver whose current configuration is considered * @minor: the minor number of the desired device * - * This walks the driver device list and returns a pointer to the interface - * with the matching minor. Note, this only works for devices that share the - * USB major number. + * This walks the bus device list and returns a pointer to the interface + * with the matching minor and driver. Note, this only works for devices + * that share the USB major number. */ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { struct find_interface_arg argb; - int retval; + struct device *dev; argb.minor = minor; - argb.interface = NULL; - /* eat the error, it will be in argb.interface */ - retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb, - __find_interface); - return argb.interface; + argb.drv = &drv->drvwrap.driver; + + dev = bus_find_device(&usb_bus_type, NULL, &argb, __find_interface); + + /* Drop reference count from bus_find_device */ + put_device(dev); + + return dev ? to_usb_interface(dev) : NULL; } EXPORT_SYMBOL_GPL(usb_find_interface); From 08d05bad84c4cc91a92ac9aa8c3106610cc0584b Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Sun, 6 Dec 2009 15:45:43 +0200 Subject: [PATCH 089/670] pxa/em-x270: fix usb hub power up/reset sequence commit 1b82e4c32fba96d8805b1e2126ba5382e56fac32 upstream. Signed-off-by: Igor Grinberg Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-pxa/em-x270.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index aec7f4214b14..86a87327ad42 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -497,16 +497,15 @@ static int em_x270_usb_hub_init(void) goto err_free_vbus_gpio; /* USB Hub power-on and reset */ - gpio_direction_output(usb_hub_reset, 0); + gpio_direction_output(usb_hub_reset, 1); + gpio_direction_output(GPIO9_USB_VBUS_EN, 0); regulator_enable(em_x270_usb_ldo); - gpio_set_value(usb_hub_reset, 1); gpio_set_value(usb_hub_reset, 0); + gpio_set_value(usb_hub_reset, 1); regulator_disable(em_x270_usb_ldo); regulator_enable(em_x270_usb_ldo); - gpio_set_value(usb_hub_reset, 1); - - /* enable VBUS */ - gpio_direction_output(GPIO9_USB_VBUS_EN, 1); + gpio_set_value(usb_hub_reset, 0); + gpio_set_value(GPIO9_USB_VBUS_EN, 1); return 0; From 037b7867ec53baa0dea5d05d4201e4fbf2405fc3 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Mon, 14 Dec 2009 17:57:37 -0800 Subject: [PATCH 090/670] hfs: fix a potential buffer overflow commit ec81aecb29668ad71f699f4e7b96ec46691895b6 upstream. A specially-crafted Hierarchical File System (HFS) filesystem could cause a buffer overflow to occur in a process's kernel stack during a memcpy() call within the hfs_bnode_read() function (at fs/hfs/bnode.c:24). The attacker can provide the source buffer and length, and the destination buffer is a local variable of a fixed length. This local variable (passed as "&entry" from fs/hfs/dir.c:112 and allocated on line 60) is stored in the stack frame of hfs_bnode_read()'s caller, which is hfs_readdir(). Because the hfs_readdir() function executes upon any attempt to read a directory on the filesystem, it gets called whenever a user attempts to inspect any filesystem contents. [amwang@redhat.com: modify this patch and fix coding style problems] Signed-off-by: WANG Cong Cc: Eugene Teo Cc: Roman Zippel Cc: Al Viro Cc: Christoph Hellwig Cc: Alexey Dobriyan Cc: Dave Anderson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/hfs/catalog.c | 4 ++++ fs/hfs/dir.c | 11 +++++++++++ fs/hfs/super.c | 7 ++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c index 6d98f116ca03..424b0337f524 100644 --- a/fs/hfs/catalog.c +++ b/fs/hfs/catalog.c @@ -289,6 +289,10 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name, err = hfs_brec_find(&src_fd); if (err) goto out; + if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) { + err = -EIO; + goto out; + } hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, src_fd.entrylength); diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index 7c69b98a2e45..2b3b8611b41b 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c @@ -79,6 +79,11 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) filp->f_pos++; /* fall through */ case 1: + if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { + err = -EIO; + goto out; + } + hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); if (entry.type != HFS_CDR_THD) { printk(KERN_ERR "hfs: bad catalog folder thread\n"); @@ -109,6 +114,12 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) err = -EIO; goto out; } + + if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { + err = -EIO; + goto out; + } + hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); type = entry.type; len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName); diff --git a/fs/hfs/super.c b/fs/hfs/super.c index f7fcbe49da72..5ed7252b7b23 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -409,8 +409,13 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) /* try to get the root inode */ hfs_find_init(HFS_SB(sb)->cat_tree, &fd); res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd); - if (!res) + if (!res) { + if (fd.entrylength > sizeof(rec) || fd.entrylength < 0) { + res = -EIO; + goto bail; + } hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength); + } if (res) { hfs_find_exit(&fd); goto bail_no_root; From b9058d460800ee672e90d09f7419117baa64f045 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 8 Dec 2009 13:13:03 -0500 Subject: [PATCH 091/670] SUNRPC: IS_ERR/PTR_ERR confusion commit 480e3243df156e39eea6c91057e2ae612a6bbe19 upstream. IS_ERR returns 1 or 0, PTR_ERR returns the error value. Signed-off-by: Roel Kluin Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/auth_gss/auth_gss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index fc6a43ccd950..129d75ea25d2 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -485,7 +485,7 @@ gss_refresh_upcall(struct rpc_task *task) dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, cred->cr_uid); gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); - if (IS_ERR(gss_msg) == -EAGAIN) { + if (PTR_ERR(gss_msg) == -EAGAIN) { /* XXX: warning on the first, under the assumption we * shouldn't normally hit this case on a refresh. */ warn_gssd(); From e4f676cea796e170fcd8561c8e2a234724d05f35 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 10 Dec 2009 09:05:55 -0500 Subject: [PATCH 092/670] NFS: Fix nfs_migrate_page() commit 190f38e5cedc910940b1da9015f00458c18f97b4 upstream. The call to migrate_page() will cause the page->private field to be cleared. Also fix up the locking around the page->private transfer, so that we ensure that calls to nfs_page_find_request() don't end up racing. Finally, fix up a double free bug: nfs_unlock_request() already calls nfs_release_request() for us... Reported-by: Wu Fengguang Tested-by: Andi Kleen Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/write.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 53eb26c16b50..6fc37762c495 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1612,15 +1612,16 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage, if (ret) goto out_unlock; page_cache_get(newpage); + spin_lock(&mapping->host->i_lock); req->wb_page = newpage; SetPagePrivate(newpage); - set_page_private(newpage, page_private(page)); + set_page_private(newpage, (unsigned long)req); ClearPagePrivate(page); set_page_private(page, 0); + spin_unlock(&mapping->host->i_lock); page_cache_release(page); out_unlock: nfs_clear_page_tag_locked(req); - nfs_release_request(req); out: return ret; } From f1416ea0278b4bb6629d160e81e61ef8b6bffb4a Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 14 Dec 2009 12:49:46 +1100 Subject: [PATCH 093/670] md/bitmap: protect against bitmap removal while being updated. commit aa5cbd103887011b4830355f88fb055f9ad2d556 upstream. A write intent bitmap can be removed from an array while the array is active. When this happens, all IO is suspended and flushed before the bitmap is removed. However it is possible that bitmap_daemon_work is still running to clear old bits from the bitmap. If it is, it can dereference the bitmap after it has been freed. So introduce a new mutex to protect bitmap_daemon_work and get it before destroying a bitmap. This is suitable for any current -stable kernel. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/bitmap.c | 24 ++++++++++++++++++------ drivers/md/bitmap.h | 2 +- drivers/md/md.c | 3 ++- drivers/md/md.h | 1 + 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 60e2b322db11..a5e5f2fbf963 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1078,23 +1078,31 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, * out to disk */ -void bitmap_daemon_work(struct bitmap *bitmap) +void bitmap_daemon_work(mddev_t *mddev) { + struct bitmap *bitmap; unsigned long j; unsigned long flags; struct page *page = NULL, *lastpage = NULL; int blocks; void *paddr; - if (bitmap == NULL) + /* Use a mutex to guard daemon_work against + * bitmap_destroy. + */ + mutex_lock(&mddev->bitmap_mutex); + bitmap = mddev->bitmap; + if (bitmap == NULL) { + mutex_unlock(&mddev->bitmap_mutex); return; + } if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ)) goto done; bitmap->daemon_lastrun = jiffies; if (bitmap->allclean) { bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; - return; + goto done; } bitmap->allclean = 1; @@ -1203,6 +1211,7 @@ void bitmap_daemon_work(struct bitmap *bitmap) done: if (bitmap->allclean == 0) bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ; + mutex_unlock(&mddev->bitmap_mutex); } static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, @@ -1541,9 +1550,9 @@ void bitmap_flush(mddev_t *mddev) */ sleep = bitmap->daemon_sleep; bitmap->daemon_sleep = 0; - bitmap_daemon_work(bitmap); - bitmap_daemon_work(bitmap); - bitmap_daemon_work(bitmap); + bitmap_daemon_work(mddev); + bitmap_daemon_work(mddev); + bitmap_daemon_work(mddev); bitmap->daemon_sleep = sleep; bitmap_update_sb(bitmap); } @@ -1574,6 +1583,7 @@ static void bitmap_free(struct bitmap *bitmap) kfree(bp); kfree(bitmap); } + void bitmap_destroy(mddev_t *mddev) { struct bitmap *bitmap = mddev->bitmap; @@ -1581,7 +1591,9 @@ void bitmap_destroy(mddev_t *mddev) if (!bitmap) /* there was no bitmap */ return; + mutex_lock(&mddev->bitmap_mutex); mddev->bitmap = NULL; /* disconnect from the md device */ + mutex_unlock(&mddev->bitmap_mutex); if (mddev->thread) mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h index e98900671ca9..7e38d13ddcac 100644 --- a/drivers/md/bitmap.h +++ b/drivers/md/bitmap.h @@ -282,7 +282,7 @@ void bitmap_close_sync(struct bitmap *bitmap); void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector); void bitmap_unplug(struct bitmap *bitmap); -void bitmap_daemon_work(struct bitmap *bitmap); +void bitmap_daemon_work(mddev_t *mddev); #endif #endif diff --git a/drivers/md/md.c b/drivers/md/md.c index b182f86a19dd..02e45513789b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -367,6 +367,7 @@ static mddev_t * mddev_find(dev_t unit) mutex_init(&new->open_mutex); mutex_init(&new->reconfig_mutex); + mutex_init(&new->bitmap_mutex); INIT_LIST_HEAD(&new->disks); INIT_LIST_HEAD(&new->all_mddevs); init_timer(&new->safemode_timer); @@ -6629,7 +6630,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev->bitmap) - bitmap_daemon_work(mddev->bitmap); + bitmap_daemon_work(mddev); if (mddev->ro) return; diff --git a/drivers/md/md.h b/drivers/md/md.h index f184b69ef337..87430fea2875 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -289,6 +289,7 @@ struct mddev_s * hot-adding a bitmap. It should * eventually be settable by sysfs. */ + struct mutex bitmap_mutex; struct list_head all_mddevs; }; From bb2fb5d6a16840cf98af1a5d405a583c200d87a8 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 8 Dec 2009 13:19:42 +0100 Subject: [PATCH 094/670] futex: Take mmap_sem for get_user_pages in fault_in_user_writeable commit 722d0172377a5697919b9f7e5beb95165b1dec4e upstream. get_user_pages() must be called with mmap_sem held. Signed-off-by: Andi Kleen Cc: Andrew Morton Cc: Nick Piggin Cc: Darren Hart Cc: Peter Zijlstra LKML-Reference: <20091208121942.GA21298@basil.fritz.box> Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index fb65e822fc41..d73ef1f3e55d 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -304,8 +304,14 @@ void put_futex_key(int fshared, union futex_key *key) */ static int fault_in_user_writeable(u32 __user *uaddr) { - int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, - 1, 1, 0, NULL, NULL); + struct mm_struct *mm = current->mm; + int ret; + + down_read(&mm->mmap_sem); + ret = get_user_pages(current, mm, (unsigned long)uaddr, + 1, 1, 0, NULL, NULL); + up_read(&mm->mmap_sem); + return ret < 0 ? ret : 0; } From 5451f13711a2af1fffdfe0d1e2faf02449fdab28 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Tue, 17 Nov 2009 18:35:43 -0800 Subject: [PATCH 095/670] devpts_get_tty() should validate inode commit edfacdd6f81119b9005615593f2cbd94b8c7e2d8 upstream. devpts_get_tty() assumes that the inode passed in is associated with a valid pty. But if the only reference to the pty is via a bind-mount, the inode passed to devpts_get_tty() while valid, would refer to a pty that no longer exists. With a lot of debug effort, Grzegorz Nosek developed a small program (see below) to reproduce a crash on recent kernels. This crash is a regression introduced by the commit: commit 527b3e4773628b30d03323a2cb5fb0d84441990f Author: Sukadev Bhattiprolu Date: Mon Oct 13 10:43:08 2008 +0100 To fix, ensure that the dentry associated with the inode has not yet been deleted/unhashed by devpts_pty_kill(). See also: https://lists.linux-foundation.org/pipermail/containers/2009-July/019273.html tty-bug.c: #define _GNU_SOURCE #include #include #include #include #include #include #include #include void dummy(int sig) { } static int child(void *unused) { int fd; signal(SIGINT, dummy); signal(SIGHUP, dummy); pause(); /* cheesy synchronisation to wait for /dev/pts/0 to appear */ mount("/dev/pts/0", "/dev/console", NULL, MS_BIND, NULL); sleep(2); fd = open("/dev/console", O_RDWR); dup(0); dup(0); write(1, "Hello world!\n", sizeof("Hello world!\n")-1); return 0; } int main(void) { pid_t pid; char *stack; stack = malloc(16384); pid = clone(child, stack+16384, CLONE_NEWNS|SIGCHLD, NULL); open("/dev/ptmx", O_RDWR|O_NOCTTY|O_NONBLOCK); unlockpt(fd); grantpt(fd); sleep(2); kill(pid, SIGHUP); sleep(1); return 0; /* exit before child opens /dev/console */ } Reported-by: Grzegorz Nosek Signed-off-by: Sukadev Bhattiprolu Tested-by: Serge Hallyn Signed-off-by: Greg Kroah-Hartman --- fs/devpts/inode.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index d5f8c96964be..8882ecc0f1bf 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -517,11 +517,23 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) { + struct dentry *dentry; + struct tty_struct *tty; + BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); + /* Ensure dentry has not been deleted by devpts_pty_kill() */ + dentry = d_find_alias(pts_inode); + if (!dentry) + return NULL; + + tty = NULL; if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) - return (struct tty_struct *)pts_inode->i_private; - return NULL; + tty = (struct tty_struct *)pts_inode->i_private; + + dput(dentry); + + return tty; } void devpts_pty_kill(struct tty_struct *tty) From 9f2813ec1f4868d07d8a16f4a9c4932819fc5d8e Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 17 Nov 2009 14:40:26 -0800 Subject: [PATCH 096/670] debugfs: fix create mutex racy fops and private data commit d3a3b0adad0865c12e39b712ca89efbd0a3a0dbc upstream. Setting fops and private data outside of the mutex at debugfs file creation introduces a race where the files can be opened with the wrong file operations and private data. It is easy to trigger with a process waiting on file creation notification. Signed-off-by: Mathieu Desnoyers Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/inode.c | 55 +++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index d22438ef7674..39c6ee868d7b 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -32,7 +32,9 @@ static struct vfsmount *debugfs_mount; static int debugfs_mount_count; static bool debugfs_registered; -static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev) +static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev, + void *data, const struct file_operations *fops) + { struct inode *inode = new_inode(sb); @@ -44,14 +46,18 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d init_special_inode(inode, mode, dev); break; case S_IFREG: - inode->i_fop = &debugfs_file_operations; + inode->i_fop = fops ? fops : &debugfs_file_operations; + inode->i_private = data; break; case S_IFLNK: inode->i_op = &debugfs_link_operations; + inode->i_fop = fops; + inode->i_private = data; break; case S_IFDIR: inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; + inode->i_fop = fops ? fops : &simple_dir_operations; + inode->i_private = data; /* directory inodes start off with i_nlink == 2 * (for "." entry) */ @@ -64,7 +70,8 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d /* SMP-safe */ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, - int mode, dev_t dev) + int mode, dev_t dev, void *data, + const struct file_operations *fops) { struct inode *inode; int error = -EPERM; @@ -72,7 +79,7 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, if (dentry->d_inode) return -EEXIST; - inode = debugfs_get_inode(dir->i_sb, mode, dev); + inode = debugfs_get_inode(dir->i_sb, mode, dev, data, fops); if (inode) { d_instantiate(dentry, inode); dget(dentry); @@ -81,12 +88,13 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, return error; } -static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode, + void *data, const struct file_operations *fops) { int res; mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; - res = debugfs_mknod(dir, dentry, mode, 0); + res = debugfs_mknod(dir, dentry, mode, 0, data, fops); if (!res) { inc_nlink(dir); fsnotify_mkdir(dir, dentry); @@ -94,18 +102,20 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) return res; } -static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode) +static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode, + void *data, const struct file_operations *fops) { mode = (mode & S_IALLUGO) | S_IFLNK; - return debugfs_mknod(dir, dentry, mode, 0); + return debugfs_mknod(dir, dentry, mode, 0, data, fops); } -static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) +static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode, + void *data, const struct file_operations *fops) { int res; mode = (mode & S_IALLUGO) | S_IFREG; - res = debugfs_mknod(dir, dentry, mode, 0); + res = debugfs_mknod(dir, dentry, mode, 0, data, fops); if (!res) fsnotify_create(dir, dentry); return res; @@ -139,7 +149,9 @@ static struct file_system_type debug_fs_type = { static int debugfs_create_by_name(const char *name, mode_t mode, struct dentry *parent, - struct dentry **dentry) + struct dentry **dentry, + void *data, + const struct file_operations *fops) { int error = 0; @@ -164,13 +176,16 @@ static int debugfs_create_by_name(const char *name, mode_t mode, if (!IS_ERR(*dentry)) { switch (mode & S_IFMT) { case S_IFDIR: - error = debugfs_mkdir(parent->d_inode, *dentry, mode); + error = debugfs_mkdir(parent->d_inode, *dentry, mode, + data, fops); break; case S_IFLNK: - error = debugfs_link(parent->d_inode, *dentry, mode); + error = debugfs_link(parent->d_inode, *dentry, mode, + data, fops); break; default: - error = debugfs_create(parent->d_inode, *dentry, mode); + error = debugfs_create(parent->d_inode, *dentry, mode, + data, fops); break; } dput(*dentry); @@ -221,19 +236,13 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode, if (error) goto exit; - error = debugfs_create_by_name(name, mode, parent, &dentry); + error = debugfs_create_by_name(name, mode, parent, &dentry, + data, fops); if (error) { dentry = NULL; simple_release_fs(&debugfs_mount, &debugfs_mount_count); goto exit; } - - if (dentry->d_inode) { - if (data) - dentry->d_inode->i_private = data; - if (fops) - dentry->d_inode->i_fop = fops; - } exit: return dentry; } From fa8e26457e28606446f9afd6566cead9d0418b73 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 4 Dec 2009 11:06:57 -0500 Subject: [PATCH 097/670] Driver core: fix race in dev_driver_string commit 3589972e51fac1e02d0aaa576fa47f568cb94d40 upstream. This patch (as1310) works around a race in dev_driver_string(). If the device is unbound while the function is running, dev->driver might become NULL after we test it and before we dereference it. Signed-off-by: Alan Stern Cc: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 6bee6af8d8e1..109317948d5d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -56,7 +56,14 @@ static inline int device_is_not_partition(struct device *dev) */ const char *dev_driver_string(const struct device *dev) { - return dev->driver ? dev->driver->name : + struct device_driver *drv; + + /* dev->driver can change to NULL underneath us because of unbinding, + * so be careful about accessing it. dev->bus and dev->class should + * never change once they are set, so they don't need special care. + */ + drv = ACCESS_ONCE(dev->driver); + return drv ? drv->name : (dev->bus ? dev->bus->name : (dev->class ? dev->class->name : "")); } From a4b8b8eb2533da448fcaaef2467a1cc4489057b9 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 18 Nov 2009 11:08:11 +0100 Subject: [PATCH 098/670] Serial: Do not read IIR in serial8250_start_tx when UART_BUG_TXEN commit 68cb4f8e246bbbc649980be0628cae9265870a91 upstream. Do not read IIR in serial8250_start_tx when UART_BUG_TXEN Reading the IIR clears some oustanding interrupts so it is not safe. Instead, simply transmit immediately if the buffer is empty without regard to IIR. Signed-off-by: Ian Jackson Reviewed-by: Markus Armbruster Reviewed-by: Jiri Kosina Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 737b4c960971..807042b14882 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1339,14 +1339,12 @@ static void serial8250_start_tx(struct uart_port *port) serial_out(up, UART_IER, up->ier); if (up->bugs & UART_BUG_TXEN) { - unsigned char lsr, iir; + unsigned char lsr; lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - iir = serial_in(up, UART_IIR) & 0x0f; if ((up->port.type == PORT_RM9000) ? - (lsr & UART_LSR_THRE && - (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) : - (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)) + (lsr & UART_LSR_THRE) : + (lsr & UART_LSR_TEMT)) transmit_chars(up); } } From fb0f7048cfa072125c98dc11884a96d1e03c0f9a Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 4 Dec 2009 17:41:34 +0530 Subject: [PATCH 099/670] mac80211: Fix bug in computing crc over dynamic IEs in beacon commit 1814077fd12a9cdf478c10076e9c42094e9d9250 upstream. On a 32-bit machine, BIT() macro does not give the required bit value if the bit is mroe than 31. In ieee802_11_parse_elems_crc(), BIT() is suppossed to get the bit value more than 31 (42 (id of ERP_INFO_IE), 37 (CHANNEL_SWITCH_IE), (42), 32 (POWER_CONSTRAINT_IE), 45 (HT_CAP_IE), 61 (HT_INFO_IE)). As we do not get the required bit value for the above IEs, crc over these IEs are never calculated, so any dynamic change in these IEs after the association is not really handled on 32-bit platforms. This patch fixes this issue. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e6c08da8da26..cbc5d2057dbf 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -579,7 +579,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, if (elen > left) break; - if (calc_crc && id < 64 && (filter & BIT(id))) + if (calc_crc && id < 64 && (filter & (1ULL << id))) crc = crc32_be(crc, pos - 2, elen + 2); switch (id) { From dde24b6c58b10e27c296f2d343e9512ec0dce874 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Wed, 9 Dec 2009 18:43:00 -0800 Subject: [PATCH 100/670] mac80211: Fixed bug in mesh portal paths commit 5d618cb81aeea19879975cd1f9a1e707694dfd7c upstream. Paths to mesh portals were being timed out immediately after each use in intermediate forwarding nodes. mppath->exp_time is set to the expiration time so assigning it to jiffies was marking the path as expired. Signed-off-by: Javier Cardona Signed-off-by: Andrey Yurovsky Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/rx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7170bf4565a8..4e14754373a4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1514,7 +1514,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); } else { spin_lock_bh(&mppath->state_lock); - mppath->exp_time = jiffies; if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); spin_unlock_bh(&mppath->state_lock); From c04c99abc6754fa92d428915ac4215994fe95609 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Wed, 9 Dec 2009 18:43:01 -0800 Subject: [PATCH 101/670] mac80211: Revert 'Use correct sign for mesh active path refresh' commit 7b324d28a94dac5a451e8cba66e8d324601e5b9a upstream. The patch ("mac80211: Use correct sign for mesh active path refresh.") was actually a bug. Reverted it and improved the explanation of how mesh path refresh works. Signed-off-by: Javier Cardona Signed-off-by: Andrey Yurovsky Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mesh.h | 5 +++-- net/mac80211/mesh_hwmp.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index dd1c19319f0a..010ff2fc47f8 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -186,8 +186,9 @@ struct mesh_rmc { */ #define MESH_PREQ_MIN_INT 10 #define MESH_DIAM_TRAVERSAL_TIME 50 -/* Paths will be refreshed if they are closer than PATH_REFRESH_TIME to their - * expiration +/* A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds before + * timing out. This way it will remain ACTIVE and no data frames will be + * unnecesarily held in the pending queue. */ #define MESH_PATH_REFRESH_TIME 1000 #define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 29b82e98effa..93c49fc8913d 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -813,7 +813,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, } if (mpath->flags & MESH_PATH_ACTIVE) { - if (time_after(jiffies, mpath->exp_time + + if (time_after(jiffies, mpath->exp_time - msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && !memcmp(sdata->dev->dev_addr, hdr->addr4, ETH_ALEN) From 22731c4b03371594e3bfdf032a64ee3cc6e61365 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 31 Oct 2009 07:44:08 +0100 Subject: [PATCH 102/670] mac80211: fix scan abort sanity checks commit 6d3560d4fc9c5b9fe1a07a63926ea70512c69c32 upstream. Since sometimes mac80211 queues up a scan request to only act on it later, it must be allowed to (internally) cancel a not-yet-running scan, e.g. when the interface is taken down. This condition was missing since we always checked only the local->scanning variable which isn't yet set in that situation. Reported-by: Luis R. Rodriguez Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/scan.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 71e10cabf811..736537fc03dd 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -264,10 +264,14 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) mutex_lock(&local->scan_mtx); - if (WARN_ON(!local->scanning)) { - mutex_unlock(&local->scan_mtx); - return; - } + /* + * It's ok to abort a not-yet-running scan (that + * we have one at all will be verified by checking + * local->scan_req next), but not to complete it + * successfully. + */ + if (WARN_ON(!local->scanning && !aborted)) + aborted = true; if (WARN_ON(!local->scan_req)) { mutex_unlock(&local->scan_mtx); From 8cf6359fa10996157bd8030b572ac6050dff2580 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 8 Dec 2009 17:10:13 -0500 Subject: [PATCH 103/670] wireless: correctly report signal value for IEEE80211_HW_SIGNAL_UNSPEC commit 19deffbeba930030cfaf000b920333c6ba99ad52 upstream. This part was missed in "cfg80211: implement get_wireless_stats", probably because sta_set_sinfo already existed and was only handling dBm signals. Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/cfg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 7b5131bd6fa1..cca675e25363 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -338,7 +338,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->rx_packets = sta->rx_packets; sinfo->tx_packets = sta->tx_packets; - if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { + if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || + (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { sinfo->filled |= STATION_INFO_SIGNAL; sinfo->signal = (s8)sta->last_signal; } From 7fd943643cc5aef6546ca3d8914e01d4298ee769 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 5 Dec 2009 19:25:22 -0600 Subject: [PATCH 104/670] rtl8187: Fix wrong rfkill switch mask for some models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 70d57139f932b9ca21026253d02af71cf53d764a upstream. There are different bits used to convey the setting of the rfkill switch to the driver. The current driver only supports one of these possibilities. These changes were derived from the latest version of the vendor driver. This patch fixes the regression noted in kernel Bugzilla #14743. Signed-off-by: Larry Finger Reported-and-tested-by: Antti Kaijanmäki Tested-by: Hin-Tak Leung Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtl818x/rtl8187.h | 5 +++++ drivers/net/wireless/rtl818x/rtl8187_dev.c | 12 ++++++++++-- drivers/net/wireless/rtl818x/rtl8187_rfkill.c | 4 ++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index bf9175a8c1f4..99406bf381ca 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h @@ -23,6 +23,7 @@ #define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */ #define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */ #define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */ +#define RTL8187_EEPROM_SELECT_GPIO 0x3B #define RTL8187_REQT_READ 0xC0 #define RTL8187_REQT_WRITE 0x40 @@ -31,6 +32,9 @@ #define RTL8187_MAX_RX 0x9C4 +#define RFKILL_MASK_8187_89_97 0x2 +#define RFKILL_MASK_8198 0x4 + struct rtl8187_rx_info { struct urb *urb; struct ieee80211_hw *dev; @@ -123,6 +127,7 @@ struct rtl8187_priv { u8 noise; u8 slot_time; u8 aifsn[4]; + u8 rfkill_mask; struct { __le64 buf; struct sk_buff_head queue; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 2017ccc00145..ea49918a63de 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1329,6 +1329,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, struct ieee80211_channel *channel; const char *chip_name; u16 txpwr, reg; + u16 product_id = le16_to_cpu(udev->descriptor.idProduct); int err, i; dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); @@ -1488,6 +1489,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr & 0xFF; (*channel++).hw_value = txpwr >> 8; } + /* Handle the differing rfkill GPIO bit in different models */ + priv->rfkill_mask = RFKILL_MASK_8187_89_97; + if (product_id == 0x8197 || product_id == 0x8198) { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, ®); + if (reg & 0xFF00) + priv->rfkill_mask = RFKILL_MASK_8198; + } /* * XXX: Once this driver supports anything that requires @@ -1516,9 +1524,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, mutex_init(&priv->conf_mutex); skb_queue_head_init(&priv->b_tx_status.queue); - printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n", + printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n", wiphy_name(dev->wiphy), dev->wiphy->perm_addr, - chip_name, priv->asic_rev, priv->rf->name); + chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask); #ifdef CONFIG_RTL8187_LEDS eeprom_93cx6_read(&eeprom, 0x3F, ®); diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c index cad8037ab2af..03555e1e0cab 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c @@ -25,10 +25,10 @@ static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv) u8 gpio; gpio = rtl818x_ioread8(priv, &priv->map->GPIO0); - rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~0x02); + rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask); gpio = rtl818x_ioread8(priv, &priv->map->GPIO1); - return gpio & 0x02; + return gpio & priv->rfkill_mask; } void rtl8187_rfkill_init(struct ieee80211_hw *hw) From b3e1b060b2a4079723332d9d98a5891d670b9f8e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Dec 2009 12:59:46 +0100 Subject: [PATCH 105/670] x86: Fix bogus warning in apic_noop.apic_write() commit a946d8f11f0da9cfc714248036fcfd3a794d1e27 upstream. apic_noop is used to provide dummy apic functions. It's installed when the CPU has no APIC or when the APIC is disabled on the kernel command line. The apic_noop implementation of apic_write() warns when the CPU has an APIC or when the APIC is not disabled. That's bogus. The warning should only happen when the CPU has an APIC _AND_ the APIC is not disabled. apic_noop.apic_read() has the correct check. Signed-off-by: Thomas Gleixner Cc: Cyrill Gorcunov LKML-Reference: Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 894aa97f0717..c86dbcf39e8d 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -246,7 +246,7 @@ static int modern_apic(void) */ static void native_apic_write_dummy(u32 reg, u32 v) { - WARN_ON_ONCE((cpu_has_apic || !disable_apic)); + WARN_ON_ONCE(cpu_has_apic && !disable_apic); } static u32 native_apic_read_dummy(u32 reg) From 23022aab1a90cc3117b3816c79aea3977bce09ff Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Mon, 14 Dec 2009 17:59:58 -0800 Subject: [PATCH 106/670] mm: hugetlb: fix hugepage memory leak in mincore() commit 4f16fc107d9c9b8a72aa19b189a9216e90a7aaef upstream. Most callers of pmd_none_or_clear_bad() check whether the target page is in a hugepage or not, but mincore() and walk_page_range() do not check it. So if we use mincore() on a hugepage on x86 machine, the hugepage memory is leaked as shown below. This patch fixes it by extending mincore() system call to support hugepages. Details ======= My test program (leak_mincore) works as follows: - creat() and mmap() a file on hugetlbfs (file size is 200MB == 100 hugepages,) - read()/write() something on it, - call mincore() for first ten pages and printf() the values of *vec - munmap() and unlink() the file on hugetlbfs Without my patch ---------------- $ cat /proc/meminfo| grep "HugePage" HugePages_Total: 1000 HugePages_Free: 1000 HugePages_Rsvd: 0 HugePages_Surp: 0 $ ./leak_mincore vec[0] 0 vec[1] 0 vec[2] 0 vec[3] 0 vec[4] 0 vec[5] 0 vec[6] 0 vec[7] 0 vec[8] 0 vec[9] 0 $ cat /proc/meminfo |grep "HugePage" HugePages_Total: 1000 HugePages_Free: 999 HugePages_Rsvd: 0 HugePages_Surp: 0 $ ls /hugetlbfs/ $ Return values in *vec from mincore() are set to 0, while the hugepage should be in memory, and 1 hugepage is still accounted as used while there is no file on hugetlbfs. With my patch ------------- $ cat /proc/meminfo| grep "HugePage" HugePages_Total: 1000 HugePages_Free: 1000 HugePages_Rsvd: 0 HugePages_Surp: 0 $ ./leak_mincore vec[0] 1 vec[1] 1 vec[2] 1 vec[3] 1 vec[4] 1 vec[5] 1 vec[6] 1 vec[7] 1 vec[8] 1 vec[9] 1 $ cat /proc/meminfo |grep "HugePage" HugePages_Total: 1000 HugePages_Free: 1000 HugePages_Rsvd: 0 HugePages_Surp: 0 $ ls /hugetlbfs/ $ Return value in *vec set to 1 and no memory leaks. [akpm@linux-foundation.org: cleanup] [akpm@linux-foundation.org: build fix] Signed-off-by: Naoya Horiguchi Cc: Andi Kleen Cc: Wu Fengguang Cc: Hugh Dickins Cc: Mel Gorman Cc: Lee Schermerhorn Cc: Andy Whitcroft Cc: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mincore.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/mm/mincore.c b/mm/mincore.c index 8cb508f84ea4..7a3436ef39eb 100644 --- a/mm/mincore.c +++ b/mm/mincore.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -72,6 +73,42 @@ static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pag if (!vma || addr < vma->vm_start) return -ENOMEM; +#ifdef CONFIG_HUGETLB_PAGE + if (is_vm_hugetlb_page(vma)) { + struct hstate *h; + unsigned long nr_huge; + unsigned char present; + + i = 0; + nr = min(pages, (vma->vm_end - addr) >> PAGE_SHIFT); + h = hstate_vma(vma); + nr_huge = ((addr + pages * PAGE_SIZE - 1) >> huge_page_shift(h)) + - (addr >> huge_page_shift(h)) + 1; + nr_huge = min(nr_huge, + (vma->vm_end - addr) >> huge_page_shift(h)); + while (1) { + /* hugepage always in RAM for now, + * but generally it needs to be check */ + ptep = huge_pte_offset(current->mm, + addr & huge_page_mask(h)); + present = !!(ptep && + !huge_pte_none(huge_ptep_get(ptep))); + while (1) { + vec[i++] = present; + addr += PAGE_SIZE; + /* reach buffer limit */ + if (i == nr) + return nr; + /* check hugepage border */ + if (!((addr & ~huge_page_mask(h)) + >> PAGE_SHIFT)) + break; + } + } + return nr; + } +#endif + /* * Calculate how many pages there are left in the last level of the * PTE array for our address. From 0a0fa09874289cbfce7e94bc1b61b57e7751a63f Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Mon, 14 Dec 2009 17:59:59 -0800 Subject: [PATCH 107/670] mm: hugetlb: fix hugepage memory leak in walk_page_range() commit d33b9f45bd24a6391bc05e2b5a13c1b5787ca9c2 upstream. Most callers of pmd_none_or_clear_bad() check whether the target page is in a hugepage or not, but walk_page_range() do not check it. So if we read /proc/pid/pagemap for the hugepage on x86 machine, the hugepage memory is leaked as shown below. This patch fixes it. Details ======= My test program (leak_pagemap) works as follows: - creat() and mmap() a file on hugetlbfs (file size is 200MB == 100 hugepages,) - read()/write() something on it, - call page-types with option -p (walk around the page tables), - munmap() and unlink() the file on hugetlbfs Without my patches ------------------ $ cat /proc/meminfo |grep "HugePage" HugePages_Total: 1000 HugePages_Free: 1000 HugePages_Rsvd: 0 HugePages_Surp: 0 $ ./leak_pagemap [snip output] $ cat /proc/meminfo |grep "HugePage" HugePages_Total: 1000 HugePages_Free: 900 HugePages_Rsvd: 0 HugePages_Surp: 0 $ ls /hugetlbfs/ $ 100 hugepages are accounted as used while there is no file on hugetlbfs. With my patches --------------- $ cat /proc/meminfo |grep "HugePage" HugePages_Total: 1000 HugePages_Free: 1000 HugePages_Rsvd: 0 HugePages_Surp: 0 $ ./leak_pagemap [snip output] $ cat /proc/meminfo |grep "HugePage" HugePages_Total: 1000 HugePages_Free: 1000 HugePages_Rsvd: 0 HugePages_Surp: 0 $ ls /hugetlbfs $ No memory leaks. Signed-off-by: Naoya Horiguchi Cc: Andi Kleen Cc: Wu Fengguang Cc: Hugh Dickins Cc: Mel Gorman Cc: Lee Schermerhorn Cc: Andy Whitcroft Cc: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/pagewalk.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/mm/pagewalk.c b/mm/pagewalk.c index d5878bed7841..a286915e23ef 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -1,6 +1,7 @@ #include #include #include +#include static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, struct mm_walk *walk) @@ -107,6 +108,7 @@ int walk_page_range(unsigned long addr, unsigned long end, pgd_t *pgd; unsigned long next; int err = 0; + struct vm_area_struct *vma; if (addr >= end) return err; @@ -117,11 +119,22 @@ int walk_page_range(unsigned long addr, unsigned long end, pgd = pgd_offset(walk->mm, addr); do { next = pgd_addr_end(addr, end); + + /* skip hugetlb vma to avoid hugepage PMD being cleared + * in pmd_none_or_clear_bad(). */ + vma = find_vma(walk->mm, addr); + if (vma && is_vm_hugetlb_page(vma)) { + if (vma->vm_end < next) + next = vma->vm_end; + continue; + } + if (pgd_none_or_clear_bad(pgd)) { if (walk->pte_hole) err = walk->pte_hole(addr, next, walk); if (err) break; + pgd++; continue; } if (walk->pgd_entry) @@ -131,7 +144,8 @@ int walk_page_range(unsigned long addr, unsigned long end, err = walk_pud_range(pgd, addr, next, walk); if (err) break; - } while (pgd++, addr = next, addr != end); + pgd++; + } while (addr = next, addr != end); return err; } From d5f60d19405b2b8c338be1c70f013d39a40d049d Mon Sep 17 00:00:00 2001 From: Bolko Maass Date: Fri, 27 Nov 2009 05:44:33 +0000 Subject: [PATCH 108/670] powerpc/windfarm: Add detection for second cpu pump commit 529586dc39b0ec47c6290c4e7bed6ea3ffd1d8fb upstream. Windfarm SMU control is explicitly missing support for a second CPU pump in G5 PowerMacs. Such machines actually exist (specifically Quads with a second pump), so this patch adds detection for it. Signed-off by: Bolko Maass Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- drivers/macintosh/windfarm_smu_controls.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 961fa0e7c2cf..6c68b9e5f5c4 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c @@ -202,6 +202,8 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, fct->ctrl.name = "cpu-front-fan-1"; else if (!strcmp(l, "CPU A PUMP")) fct->ctrl.name = "cpu-pump-0"; + else if (!strcmp(l, "CPU B PUMP")) + fct->ctrl.name = "cpu-pump-1"; else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") || !strcmp(l, "EXPANSION SLOTS INTAKE")) fct->ctrl.name = "slots-fan"; From 6b3f68aeeae30d18186a844c92bf3269e3226f51 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 3 Dec 2009 16:19:59 +0000 Subject: [PATCH 109/670] powerpc/therm_adt746x: Record pwm invert bit at module load time] commit 1496e89ae2a0962748e55165a590fa3209c6f158 upstream. In commit 0512a9a8e277a9de2820211eef964473b714ae65, we unilaterally zero the "pwm invert" bit in the fan behavior configuration register. On my PowerBook G4, this results in the fans going to full speed at low temperature and shutting off at high temperature because the pwm invert bit is supposed to be set. Therefore, record the pwm invert bit at driver load time, and write the bit into the fan behavior control register. This restores correct behavior on my PBG4 and should work around the bit being set to the wrong value after suspend/resume (which is what the original patch was trying to fix). It also fixes a minor omission where the pwm invert bit correction is NOT performed when switching into automatic mode. Signed-off-by: Darrick J. Wong Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- drivers/macintosh/therm_adt746x.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 556f0feaa4df..386a7972111d 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -79,6 +79,7 @@ struct thermostat { u8 limits[3]; int last_speed[2]; int last_var[2]; + int pwm_inv[2]; }; static enum {ADT7460, ADT7467} therm_type; @@ -229,19 +230,23 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan) if (speed >= 0) { manual = read_reg(th, MANUAL_MODE[fan]); + manual &= ~INVERT_MASK; write_reg(th, MANUAL_MODE[fan], - (manual|MANUAL_MASK) & (~INVERT_MASK)); + manual | MANUAL_MASK | th->pwm_inv[fan]); write_reg(th, FAN_SPD_SET[fan], speed); } else { /* back to automatic */ if(therm_type == ADT7460) { manual = read_reg(th, MANUAL_MODE[fan]) & (~MANUAL_MASK); - + manual &= ~INVERT_MASK; + manual |= th->pwm_inv[fan]; write_reg(th, MANUAL_MODE[fan], manual|REM_CONTROL[fan]); } else { manual = read_reg(th, MANUAL_MODE[fan]); + manual &= ~INVERT_MASK; + manual |= th->pwm_inv[fan]; write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK)); } } @@ -418,6 +423,10 @@ static int probe_thermostat(struct i2c_client *client, thermostat = th; + /* record invert bit status because fw can corrupt it after suspend */ + th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK; + th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK; + /* be sure to really write fan speed the first time */ th->last_speed[0] = -2; th->last_speed[1] = -2; From 49e6aacefc4ba11f7515391659a6e2f316a6e1ae Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 8 Dec 2009 18:45:45 +0000 Subject: [PATCH 110/670] powerpc: Fix usage of 64-bit instruction in 32-bit altivec code commit e090aa80321b64c3b793f3b047e31ecf1af9538d upstream. e821ea70f3b4873b50056a1e0f74befed1014c09 introduced a bug by copying some 64-bit originated code as-is to be used by both 32 and 64-bit but this code contains a 64-bit ony "cmpdi" instruction. This changes it to cmpwi, which is fine since VRSAVE can only contains a 32-bit value anyway. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/vector.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 67b6916f0e94..fe460482fa68 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S @@ -58,7 +58,7 @@ _GLOBAL(load_up_altivec) * all 1's */ mfspr r4,SPRN_VRSAVE - cmpdi 0,r4,0 + cmpwi 0,r4,0 bne+ 1f li r4,-1 mtspr SPRN_VRSAVE,r4 From 5c5c0d7335f6cc65a7f18b09e473c346d20edc83 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Dec 2009 14:49:50 -0500 Subject: [PATCH 111/670] drm/radeon/kms: Add quirk for HIS X1300 board commit 4e3f9b78ff917cc5c833858fdb5d96bc262e0bf3 upstream. Board is DVI+VGA, not DVI+DVI Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_atombios.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 2ed88a820935..969502acc29c 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -135,6 +135,14 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } } + /* HIS X1300 is DVI+VGA, not DVI+DVI */ + if ((dev->pdev->device == 0x7146) && + (dev->pdev->subsystem_vendor == 0x17af) && + (dev->pdev->subsystem_device == 0x2058)) { + if (supported_device == ATOM_DEVICE_DFP1_SUPPORT) + return false; + } + /* Funky macbooks */ if ((dev->pdev->device == 0x71C5) && (dev->pdev->subsystem_vendor == 0x106b) && From 373b9483b6b1cc9ec21080ba29c90e9968102aa8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Dec 2009 11:46:52 -0500 Subject: [PATCH 112/670] drm/radeon/kms: handle vblanks properly with dpms on commit 500b758725314ab1b5316eb0caa5b0fa26740e6b upstream. avivo chips Copied from pre-avivo code. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index c15287a590ff..c6777cbee474 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -241,6 +241,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); switch (mode) { case DRM_MODE_DPMS_ON: @@ -248,20 +249,19 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) if (ASIC_IS_DCE3(rdev)) atombios_enable_crtc_memreq(crtc, 1); atombios_blank_crtc(crtc, 0); + drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); + radeon_crtc_load_lut(crtc); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: + drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); atombios_blank_crtc(crtc, 1); if (ASIC_IS_DCE3(rdev)) atombios_enable_crtc_memreq(crtc, 0); atombios_enable_crtc(crtc, 0); break; } - - if (mode != DRM_MODE_DPMS_OFF) { - radeon_crtc_load_lut(crtc); - } } static void From 48198675919e94a9a8d5185a8312789eae2ea9a0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 3 Dec 2009 12:15:54 -0500 Subject: [PATCH 113/670] drm/radeon/kms: fix legacy crtc2 dpms commit 8de21525439e6b5bb8d8c81e49094d867bf82f6d upstream. noticed by Matthijs Kooijman on fdo bug 22140 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 8d0b7aa87fa4..22ce4d6015e8 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -292,8 +292,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) uint32_t mask; if (radeon_crtc->crtc_id) - mask = (RADEON_CRTC2_EN | - RADEON_CRTC2_DISP_DIS | + mask = (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B); @@ -305,7 +304,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) switch (mode) { case DRM_MODE_DPMS_ON: if (radeon_crtc->crtc_id) - WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~mask); + WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask)); else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); @@ -319,7 +318,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_OFF: drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); if (radeon_crtc->crtc_id) - WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask); + WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask)); else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); From 3234b70ff908ed6479481027456fdd9826f56937 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 3 Dec 2009 16:18:19 -0500 Subject: [PATCH 114/670] drm/radeon/kms: fix vram setup on rs600 commit 722f29434e72188b2d20f9b41f4b5952073ed568 upstream. also fix up rs690 mem width. should fix fdo bug 25408 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/rs600.c | 6 ++++++ drivers/gpu/drm/radeon/rs690.c | 10 ++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 5f117cd8736a..c8d987d4d84e 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -315,6 +315,12 @@ void rs600_vram_info(struct radeon_device *rdev) /* FIXME: to do or is these values sane ? */ rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; + + rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; + + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); + rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); } void rs600_bandwidth_update(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 27547175cf93..787584f55034 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -131,19 +131,13 @@ void rs690_pm_info(struct radeon_device *rdev) void rs690_vram_info(struct radeon_device *rdev) { - uint32_t tmp; fixed20_12 a; rs400_gart_adjust_size(rdev); /* DDR for all card after R300 & IGP */ rdev->mc.vram_is_ddr = true; - /* FIXME: is this correct for RS690/RS740 ? */ - tmp = RREG32(RADEON_MEM_CNTL); - if (tmp & R300_MEM_NUM_CHANNELS_MASK) { - rdev->mc.vram_width = 128; - } else { - rdev->mc.vram_width = 64; - } + rdev->mc.vram_width = 128; + rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; From e582ed67311ec17b343f21b82fc40de4d35fff3e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 3 Dec 2009 16:28:02 -0500 Subject: [PATCH 115/670] drm/radeon/kms: rs6xx/rs740: clamp vram to aperture size commit 0088dbdb809e8799cb8f26da5ac64b15201fa99d upstream. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/rs600.c | 9 ++++++--- drivers/gpu/drm/radeon/rs690.c | 9 ++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index c8d987d4d84e..4444f48c496e 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -301,9 +301,7 @@ int rs600_mc_wait_for_idle(struct radeon_device *rdev) void rs600_gpu_init(struct radeon_device *rdev) { - /* FIXME: HDP same place on rs600 ? */ r100_hdp_reset(rdev); - /* FIXME: is this correct ? */ r420_pipes_init(rdev); /* Wait for mc idle */ if (rs600_mc_wait_for_idle(rdev)) @@ -312,7 +310,6 @@ void rs600_gpu_init(struct radeon_device *rdev) void rs600_vram_info(struct radeon_device *rdev) { - /* FIXME: to do or is these values sane ? */ rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; @@ -321,6 +318,12 @@ void rs600_vram_info(struct radeon_device *rdev) rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + + if (rdev->mc.mc_vram_size > rdev->mc.aper_size) + rdev->mc.mc_vram_size = rdev->mc.aper_size; + + if (rdev->mc.real_vram_size > rdev->mc.aper_size) + rdev->mc.real_vram_size = rdev->mc.aper_size; } void rs600_bandwidth_update(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 787584f55034..b12ff76c19d3 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -134,7 +134,7 @@ void rs690_vram_info(struct radeon_device *rdev) fixed20_12 a; rs400_gart_adjust_size(rdev); - /* DDR for all card after R300 & IGP */ + rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; @@ -143,6 +143,13 @@ void rs690_vram_info(struct radeon_device *rdev) rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + + if (rdev->mc.mc_vram_size > rdev->mc.aper_size) + rdev->mc.mc_vram_size = rdev->mc.aper_size; + + if (rdev->mc.real_vram_size > rdev->mc.aper_size) + rdev->mc.real_vram_size = rdev->mc.aper_size; + rs690_pm_info(rdev); /* FIXME: we should enforce default clock in case GPU is not in * default setup From 4a6ab40474d859a218e326550c2192f384527f81 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Thu, 19 Nov 2009 16:29:45 +0000 Subject: [PATCH 116/670] drm/ttm: Fix build failure due to missing struct page commit c3a73ba13bac7fd96030f39202b2d37fb19c46a6 upstream. drm/ttm fails to build on MIPS because "struct page" is not known: | In file included from drivers/gpu/drm/ttm/ttm_memory.c:28: | include/drm/ttm/ttm_memory.h:154: warning: 'struct page' declared inside parameter list | include/drm/ttm/ttm_memory.h:154: warning: its scope is only this definition or declaration, which is probably not what you want | include/drm/ttm/ttm_memory.h:156: warning: 'struct page' declared inside parameter list | drivers/gpu/drm/ttm/ttm_memory.c:540: error: conflicting types for 'ttm_mem_global_alloc_page' | include/drm/ttm/ttm_memory.h:154: error: previous declaration of 'ttm_mem_global_alloc_page' was here | drivers/gpu/drm/ttm/ttm_memory.c:561: error: conflicting types for 'ttm_mem_global_free_page' | include/drm/ttm/ttm_memory.h:156: error: previous declaration of 'ttm_mem_global_free_page' was here Signed-off-by: Martin Michlmayr Acked-by: Thomas Hellstrom Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- include/drm/ttm/ttm_memory.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h index 6983a7cf4da4..b199170b3c2c 100644 --- a/include/drm/ttm/ttm_memory.h +++ b/include/drm/ttm/ttm_memory.h @@ -33,6 +33,7 @@ #include #include #include +#include /** * struct ttm_mem_shrink - callback to shrink TTM memory usage. From 739f9e4f0c9ede0209e874ed223b297d04483358 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 2 Dec 2009 15:15:30 +0000 Subject: [PATCH 117/670] drm/i915: Set the error code after failing to insert new offset into mm ht. commit 5618ca6abc2d6f475b258badc017a5254cf43d1b upstream. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index abfc27b0c2ea..5ddbd38201b0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1288,6 +1288,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) list->hash.key = list->file_offset_node->start; if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { DRM_ERROR("failed to add to map hash\n"); + ret = -ENOMEM; goto out_free_mm; } From 14173dbee479f3c9560f303040488505d7ae5381 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 2 Dec 2009 10:03:33 +0800 Subject: [PATCH 118/670] drm/i915: Add the missing clonemask for display port on Ironlake commit 652af9d74e1a3a10bb10f0d8e8f42ddac26bbc1a upstream. Add the missing clonemask for display port on Ironlake. Signed-off-by: Zhao Yakui Reviewed-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_dp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d83447557f9b..92a3d7b0d009 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1254,11 +1254,11 @@ intel_dp_init(struct drm_device *dev, int output_reg) else intel_output->type = INTEL_OUTPUT_DISPLAYPORT; - if (output_reg == DP_B) + if (output_reg == DP_B || output_reg == PCH_DP_B) intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT); - else if (output_reg == DP_C) + else if (output_reg == DP_C || output_reg == PCH_DP_C) intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT); - else if (output_reg == DP_D) + else if (output_reg == DP_D || output_reg == PCH_DP_D) intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); if (IS_eDP(intel_output)) { From fd28fac739e3a2e2be8138fb10ce554f74a50cae Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 24 Nov 2009 16:41:47 -0800 Subject: [PATCH 119/670] xen/xenbus: make DEVICE_ATTR()s static commit db05fed0ad72f264e39bcb366795f7367384ec92 upstream. They don't need to be global, and may cause linker clashes. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xenbus/xenbus_probe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index d42e25d5968d..3800da7dabfe 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -454,21 +454,21 @@ static ssize_t xendev_show_nodename(struct device *dev, { return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename); } -DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); +static DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); static ssize_t xendev_show_devtype(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype); } -DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); +static DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); static ssize_t xendev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype); } -DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL); +static DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL); int xenbus_probe_node(struct xen_bus_type *bus, const char *type, From e27d65dec237be523c3e3c8b193007243367aad9 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Sat, 21 Nov 2009 08:35:55 +0800 Subject: [PATCH 120/670] xen: re-register runstate area earlier on resume. commit be012920ecba161ad20303a3f6d9e96c58cf97c7 upstream. This is necessary to ensure the runstate area is available to xen_sched_clock before any calls to printk which will require it in order to provide a timestamp. I chose to pull the xen_setup_runstate_info out of xen_time_init into the caller in order to maintain parity with calling xen_setup_runstate_info separately from calling xen_time_resume. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten.c | 2 ++ arch/x86/xen/time.c | 5 ++--- arch/x86/xen/xen-ops.h | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index dfbf70e65860..cb61f77e4496 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -148,6 +148,8 @@ void xen_vcpu_restore(void) HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL)) BUG(); + xen_setup_runstate_info(cpu); + xen_vcpu_setup(cpu); if (other_cpu && diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 0a5aa44299a5..6bbff94328d2 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -100,7 +100,7 @@ bool xen_vcpu_stolen(int vcpu) return per_cpu(runstate, vcpu).state == RUNSTATE_runnable; } -static void setup_runstate_info(int cpu) +void xen_setup_runstate_info(int cpu) { struct vcpu_register_runstate_memory_area area; @@ -442,8 +442,6 @@ void xen_setup_timer(int cpu) evt->cpumask = cpumask_of(cpu); evt->irq = irq; - - setup_runstate_info(cpu); } void xen_teardown_timer(int cpu) @@ -494,6 +492,7 @@ __init void xen_time_init(void) setup_force_cpu_cap(X86_FEATURE_TSC); + xen_setup_runstate_info(cpu); xen_setup_timer(cpu); xen_setup_cpu_clockevents(); } diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 355fa6b99c9c..32529326683d 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -41,6 +41,7 @@ void __init xen_build_dynamic_phys_to_machine(void); void xen_init_irq_ops(void); void xen_setup_timer(int cpu); +void xen_setup_runstate_info(int cpu); void xen_teardown_timer(int cpu); cycle_t xen_clocksource_read(void); void xen_setup_cpu_clockevents(void); From b6c73e8a66cd9f54bfc0d2267afd10eaf44157e1 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 21 Nov 2009 08:46:29 +0800 Subject: [PATCH 121/670] xen: restore runstate_info even if !have_vcpu_info_placement commit 3905bb2aa7bb801b31946b37a4635ebac4009051 upstream. Even if have_vcpu_info_placement is not set, we still need to set up the runstate area on each resumed vcpu. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index cb61f77e4496..a7b49f99a130 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -138,26 +138,23 @@ static void xen_vcpu_setup(int cpu) */ void xen_vcpu_restore(void) { - if (have_vcpu_info_placement) { - int cpu; + int cpu; - for_each_online_cpu(cpu) { - bool other_cpu = (cpu != smp_processor_id()); + for_each_online_cpu(cpu) { + bool other_cpu = (cpu != smp_processor_id()); - if (other_cpu && - HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL)) - BUG(); + if (other_cpu && + HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL)) + BUG(); - xen_setup_runstate_info(cpu); + xen_setup_runstate_info(cpu); + if (have_vcpu_info_placement) xen_vcpu_setup(cpu); - if (other_cpu && - HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL)) - BUG(); - } - - BUG_ON(!have_vcpu_info_placement); + if (other_cpu && + HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL)) + BUG(); } } From b6172e046931fd39a53b3607af40155eadbbecc2 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Sat, 21 Nov 2009 11:32:49 +0000 Subject: [PATCH 122/670] xen: correctly restore pfn_to_mfn_list_list after resume commit fa24ba62ea2869308ffc9f0b286ac9650b4ca6cb upstream. pvops kernels >= 2.6.30 can currently only be saved and restored once. The second attempt to save results in: ERROR Internal error: Frame# in pfn-to-mfn frame list is not in pseudophys ERROR Internal error: entry 0: p2m_frame_list[0] is 0xf2c2c2c2, max 0x120000 ERROR Internal error: Failed to map/save the p2m frame list I finally narrowed it down to: commit cdaead6b4e657f960d6d6f9f380e7dfeedc6a09b Author: Jeremy Fitzhardinge Date: Fri Feb 27 15:34:59 2009 -0800 xen: split construction of p2m mfn tables from registration Build the p2m_mfn_list_list early with the rest of the p2m table, but register it later when the real shared_info structure is in place. Signed-off-by: Jeremy Fitzhardinge The unforeseen side-effect of this change was to cause the mfn list list to not be rebuilt on resume. Prior to this change it would have been rebuilt via xen_post_suspend() -> xen_setup_shared_info() -> xen_setup_mfn_list_list(). Fix by explicitly calling xen_build_mfn_list_list() from xen_post_suspend(). Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/mmu.c | 2 +- arch/x86/xen/suspend.c | 2 ++ arch/x86/xen/xen-ops.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 3bf7b1d250ce..bf4cd6bfe959 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -185,7 +185,7 @@ static inline unsigned p2m_index(unsigned long pfn) } /* Build the parallel p2m_top_mfn structures */ -static void __init xen_build_mfn_list_list(void) +void xen_build_mfn_list_list(void) { unsigned pfn, idx; diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c index 95be7b434724..6343a5d8e93c 100644 --- a/arch/x86/xen/suspend.c +++ b/arch/x86/xen/suspend.c @@ -27,6 +27,8 @@ void xen_pre_suspend(void) void xen_post_suspend(int suspend_cancelled) { + xen_build_mfn_list_list(); + xen_setup_shared_info(); if (suspend_cancelled) { diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 32529326683d..f9153a300bce 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -25,6 +25,7 @@ extern struct shared_info *HYPERVISOR_shared_info; void xen_setup_mfn_list_list(void); void xen_setup_shared_info(void); +void xen_build_mfn_list_list(void); void xen_setup_machphys_mapping(void); pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn); void xen_ident_map_ISA(void); From d7b1aedc1a241dcde39a8a35757b6b0797eac5ff Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 24 Nov 2009 10:16:23 +0000 Subject: [PATCH 123/670] xen: register timer interrupt with IRQF_TIMER commit f350c7922faad3397c98c81a9e5658f5a1ef0214 upstream. Otherwise the timer is disabled by dpm_suspend_noirq() which in turn prevents correct operation of stop_machine on multi-processor systems and breaks suspend. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 6bbff94328d2..9d1f853120d8 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -434,7 +434,7 @@ void xen_setup_timer(int cpu) name = ""; irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, - IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, + IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER, name, NULL); evt = &per_cpu(xen_clock_events, cpu); From 25fa3416973b064c4a156340301a5b97301af602 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 24 Nov 2009 09:32:48 -0800 Subject: [PATCH 124/670] xen: register runstate on secondary CPUs commit 028896721ac04f6fa0697f3ecac3f98761746363 upstream. The commit "xen: re-register runstate area earlier on resume" caused us to never try and setup the runstate area for secondary CPUs. Ensure that we do this... Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/smp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index fe03eeed7b48..360f8d8c19cd 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -295,6 +295,7 @@ static int __cpuinit xen_cpu_up(unsigned int cpu) (unsigned long)task_stack_page(idle) - KERNEL_STACK_OFFSET + THREAD_SIZE; #endif + xen_setup_runstate_info(cpu); xen_setup_timer(cpu); xen_init_lock_cpu(cpu); From 8fd7520c678cc3d8af422bca9f22149731520f1b Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 24 Nov 2009 09:58:49 -0800 Subject: [PATCH 125/670] xen: don't call dpm_resume_noirq() with interrupts disabled. commit 922cc38ab71d1360978e65207e4a4f4988987127 upstream. dpm_resume_noirq() takes a mutex, so it can't be called from a no-interrupt context. Don't call it from within the stop-machine function, but just afterwards, since we're resuming anyway, regardless of what happened. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/manage.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 10d03d7931c4..7b69a1aef877 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -43,7 +43,6 @@ static int xen_suspend(void *data) if (err) { printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", err); - dpm_resume_noirq(PMSG_RESUME); return err; } @@ -69,7 +68,6 @@ static int xen_suspend(void *data) } sysdev_resume(); - dpm_resume_noirq(PMSG_RESUME); return 0; } @@ -108,6 +106,9 @@ static void do_suspend(void) } err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); + + dpm_resume_noirq(PMSG_RESUME); + if (err) { printk(KERN_ERR "failed to start xen_suspend: %d\n", err); goto out; @@ -119,8 +120,6 @@ static void do_suspend(void) } else xs_suspend_cancel(); - dpm_resume_noirq(PMSG_RESUME); - resume_devices: dpm_resume_end(PMSG_RESUME); From c7092102563af5c81bd8d08582fdbe4529cbcf17 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 24 Nov 2009 09:38:25 -0800 Subject: [PATCH 126/670] xen: register runstate info for boot CPU early commit 499d19b82b586aef18727b9ae1437f8f37b66e91 upstream. printk timestamping uses sched_clock, which in turn relies on runstate info under Xen. So make sure we set it up before any printks can be called. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index a7b49f99a130..79f97383cde3 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1181,6 +1181,8 @@ asmlinkage void __init xen_start_kernel(void) xen_raw_console_write("about to get started...\n"); + xen_setup_runstate_info(0); + /* Start the world */ #ifdef CONFIG_X86_32 i386_start_kernel(); From 0bf7bb9861a419c63055293ddec67329165f8d84 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 25 Nov 2009 14:12:08 +0000 Subject: [PATCH 127/670] xen: call clock resume notifier on all CPUs commit f6eafe3665bcc374c66775d58312d1c06c55303f upstream. tick_resume() is never called on secondary processors. Presumably this is because they are offlined for suspend on native and so this is normally taken care of in the CPU onlining path. Under Xen we keep all CPUs online over a suspend. This patch papers over the issue for me but I will investigate a more generic, less hacky, way of doing to the same. tick_suspend is also only called on the boot CPU which I presume should be fixed too. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Cc: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/suspend.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c index 6343a5d8e93c..987267f79bf5 100644 --- a/arch/x86/xen/suspend.c +++ b/arch/x86/xen/suspend.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -46,7 +47,19 @@ void xen_post_suspend(int suspend_cancelled) } +static void xen_vcpu_notify_restore(void *data) +{ + unsigned long reason = (unsigned long)data; + + /* Boot processor notified via generic timekeeping_resume() */ + if ( smp_processor_id() == 0) + return; + + clockevents_notify(reason, NULL); +} + void xen_arch_resume(void) { - /* nothing */ + smp_call_function(xen_vcpu_notify_restore, + (void *)CLOCK_EVT_NOTIFY_RESUME, 1); } From f180b871d6cbcaaf9349075afb515081de073acb Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 1 Dec 2009 11:47:14 +0000 Subject: [PATCH 128/670] xen: improve error handling in do_suspend. commit 65f63384b391bf4d384327d8a7c6de9860290b5c upstream. The existing error handling has a few issues: - If freeze_processes() fails it exits with shutting_down = SHUTDOWN_SUSPEND. - If dpm_suspend_noirq() fails it exits without resuming xenbus. - If stop_machine() fails it exits without resuming xenbus or calling dpm_resume_end(). - xs_suspend()/xs_resume() and dpm_suspend_noirq()/dpm_resume_noirq() were not nested in the obvious way. Fix by ensuring each failure case goto's the correct label. Treat a failure of stop_machine() as a cancelled suspend in order to follow the correct resume path. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/manage.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 7b69a1aef877..2fb7d39b814c 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -86,32 +86,32 @@ static void do_suspend(void) err = freeze_processes(); if (err) { printk(KERN_ERR "xen suspend: freeze failed %d\n", err); - return; + goto out; } #endif err = dpm_suspend_start(PMSG_SUSPEND); if (err) { printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err); - goto out; + goto out_thaw; } - printk(KERN_DEBUG "suspending xenstore...\n"); - xs_suspend(); - err = dpm_suspend_noirq(PMSG_SUSPEND); if (err) { printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); - goto resume_devices; + goto out_resume; } + printk(KERN_DEBUG "suspending xenstore...\n"); + xs_suspend(); + err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); dpm_resume_noirq(PMSG_RESUME); if (err) { printk(KERN_ERR "failed to start xen_suspend: %d\n", err); - goto out; + cancelled = 1; } if (!cancelled) { @@ -120,15 +120,17 @@ static void do_suspend(void) } else xs_suspend_cancel(); -resume_devices: +out_resume: dpm_resume_end(PMSG_RESUME); /* Make sure timer events get retriggered on all CPUs */ clock_was_set(); -out: + +out_thaw: #ifdef CONFIG_PREEMPT thaw_processes(); #endif +out: shutting_down = SHUTDOWN_INVALID; } #endif /* CONFIG_PM_SLEEP */ From 98a0174b42a81685c342a230a8a8755a9df9bcd6 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 1 Dec 2009 16:15:30 +0000 Subject: [PATCH 129/670] xen: don't leak IRQs over suspend/resume. commit fed5ea87e02aaf902ff38c65b4514233db03dc09 upstream. On resume irq_info[*].evtchn is reset to 0 since event channel mappings are not preserved over suspend/resume. The other contents of irq_info is preserved to allow rebind_evtchn_irq() to function. However when a device resumes it will try to unbind from the previous IRQ (e.g. blkfront goes blkfront_resume() -> blkif_free() -> unbind_from_irqhandler() -> unbind_from_irq()). This will fail due to the check for VALID_EVTCHN in unbind_from_irq() and the IRQ is leaked. The device will then continue to resume and allocate a new IRQ, eventually leading to find_unbound_irq() panic()ing. Fix this by changing unbind_from_irq() to handle teardown of interrupts which have type!=IRQT_UNBOUND but are not currently bound to a specific event channel. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 2f57276e87a2..ce602dd09bc1 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -474,6 +474,9 @@ static void unbind_from_irq(unsigned int irq) bind_evtchn_to_cpu(evtchn, 0); evtchn_to_irq[evtchn] = -1; + } + + if (irq_info[irq].type != IRQT_UNBOUND) { irq_info[irq] = mk_unbound_info(); dynamic_irq_cleanup(irq); From ebe5f3b81f1d3677882b5b1c382321096c7d1851 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 25 Nov 2009 13:15:38 -0800 Subject: [PATCH 130/670] xen: use iret for return from 64b kernel to 32b usermode commit 6aaf5d633bb6cead81b396d861d7bae4b9a0ba7e upstream. If Xen wants to return to a 32b usermode with sysret it must use the right form. When using VCGF_in_syscall to trigger this, it looks at the code segment and does a 32b sysret if it is FLAT_USER_CS32. However, this is different from __USER32_CS, so it fails to return properly if we use the normal Linux segment. So avoid the whole mess by dropping VCGF_in_syscall and simply use plain iret to return to usermode. Signed-off-by: Jeremy Fitzhardinge Acked-by: Jan Beulich Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/xen-asm_64.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index 02f496a8dbaa..53adefda4275 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S @@ -96,7 +96,7 @@ ENTRY(xen_sysret32) pushq $__USER32_CS pushq %rcx - pushq $VGCF_in_syscall + pushq $0 1: jmp hypercall_iret ENDPATCH(xen_sysret32) RELOC(xen_sysret32, 1b+1) @@ -151,7 +151,7 @@ ENTRY(xen_syscall32_target) ENTRY(xen_sysenter_target) lea 16(%rsp), %rsp /* strip %rcx, %r11 */ mov $-ENOSYS, %rax - pushq $VGCF_in_syscall + pushq $0 jmp hypercall_iret ENDPROC(xen_syscall32_target) ENDPROC(xen_sysenter_target) From 7a0eb0721ef8015e1d17fb1cc017179eedf8cc2c Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 1 Dec 2009 11:47:15 +0000 Subject: [PATCH 131/670] xen: explicitly create/destroy stop_machine workqueues outside suspend/resume region. commit b4606f2165153833247823e8c04c5e88cb3d298b upstream. I have observed cases where the implicit stop_machine_destroy() done by stop_machine() hangs while destroying the workqueues, specifically in kthread_stop(). This seems to be because timer ticks are not restarted until after stop_machine() returns. Fortunately stop_machine provides a facility to pre-create/post-destroy the workqueues so use this to ensure that workqueues are only destroyed after everything is really up and running again. I only actually observed this failure with 2.6.30. It seems that newer kernels are somehow more robust against doing kthread_stop() without timer interrupts (I tried some backports of some likely looking candidates but did not track down the commit which added this robustness). However this change seems like a reasonable belt&braces thing to do. Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/manage.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 2fb7d39b814c..c4997930afc7 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -79,6 +79,12 @@ static void do_suspend(void) shutting_down = SHUTDOWN_SUSPEND; + err = stop_machine_create(); + if (err) { + printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err); + goto out; + } + #ifdef CONFIG_PREEMPT /* If the kernel is preemptible, we need to freeze all the processes to prevent them from being in the middle of a pagetable update @@ -86,7 +92,7 @@ static void do_suspend(void) err = freeze_processes(); if (err) { printk(KERN_ERR "xen suspend: freeze failed %d\n", err); - goto out; + goto out_destroy_sm; } #endif @@ -129,7 +135,11 @@ static void do_suspend(void) out_thaw: #ifdef CONFIG_PREEMPT thaw_processes(); + +out_destroy_sm: #endif + stop_machine_destroy(); + out: shutting_down = SHUTDOWN_INVALID; } From 910965b03f3c8930db26378bd9ab06ea74b91bdb Mon Sep 17 00:00:00 2001 From: Gianluca Guida Date: Thu, 30 Jul 2009 22:54:36 +0100 Subject: [PATCH 132/670] Xen balloon: fix totalram_pages counting. commit 3d65c9488cadd2f11bd4d60c7266e639ece5d0d6 upstream. Change totalram_pages when a single page is added/removed to the ballooned list. This avoid totalram_pages to be set erroneously to max_pfn at boot. Signed-off-by: Gianluca Guida Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/balloon.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index d31505b6f7a4..6eb62654410a 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -136,6 +136,8 @@ static void balloon_append(struct page *page) list_add(&page->lru, &ballooned_pages); balloon_stats.balloon_low++; } + + totalram_pages--; } /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ @@ -156,6 +158,8 @@ static struct page *balloon_retrieve(void) else balloon_stats.balloon_low--; + totalram_pages++; + return page; } @@ -260,7 +264,6 @@ static int increase_reservation(unsigned long nr_pages) } balloon_stats.current_pages += nr_pages; - totalram_pages = balloon_stats.current_pages; out: spin_unlock_irqrestore(&balloon_lock, flags); @@ -323,7 +326,6 @@ static int decrease_reservation(unsigned long nr_pages) BUG_ON(ret != nr_pages); balloon_stats.current_pages -= nr_pages; - totalram_pages = balloon_stats.current_pages; spin_unlock_irqrestore(&balloon_lock, flags); @@ -422,7 +424,6 @@ static int __init balloon_init(void) pr_info("xen_balloon: Initialising balloon driver.\n"); balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn); - totalram_pages = balloon_stats.current_pages; balloon_stats.target_pages = balloon_stats.current_pages; balloon_stats.balloon_low = 0; balloon_stats.balloon_high = 0; From 1e75ccef288b75a3b207c1b1be4baf5ae5ac0ffb Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 5 Jun 2009 11:58:37 +0100 Subject: [PATCH 133/670] xen: try harder to balloon up under memory pressure. commit bc2c0303226ec716854d3c208c7f84fe7aa35cd7 upstream. Currently if the balloon driver is unable to increase the guest's reservation it assumes the failure was due to reaching its full allocation, gives up on the ballooning operation and records the limit it reached as the "hard limit". The driver will not try again until the target is set again (even to the same value). However it is possible that ballooning has in fact failed due to memory pressure in the host and therefore it is desirable to keep attempting to reach the target in case memory becomes available. The most likely scenario is that some guests are ballooning down while others are ballooning up and therefore there is temporary memory pressure while things stabilise. You would not expect a well behaved toolstack to ask a domain to balloon to more than its allocation nor would you expect it to deliberately over-commit memory by setting balloon targets which exceed the total host memory. This patch drops the concept of a hard limit and causes the balloon driver to retry increasing the reservation on a timer in the same manner as when decreasing the reservation. Also if we partially succeed in increasing the reservation (i.e. receive less pages than we asked for) then we may as well keep those pages rather than returning them to Xen. Signed-off-by: Ian Campbell Signed-off-by: Greg Kroah-Hartman --- drivers/xen/balloon.c | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 6eb62654410a..420433613584 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -66,8 +66,6 @@ struct balloon_stats { /* We aim for 'current allocation' == 'target allocation'. */ unsigned long current_pages; unsigned long target_pages; - /* We may hit the hard limit in Xen. If we do then we remember it. */ - unsigned long hard_limit; /* * Drivers may alter the memory reservation independently, but they * must inform the balloon driver so we avoid hitting the hard limit. @@ -185,7 +183,7 @@ static void balloon_alarm(unsigned long unused) static unsigned long current_target(void) { - unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit); + unsigned long target = balloon_stats.target_pages; target = min(target, balloon_stats.current_pages + @@ -221,23 +219,10 @@ static int increase_reservation(unsigned long nr_pages) set_xen_guest_handle(reservation.extent_start, frame_list); reservation.nr_extents = nr_pages; rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); - if (rc < nr_pages) { - if (rc > 0) { - int ret; - - /* We hit the Xen hard limit: reprobe. */ - reservation.nr_extents = rc; - ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, - &reservation); - BUG_ON(ret != rc); - } - if (rc >= 0) - balloon_stats.hard_limit = (balloon_stats.current_pages + rc - - balloon_stats.driver_pages); + if (rc < 0) goto out; - } - for (i = 0; i < nr_pages; i++) { + for (i = 0; i < rc; i++) { page = balloon_retrieve(); BUG_ON(page == NULL); @@ -263,12 +248,12 @@ static int increase_reservation(unsigned long nr_pages) __free_page(page); } - balloon_stats.current_pages += nr_pages; + balloon_stats.current_pages += rc; out: spin_unlock_irqrestore(&balloon_lock, flags); - return 0; + return rc < 0 ? rc : rc != nr_pages; } static int decrease_reservation(unsigned long nr_pages) @@ -369,7 +354,6 @@ static void balloon_process(struct work_struct *work) static void balloon_set_new_target(unsigned long target) { /* No need for lock. Not read-modify-write updates. */ - balloon_stats.hard_limit = ~0UL; balloon_stats.target_pages = target; schedule_work(&balloon_worker); } @@ -428,7 +412,6 @@ static int __init balloon_init(void) balloon_stats.balloon_low = 0; balloon_stats.balloon_high = 0; balloon_stats.driver_pages = 0UL; - balloon_stats.hard_limit = ~0UL; init_timer(&balloon_timer); balloon_timer.data = 0; @@ -473,9 +456,6 @@ module_exit(balloon_exit); BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); -BALLOON_SHOW(hard_limit_kb, - (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n", - (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0); BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr, @@ -545,7 +525,6 @@ static struct attribute *balloon_info_attrs[] = { &attr_current_kb.attr, &attr_low_kb.attr, &attr_high_kb.attr, - &attr_hard_limit_kb.attr, &attr_driver_kb.attr, NULL }; From 5db89cf4ea748e1c2d29d52175b2bace466078c7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 10 Dec 2009 23:51:52 +0000 Subject: [PATCH 134/670] dm exception store: free tmp_store on persistent flag error commit 613978f8711c7fd4d0aa856872375d2abd7c92ff upstream. Error handling code following a kmalloc should free the allocated data. Signed-off-by: Julia Lawall Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-exception-store.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 7dbe652efb5a..205215968ff1 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -216,7 +216,8 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, type = get_type("N"); else { ti->error = "Persistent flag is not P or N"; - return -EINVAL; + r = -EINVAL; + goto bad_type; } if (!type) { From 5f5d50a0f5530e5a6df52755c74ec5a47829f8cc Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 10 Dec 2009 23:51:53 +0000 Subject: [PATCH 135/670] dm snapshot: only take lock for statustype info not table commit 94e76572b5dd37b1f0f4b3742ee8a565daead932 upstream. Take snapshot lock only for STATUSTYPE_INFO, not STATUSTYPE_TABLE. Commit 4c6fff445d7aa753957856278d4d93bcad6e2c14 (dm-snapshot-lock-snapshot-while-supplying-status.patch) introduced this use of the lock, but userspace applications using libdevmapper have been found to request STATUSTYPE_TABLE while the device is suspended and the lock is already held, leading to deadlock. Since the lock is not necessary in this case, don't try to take it. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-snap.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 3a3ba46e6d4b..d135212958f1 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1152,10 +1152,11 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, unsigned sz = 0; struct dm_snapshot *snap = ti->private; - down_write(&snap->lock); - switch (type) { case STATUSTYPE_INFO: + + down_write(&snap->lock); + if (!snap->valid) DMEMIT("Invalid"); else { @@ -1171,6 +1172,9 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, else DMEMIT("Unknown"); } + + up_write(&snap->lock); + break; case STATUSTYPE_TABLE: @@ -1185,8 +1189,6 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, break; } - up_write(&snap->lock); - return 0; } From c7f27e82997f9c835b4c241d1f302501d0cdcc9e Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Thu, 10 Dec 2009 23:51:55 +0000 Subject: [PATCH 136/670] dm crypt: move private iv fields to structs commit 6047359277517c4e56d8bfd6ea4966d7a3924151 upstream. Define private structures for IV so it's easy to add further attributes in a following patch which fixes the way key material is wiped from memory. Also move ESSIV destructor and remove unnecessary 'status' operation. There are no functional changes in this patch. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-crypt.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ed1038164019..9fa1b88b9680 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -71,10 +71,17 @@ struct crypt_iv_operations { int (*ctr)(struct crypt_config *cc, struct dm_target *ti, const char *opts); void (*dtr)(struct crypt_config *cc); - const char *(*status)(struct crypt_config *cc); int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector); }; +struct iv_essiv_private { + struct crypto_cipher *tfm; +}; + +struct iv_benbi_private { + int shift; +}; + /* * Crypt: maps a linear range of a block device * and encrypts / decrypts at the same time. @@ -102,8 +109,8 @@ struct crypt_config { struct crypt_iv_operations *iv_gen_ops; char *iv_mode; union { - struct crypto_cipher *essiv_tfm; - int benbi_shift; + struct iv_essiv_private essiv; + struct iv_benbi_private benbi; } iv_gen_private; sector_t iv_offset; unsigned int iv_size; @@ -169,6 +176,14 @@ static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector) return 0; } +static void crypt_iv_essiv_dtr(struct crypt_config *cc) +{ + struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; + + crypto_free_cipher(essiv->tfm); + essiv->tfm = NULL; +} + static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, const char *opts) { @@ -236,21 +251,15 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, } kfree(salt); - cc->iv_gen_private.essiv_tfm = essiv_tfm; + cc->iv_gen_private.essiv.tfm = essiv_tfm; return 0; } -static void crypt_iv_essiv_dtr(struct crypt_config *cc) -{ - crypto_free_cipher(cc->iv_gen_private.essiv_tfm); - cc->iv_gen_private.essiv_tfm = NULL; -} - static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) { memset(iv, 0, cc->iv_size); *(u64 *)iv = cpu_to_le64(sector); - crypto_cipher_encrypt_one(cc->iv_gen_private.essiv_tfm, iv, iv); + crypto_cipher_encrypt_one(cc->iv_gen_private.essiv.tfm, iv, iv); return 0; } @@ -273,7 +282,7 @@ static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, return -EINVAL; } - cc->iv_gen_private.benbi_shift = 9 - log; + cc->iv_gen_private.benbi.shift = 9 - log; return 0; } @@ -288,7 +297,7 @@ static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector) memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */ - val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi_shift) + 1); + val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi.shift) + 1); put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64))); return 0; From c22d66f16eaeec0d3c4df607f425f4ebf2b8d238 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Thu, 10 Dec 2009 23:51:56 +0000 Subject: [PATCH 137/670] dm crypt: restructure essiv error path commit 5861f1be00b3b70f8ab5e5a81392a6cf69666cd2 upstream. Use kzfree for salt deallocation because it is derived from the volume key. Use a common error path in ESSIV constructor. Required by a later patch which fixes the way key material is wiped from memory. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-crypt.c | 46 ++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 9fa1b88b9680..2856bdca2515 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -187,15 +187,15 @@ static void crypt_iv_essiv_dtr(struct crypt_config *cc) static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, const char *opts) { - struct crypto_cipher *essiv_tfm; - struct crypto_hash *hash_tfm; + struct crypto_cipher *essiv_tfm = NULL; + struct crypto_hash *hash_tfm = NULL; struct hash_desc desc; struct scatterlist sg; unsigned int saltsize; - u8 *salt; + u8 *salt = NULL; int err; - if (opts == NULL) { + if (!opts) { ti->error = "Digest algorithm missing for ESSIV mode"; return -EINVAL; } @@ -204,15 +204,16 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, hash_tfm = crypto_alloc_hash(opts, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(hash_tfm)) { ti->error = "Error initializing ESSIV hash"; - return PTR_ERR(hash_tfm); + err = PTR_ERR(hash_tfm); + goto bad; } saltsize = crypto_hash_digestsize(hash_tfm); - salt = kmalloc(saltsize, GFP_KERNEL); - if (salt == NULL) { + salt = kzalloc(saltsize, GFP_KERNEL); + if (!salt) { ti->error = "Error kmallocing salt storage in ESSIV"; - crypto_free_hash(hash_tfm); - return -ENOMEM; + err = -ENOMEM; + goto bad; } sg_init_one(&sg, cc->key, cc->key_size); @@ -220,39 +221,44 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; err = crypto_hash_digest(&desc, &sg, cc->key_size, salt); crypto_free_hash(hash_tfm); + hash_tfm = NULL; if (err) { ti->error = "Error calculating hash in ESSIV"; - kfree(salt); - return err; + goto bad; } /* Setup the essiv_tfm with the given salt */ essiv_tfm = crypto_alloc_cipher(cc->cipher, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(essiv_tfm)) { ti->error = "Error allocating crypto tfm for ESSIV"; - kfree(salt); - return PTR_ERR(essiv_tfm); + err = PTR_ERR(essiv_tfm); + goto bad; } if (crypto_cipher_blocksize(essiv_tfm) != crypto_ablkcipher_ivsize(cc->tfm)) { ti->error = "Block size of ESSIV cipher does " "not match IV size of block cipher"; - crypto_free_cipher(essiv_tfm); - kfree(salt); - return -EINVAL; + err = -EINVAL; + goto bad; } err = crypto_cipher_setkey(essiv_tfm, salt, saltsize); if (err) { ti->error = "Failed to set key for ESSIV cipher"; - crypto_free_cipher(essiv_tfm); - kfree(salt); - return err; + goto bad; } - kfree(salt); + kzfree(salt); cc->iv_gen_private.essiv.tfm = essiv_tfm; return 0; + +bad: + if (essiv_tfm && !IS_ERR(essiv_tfm)) + crypto_free_cipher(essiv_tfm); + if (hash_tfm && !IS_ERR(hash_tfm)) + crypto_free_hash(hash_tfm); + kzfree(salt); + return err; } static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) From 0bca4a5b78ad922624e9a76a7e86453f1fec7239 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 10 Dec 2009 23:51:52 +0000 Subject: [PATCH 138/670] dm: avoid _hash_lock deadlock commit 6076905b5ef39e0ea58db32583c9e0036c05e47b upstream. Fix a reported deadlock if there are still unprocessed multipath events on a device that is being removed. _hash_lock is held during dev_remove while trying to send the outstanding events. Sending the events requests the _hash_lock again in dm_copy_name_and_uuid. This patch introduces a separate lock around regions that modify the link to the hash table (dm_set_mdptr) or the name or uuid so that dm_copy_name_and_uuid no longer needs _hash_lock. Additionally, dm_copy_name_and_uuid can only be called if md exists so we can drop the dm_get() and dm_put() which can lead to a BUG() while md is being freed. The deadlock: #0 [ffff8106298dfb48] schedule at ffffffff80063035 #1 [ffff8106298dfc20] __down_read at ffffffff8006475d #2 [ffff8106298dfc60] dm_copy_name_and_uuid at ffffffff8824f740 #3 [ffff8106298dfc90] dm_send_uevents at ffffffff88252685 #4 [ffff8106298dfcd0] event_callback at ffffffff8824c678 #5 [ffff8106298dfd00] dm_table_event at ffffffff8824dd01 #6 [ffff8106298dfd10] __hash_remove at ffffffff882507ad #7 [ffff8106298dfd30] dev_remove at ffffffff88250865 #8 [ffff8106298dfd60] ctl_ioctl at ffffffff88250d80 #9 [ffff8106298dfee0] do_ioctl at ffffffff800418c4 #10 [ffff8106298dff00] vfs_ioctl at ffffffff8002fab9 #11 [ffff8106298dff40] sys_ioctl at ffffffff8004bdaf #12 [ffff8106298dff80] tracesys at ffffffff8005d28d (via system_call) Reported-by: guy keren Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-ioctl.c | 17 +++++++++++++---- drivers/md/dm-uevent.c | 9 ++++----- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index a67942931582..d19854c98184 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -56,6 +56,11 @@ static void dm_hash_remove_all(int keep_open_devices); */ static DECLARE_RWSEM(_hash_lock); +/* + * Protects use of mdptr to obtain hash cell name and uuid from mapped device. + */ +static DEFINE_MUTEX(dm_hash_cells_mutex); + static void init_buckets(struct list_head *buckets) { unsigned int i; @@ -206,7 +211,9 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid)); } dm_get(md); + mutex_lock(&dm_hash_cells_mutex); dm_set_mdptr(md, cell); + mutex_unlock(&dm_hash_cells_mutex); up_write(&_hash_lock); return 0; @@ -224,7 +231,9 @@ static void __hash_remove(struct hash_cell *hc) /* remove from the dev hash */ list_del(&hc->uuid_list); list_del(&hc->name_list); + mutex_lock(&dm_hash_cells_mutex); dm_set_mdptr(hc->md, NULL); + mutex_unlock(&dm_hash_cells_mutex); table = dm_get_table(hc->md); if (table) { @@ -321,7 +330,9 @@ static int dm_hash_rename(uint32_t cookie, const char *old, const char *new) */ list_del(&hc->name_list); old_name = hc->name; + mutex_lock(&dm_hash_cells_mutex); hc->name = new_name; + mutex_unlock(&dm_hash_cells_mutex); list_add(&hc->name_list, _name_buckets + hash_str(new_name)); /* @@ -1582,8 +1593,7 @@ int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid) if (!md) return -ENXIO; - dm_get(md); - down_read(&_hash_lock); + mutex_lock(&dm_hash_cells_mutex); hc = dm_get_mdptr(md); if (!hc || hc->md != md) { r = -ENXIO; @@ -1596,8 +1606,7 @@ int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid) strcpy(uuid, hc->uuid ? : ""); out: - up_read(&_hash_lock); - dm_put(md); + mutex_unlock(&dm_hash_cells_mutex); return r; } diff --git a/drivers/md/dm-uevent.c b/drivers/md/dm-uevent.c index 6f65883aef12..c7c555a8c7b2 100644 --- a/drivers/md/dm-uevent.c +++ b/drivers/md/dm-uevent.c @@ -139,14 +139,13 @@ void dm_send_uevents(struct list_head *events, struct kobject *kobj) list_del_init(&event->elist); /* - * Need to call dm_copy_name_and_uuid from here for now. - * Context of previous var adds and locking used for - * hash_cell not compatable. + * When a device is being removed this copy fails and we + * discard these unsent events. */ if (dm_copy_name_and_uuid(event->md, event->name, event->uuid)) { - DMERR("%s: dm_copy_name_and_uuid() failed", - __func__); + DMINFO("%s: skipping sending uevent for lost device", + __func__); goto uevent_free; } From 8419ee8215942d6bf3814391730421a4897fc410 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 10 Dec 2009 23:51:54 +0000 Subject: [PATCH 139/670] dm snapshot: cope with chunk size larger than origin commit 8e87b9b81b3c370f7e53c1ab6e1c3519ef37a644 upstream. Under some special conditions the snapshot hash_size is calculated as zero. This patch instead sets a minimum value of 64, the same as for the pending exception table. rounddown_pow_of_two(0) is an undefined operation (it expands to shift by -1). init_exception_table with an argument of 0 would fail with -ENOMEM. The way to trigger the problem is to create a snapshot with a chunk size that is larger than the origin device. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-snap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index d135212958f1..8a4a9c838afd 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -553,6 +553,8 @@ static int init_hash_tables(struct dm_snapshot *s) hash_size = min(origin_dev_size, cow_dev_size) >> s->store->chunk_shift; hash_size = min(hash_size, max_buckets); + if (hash_size < 64) + hash_size = 64; hash_size = rounddown_pow_of_two(hash_size); if (init_exception_table(&s->complete, hash_size, DM_CHUNK_CONSECUTIVE_BITS)) From 7d41627824496f9c69ab2da972a72521ebeebf7a Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Thu, 10 Dec 2009 23:51:56 +0000 Subject: [PATCH 140/670] dm crypt: separate essiv allocation from initialisation commit b95bf2d3d5a48b095bffe2a0cd8c40453cf59557 upstream. This patch separates the construction of IV from its initialisation. (For ESSIV it is a hash calculation based on volume key.) Constructor code now preallocates hash tfm and salt array and saves it in a private IV structure. The next patch requires this to reinitialise the wiped IV without reallocating memory when resuming a suspended device. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-crypt.c | 69 +++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 2856bdca2515..e057353555bb 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -71,11 +71,14 @@ struct crypt_iv_operations { int (*ctr)(struct crypt_config *cc, struct dm_target *ti, const char *opts); void (*dtr)(struct crypt_config *cc); + int (*init)(struct crypt_config *cc); int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector); }; struct iv_essiv_private { struct crypto_cipher *tfm; + struct crypto_hash *hash_tfm; + u8 *salt; }; struct iv_benbi_private { @@ -176,12 +179,38 @@ static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector) return 0; } +/* Initialise ESSIV - compute salt but no local memory allocations */ +static int crypt_iv_essiv_init(struct crypt_config *cc) +{ + struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; + struct hash_desc desc; + struct scatterlist sg; + int err; + + sg_init_one(&sg, cc->key, cc->key_size); + desc.tfm = essiv->hash_tfm; + desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + err = crypto_hash_digest(&desc, &sg, cc->key_size, essiv->salt); + if (err) + return err; + + return crypto_cipher_setkey(essiv->tfm, essiv->salt, + crypto_hash_digestsize(essiv->hash_tfm)); +} + static void crypt_iv_essiv_dtr(struct crypt_config *cc) { struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; crypto_free_cipher(essiv->tfm); essiv->tfm = NULL; + + crypto_free_hash(essiv->hash_tfm); + essiv->hash_tfm = NULL; + + kzfree(essiv->salt); + essiv->salt = NULL; } static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, @@ -189,9 +218,6 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, { struct crypto_cipher *essiv_tfm = NULL; struct crypto_hash *hash_tfm = NULL; - struct hash_desc desc; - struct scatterlist sg; - unsigned int saltsize; u8 *salt = NULL; int err; @@ -200,7 +226,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, return -EINVAL; } - /* Hash the cipher key with the given hash algorithm */ + /* Allocate hash algorithm */ hash_tfm = crypto_alloc_hash(opts, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(hash_tfm)) { ti->error = "Error initializing ESSIV hash"; @@ -208,27 +234,14 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, goto bad; } - saltsize = crypto_hash_digestsize(hash_tfm); - salt = kzalloc(saltsize, GFP_KERNEL); + salt = kzalloc(crypto_hash_digestsize(hash_tfm), GFP_KERNEL); if (!salt) { ti->error = "Error kmallocing salt storage in ESSIV"; err = -ENOMEM; goto bad; } - sg_init_one(&sg, cc->key, cc->key_size); - desc.tfm = hash_tfm; - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - err = crypto_hash_digest(&desc, &sg, cc->key_size, salt); - crypto_free_hash(hash_tfm); - hash_tfm = NULL; - - if (err) { - ti->error = "Error calculating hash in ESSIV"; - goto bad; - } - - /* Setup the essiv_tfm with the given salt */ + /* Allocate essiv_tfm */ essiv_tfm = crypto_alloc_cipher(cc->cipher, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(essiv_tfm)) { ti->error = "Error allocating crypto tfm for ESSIV"; @@ -242,14 +255,11 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, err = -EINVAL; goto bad; } - err = crypto_cipher_setkey(essiv_tfm, salt, saltsize); - if (err) { - ti->error = "Failed to set key for ESSIV cipher"; - goto bad; - } - kzfree(salt); + cc->iv_gen_private.essiv.salt = salt; cc->iv_gen_private.essiv.tfm = essiv_tfm; + cc->iv_gen_private.essiv.hash_tfm = hash_tfm; + return 0; bad: @@ -257,7 +267,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, crypto_free_cipher(essiv_tfm); if (hash_tfm && !IS_ERR(hash_tfm)) crypto_free_hash(hash_tfm); - kzfree(salt); + kfree(salt); return err; } @@ -323,6 +333,7 @@ static struct crypt_iv_operations crypt_iv_plain_ops = { static struct crypt_iv_operations crypt_iv_essiv_ops = { .ctr = crypt_iv_essiv_ctr, .dtr = crypt_iv_essiv_dtr, + .init = crypt_iv_essiv_init, .generator = crypt_iv_essiv_gen }; @@ -1054,6 +1065,12 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) goto bad_ivmode; + if (cc->iv_gen_ops && cc->iv_gen_ops->init && + cc->iv_gen_ops->init(cc) < 0) { + ti->error = "Error initialising IV"; + goto bad_slab_pool; + } + cc->iv_size = crypto_ablkcipher_ivsize(tfm); if (cc->iv_size) /* at least a 64 bit sector number should fit in our buffer */ From 80b337ebf9ff4e06cd4185b31d8972193a985262 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Thu, 10 Dec 2009 23:51:57 +0000 Subject: [PATCH 141/670] dm crypt: make wipe message also wipe essiv key commit 542da317668c35036e8471822a564b609d05af66 upstream. The "wipe key" message is used to wipe the volume key from memory temporarily, for example when suspending to RAM. But the initialisation vector in ESSIV mode is calculated from the hashed volume key, so the wipe message should wipe this IV key too and reinitialise it when the volume key is reinstated. This patch adds an IV wipe method called from a wipe message callback. ESSIV is then reinitialised using the init function added by the last patch. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-crypt.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index e057353555bb..959d6d14cee0 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2003 Christophe Saout * Copyright (C) 2004 Clemens Fruhwirth - * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -72,6 +72,7 @@ struct crypt_iv_operations { const char *opts); void (*dtr)(struct crypt_config *cc); int (*init)(struct crypt_config *cc); + int (*wipe)(struct crypt_config *cc); int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector); }; @@ -199,6 +200,17 @@ static int crypt_iv_essiv_init(struct crypt_config *cc) crypto_hash_digestsize(essiv->hash_tfm)); } +/* Wipe salt and reset key derived from volume key */ +static int crypt_iv_essiv_wipe(struct crypt_config *cc) +{ + struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; + unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm); + + memset(essiv->salt, 0, salt_size); + + return crypto_cipher_setkey(essiv->tfm, essiv->salt, salt_size); +} + static void crypt_iv_essiv_dtr(struct crypt_config *cc) { struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; @@ -334,6 +346,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = { .ctr = crypt_iv_essiv_ctr, .dtr = crypt_iv_essiv_dtr, .init = crypt_iv_essiv_init, + .wipe = crypt_iv_essiv_wipe, .generator = crypt_iv_essiv_gen }; @@ -1310,6 +1323,7 @@ static void crypt_resume(struct dm_target *ti) static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) { struct crypt_config *cc = ti->private; + int ret = -EINVAL; if (argc < 2) goto error; @@ -1319,10 +1333,22 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) DMWARN("not suspended during key manipulation."); return -EINVAL; } - if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) - return crypt_set_key(cc, argv[2]); - if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) + if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) { + ret = crypt_set_key(cc, argv[2]); + if (ret) + return ret; + if (cc->iv_gen_ops && cc->iv_gen_ops->init) + ret = cc->iv_gen_ops->init(cc); + return ret; + } + if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) { + if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) { + ret = cc->iv_gen_ops->wipe(cc); + if (ret) + return ret; + } return crypt_wipe_key(cc); + } } error: From a02d9614bab2896760c01477162a5657e06be7ed Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 30 Nov 2009 08:55:18 +0000 Subject: [PATCH 142/670] slc90e66: fix UDMA handling [ Upstream commit ee31527a02b0a8e1aa4a5e4084d2db5fa34737ed ] Fix checking of the currently programmed UDMA mode. Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Sergei Shtylyov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/ide/slc90e66.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c index 9aec78d3bcff..1ccfb40e7215 100644 --- a/drivers/ide/slc90e66.c +++ b/drivers/ide/slc90e66.c @@ -91,8 +91,7 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed) if (!(reg48 & u_flag)) pci_write_config_word(dev, 0x48, reg48|u_flag); - /* FIXME: (reg4a & a_speed) ? */ - if ((reg4a & u_speed) != u_speed) { + if ((reg4a & a_speed) != u_speed) { pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); pci_read_config_word(dev, 0x4a, ®4a); pci_write_config_word(dev, 0x4a, reg4a|u_speed); From 0d975c7ebdebbdf559100c0b09e037679062f052 Mon Sep 17 00:00:00 2001 From: Damian Lukowski Date: Mon, 7 Dec 2009 06:06:15 +0000 Subject: [PATCH 143/670] tcp: Stalling connections: Fix timeout calculation routine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 07f29bc5bbae4e53e982ab956fed7207990a7786 ] This patch fixes a problem in the TCP connection timeout calculation. Currently, timeout decisions are made on the basis of the current tcp_time_stamp and retrans_stamp, which is usually set at the first retransmission. However, if the retransmission fails in tcp_retransmit_skb(), retrans_stamp is not updated and remains zero. This leads to wrong decisions in retransmits_timed_out() if tcp_time_stamp is larger than the specified timeout, which is very likely. In this case, the TCP connection dies after the first attempted (and unsuccessful) retransmission. With this patch, tcp_skb_cb->when is used instead, when retrans_stamp is not available. This bug has been introduced together with retransmits_timed_out() in 2.6.32, as the number of retransmissions has been used for timeout decisions before. The corresponding commit was 6fa12c85031485dff38ce550c24f10da23b0adaa (Revert Backoff [v3]: Calculate TCP's connection close threshold as a time value.). Thanks to Ilpo Järvinen for code suggestions and Frederic Leroy for testing. Reported-by: Frederic Leroy Signed-off-by: Damian Lukowski Acked-by: Ilpo Järvinen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/tcp.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 03a49c703377..842ac4de21ce 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1263,14 +1263,20 @@ static inline struct sk_buff *tcp_write_queue_prev(struct sock *sk, struct sk_bu * TCP connection after "boundary" unsucessful, exponentially backed-off * retransmissions with an initial RTO of TCP_RTO_MIN. */ -static inline bool retransmits_timed_out(const struct sock *sk, +static inline bool retransmits_timed_out(struct sock *sk, unsigned int boundary) { unsigned int timeout, linear_backoff_thresh; + unsigned int start_ts; if (!inet_csk(sk)->icsk_retransmits) return false; + if (unlikely(!tcp_sk(sk)->retrans_stamp)) + start_ts = TCP_SKB_CB(tcp_write_queue_head(sk))->when; + else + start_ts = tcp_sk(sk)->retrans_stamp; + linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN); if (boundary <= linear_backoff_thresh) @@ -1279,7 +1285,7 @@ static inline bool retransmits_timed_out(const struct sock *sk, timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN + (boundary - linear_backoff_thresh) * TCP_RTO_MAX; - return (tcp_time_stamp - tcp_sk(sk)->retrans_stamp) >= timeout; + return (tcp_time_stamp - start_ts) >= timeout; } static inline struct sk_buff *tcp_send_head(struct sock *sk) From 42d8bd7737a65b535d3247392b11fcd0f32303fe Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 1 Dec 2009 15:53:57 -0800 Subject: [PATCH 144/670] ip_fragment: also adjust skb->truesize for packets not owned by a socket [ Upstream commit b2722b1c3a893ec6021508da15b32282ec79f4da ] When a large packet gets reassembled by ip_defrag(), the head skb accounts for all the fragments in skb->truesize. If this packet is refragmented again, skb->truesize is not re-adjusted to reflect only the head size since its not owned by a socket. If the head fragment then gets recycled and reused for another received fragment, it might exceed the defragmentation limits due to its large truesize value. skb_recycle_check() explicitly checks for linear skbs, so any recycled skb should reflect its true size in skb->truesize. Change ip_fragment() to also adjust the truesize value of skbs not owned by a socket. Reported-and-tested-by: Ben Menchaca Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv4/ip_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index f9895180f481..4d50daab0c3e 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -501,8 +501,8 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) if (skb->sk) { frag->sk = skb->sk; frag->destructor = sock_wfree; - truesizes += frag->truesize; } + truesizes += frag->truesize; } /* Everything is OK. Generate! */ From 599343ebd4b057e35955915d73410ea0b987875a Mon Sep 17 00:00:00 2001 From: Stanislav Brabec Date: Tue, 8 Dec 2009 21:00:22 -0800 Subject: [PATCH 145/670] b44 WOL setup: one-bit-off stack corruption kernel panic fix [ Upstream commit: e0188829cb724e7d12a2d4e343b368ff1d6e1471 ] About 50% of shutdowns of b44 Ethernet adapter ends by kernel panic with kernels compiled with stack-protector. Checking b44_magic_pattern() return values, one call of b44_magic_pattern() returns 127. It means, that set_bit(128, pmask) was called on line 1509. It means that bit 0 of 17th byte of pmask was overwritten. But pmask has only 16 bytes. Stack corruption happens. It seems that set_bit() on line 1509 always writes one bit off. The fix does not only solve the stack corruption, but also makes Wake On LAN working on my onboard B44 on Asus A7V-333X mainboard. It seems that this problem affects all kernel versions since commit 725ad800 ([PATCH] b44: add wol for old nic) on 2006-06-20. Signed-off-by: Stanislav Brabec Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/b44.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 2a9132343b66..4869adb69586 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1505,8 +1505,7 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset) for (k = 0; k< ethaddr_bytes; k++) { ppattern[offset + magicsync + (j * ETH_ALEN) + k] = macaddr[k]; - len++; - set_bit(len, (unsigned long *) pmask); + set_bit(len++, (unsigned long *) pmask); } } return len - 1; From 257abc89a7765c57137811419caac5efca2e7b2d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 9 Dec 2009 23:44:43 -0800 Subject: [PATCH 146/670] sparc64: Don't specify IRQF_SHARED for LDC interrupts. [ Upstream commit 08a036d583409e3517e3d15b7478d029b25f2cf2 ] IRQF_SHARED and IRQF_DISABLED don't mix. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/ldc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index cb3c72c45aab..e0ba898e30cf 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c @@ -1242,13 +1242,13 @@ int ldc_bind(struct ldc_channel *lp, const char *name) snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name); err = request_irq(lp->cfg.rx_irq, ldc_rx, - IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED, + IRQF_SAMPLE_RANDOM | IRQF_DISABLED, lp->rx_irq_name, lp); if (err) return err; err = request_irq(lp->cfg.tx_irq, ldc_tx, - IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED, + IRQF_SAMPLE_RANDOM | IRQF_DISABLED, lp->tx_irq_name, lp); if (err) { free_irq(lp->cfg.rx_irq, lp); From c141dab88c2afe8a1d43b64f55db11523cc4ec2d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 9 Dec 2009 01:39:09 -0800 Subject: [PATCH 147/670] sparc64: Fix overly strict range type matching for PCI devices. [ Upstream commit 4230fa3b89ea1c413766bd411a8315a3d05aa6c7 ] When we are trying to see if a range property entry applies to a given address, we are overly strict about the type. We should only allow I/O ranges for I/O addresses, and only allow CONFIG space ranges for CONFIG space address. However for MEM ranges, they come in 32-bit and 64-bit flavors. And a lack of an exact match is OK if the range is 32-bit and the address is 64-bit. We can assign a 64-bit address properly into a 32-bit parent range just fine. So allow it. Reported-by: Patrick Finnegan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/of_device_64.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 881947e59e95..0a6f2d1798d1 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c @@ -104,9 +104,19 @@ static int of_bus_pci_map(u32 *addr, const u32 *range, int i; /* Check address type match */ - if ((addr[0] ^ range[0]) & 0x03000000) - return -EINVAL; + if (!((addr[0] ^ range[0]) & 0x03000000)) + goto type_match; + /* Special exception, we can map a 64-bit address into + * a 32-bit range. + */ + if ((addr[0] & 0x03000000) == 0x03000000 && + (range[0] & 0x03000000) == 0x02000000) + goto type_match; + + return -EINVAL; + +type_match: if (of_out_of_range(addr + 1, range + 1, range + na + pna, na - 1, ns)) return -EINVAL; From 6ec683e0dc39688557189eed2153367d0acf61e2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 9 Dec 2009 01:43:45 -0800 Subject: [PATCH 148/670] sparc64: Fix stack debugging IRQ stack regression. [ Upstream commit 166e553a575f09485f6d0df8a1ef3c5991f7d953 ] Commit 4f70f7a91bffdcc39f088748dc678953eb9a3fbd (sparc64: Implement IRQ stacks.) has two bugs. First, the softirq range check forgets to subtract STACK_BIAS before comparing with %sp. Next, on failure the wrong label is jumped to, resulting in a bogus stack being loaded. Reported-by: Igor Kovalenko Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/lib/mcount.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/sparc/lib/mcount.S b/arch/sparc/lib/mcount.S index 7ce9c65f3592..24b8b12deed2 100644 --- a/arch/sparc/lib/mcount.S +++ b/arch/sparc/lib/mcount.S @@ -64,8 +64,9 @@ mcount: 2: sethi %hi(softirq_stack), %g3 or %g3, %lo(softirq_stack), %g3 ldx [%g3 + %g1], %g7 + sub %g7, STACK_BIAS, %g7 cmp %sp, %g7 - bleu,pt %xcc, 2f + bleu,pt %xcc, 3f sethi %hi(THREAD_SIZE), %g3 add %g7, %g3, %g7 cmp %sp, %g7 @@ -75,7 +76,7 @@ mcount: * again, we are already trying to output the stack overflow * message. */ - sethi %hi(ovstack), %g7 ! cant move to panic stack fast enough +3: sethi %hi(ovstack), %g7 ! cant move to panic stack fast enough or %g7, %lo(ovstack), %g7 add %g7, OVSTACKSIZE, %g3 sub %g3, STACK_BIAS + 192, %g3 From 3263c617570ed7c7292ea484d1fdf31687d110ee Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 5 Dec 2009 17:17:55 -0800 Subject: [PATCH 149/670] sparc: Set UTS_MACHINE correctly. [ Upstream commit 7f5620a5fcd658f219e85831d3691908f1eccbde ] "ARCH" can be just about anything, so we shouldn't end up with UTS_MACHINE of "sparc" in a 64-bit kernel build just because someone set the personality using 'sparc32' or similar. CONFIG_SPARC64 drives the compilation and therefore provides the definitive value, not "ARCH". This mirrors commit 8c6531f7a99f29ba8817ffb12cc9ecf190049bd6 (x86: correctly set UTS_MACHINE for "make ARCH=x86") Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index dfe272d14465..113225b241e0 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -27,6 +27,7 @@ AS := $(AS) -32 LDFLAGS := -m elf32_sparc CHECKFLAGS += -D__sparc__ export BITS := 32 +UTS_MACHINE := sparc #KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7 KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 @@ -46,6 +47,7 @@ CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64 LDFLAGS := -m elf64_sparc export BITS := 64 +UTS_MACHINE := sparc64 KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \ From e75a313897fa83be86afb38a6e4415e923cdca80 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 23 Nov 2009 18:42:36 -0600 Subject: [PATCH 150/670] b43legacy: avoid PPC fault during resume commit 316a4d966cae3c2dec83ebb1ee1a3515f97b30ff upstream. For PPC architecture with PHY Revision < 3, a read of the register B43_MMIO_HWENABLED_LO will cause a CPU fault unless b43legacy_status() returns a value of 2 (B43legacy_STAT_STARTED); however, one finds that the driver is unable to associate after resuming from hibernation unless this routine returns 1. To satisfy both conditions, the routine is rewritten to return TRUE whenever b43legacy_status() returns a value < 2. This patch fixes the second problem listed in the postings for Red Hat Bugzilla #538523. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43legacy/rfkill.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index 8783022db11e..d579df72b783 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c @@ -34,6 +34,13 @@ bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK)) return 1; } else { + /* To prevent CPU fault on PPC, do not read a register + * unless the interface is started; however, on resume + * for hibernation, this routine is entered early. When + * that happens, unconditionally return TRUE. + */ + if (b43legacy_status(dev) < B43legacy_STAT_STARTED) + return 1; if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO) & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK) return 1; From 7847a351aaaa21696dd07f412c493786b53a1999 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 Nov 2009 23:40:09 +0100 Subject: [PATCH 151/670] tracing: Fix event format export commit 811cb50baf63461ce0bdb234927046131fc7fa8b upstream. For some reason the export of the event print format to userspace uses '#fmt' which breaks if the format string is anything but a plain string, for example if it is built with macros then the macro names are exported instead of their contents. Use "\"%s\"", fmt instead of "%s", #fmt to export the string and not the way it is built. For example, in net/mac80211/driver-trace.h for the trace event drv_start there is: TP_printk( LOCAL_PR_FMT, LOCAL_PR_ARG ) Which use to produce: print fmt: LOCAL_PR_FMT, REC->wiphy_name Now produces: print fmt: "%s", REC->wiphy_name Signed-off-by: Johannes Berg LKML-Reference: <20091113224009.GB23942@elte.hu> Signed-off-by: Steven Rostedt Cc: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/trace/ftrace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index cc0d9667e182..dacb8ef67000 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -159,7 +159,7 @@ #undef __get_str #undef TP_printk -#define TP_printk(fmt, args...) "%s, %s\n", #fmt, __stringify(args) +#define TP_printk(fmt, args...) "\"%s\", %s\n", fmt, __stringify(args) #undef TP_fast_assign #define TP_fast_assign(args...) args From 978962f22c95c70f9018a9181c73525d26f0f3bd Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 16 Dec 2009 11:51:41 -0500 Subject: [PATCH 152/670] ath9k: Fix TX hang poll routine This is a backport of upstream commit: 332c556633b8c5fb4e890b1783122f2315526590 When TX is hung, the chip is reset. Ensure that the chip is awake by using the PS wrappers. Signed-off-by: Sujith Signed-off-by: Luis R. Rodriguez Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 42551a48c8ac..972e775b3623 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2065,7 +2065,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work) if (needreset) { DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n"); + ath9k_ps_wakeup(sc); ath_reset(sc, false); + ath9k_ps_restore(sc); } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, From 022fe0eb677b07aa37a3f88eab5ed47be2faffb5 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 16 Dec 2009 11:51:42 -0500 Subject: [PATCH 153/670] ath9k: fix processing of TX PS null data frames This is a backport of upstream commit: e7824a50662f7f79b1a739f705b4d906c31cf221 When mac80211 was telling us to go into Powersave we listened and immediately turned RX off. This meant hardware would not see the ACKs from the AP we're associated with and hardware we'd end up retransmiting the null data frame in a loop helplessly. Fix this by keeping track of the transmitted nullfunc frames and only when we are sure the AP has sent back an ACK do we go ahead and shut RX off. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Vivek Natarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/ath9k.h | 3 +++ drivers/net/wireless/ath/ath9k/mac.c | 2 ++ drivers/net/wireless/ath/ath9k/mac.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 9 ++++++++- drivers/net/wireless/ath/ath9k/xmit.c | 16 ++++++++++++++++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1d59f10f68da..cdb90c5bf39b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -139,6 +139,7 @@ struct ath_buf { dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_buf_addr; /* physical addr of data buffer */ bool bf_stale; + bool bf_isnullfunc; u16 bf_flags; struct ath_buf_state bf_state; dma_addr_t bf_dmacontext; @@ -524,6 +525,8 @@ struct ath_led { #define SC_OP_BEACON_SYNC BIT(19) #define SC_OP_BTCOEX_ENABLED BIT(20) #define SC_OP_BT_PRIORITY_DETECTED BIT(21) +#define SC_OP_NULLFUNC_COMPLETED BIT(22) +#define SC_OP_PS_ENABLED BIT(23) struct ath_bus_ops { void (*read_cachesize)(struct ath_softc *sc, int *csz); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 800bfab94635..561a40ed0564 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -222,6 +222,8 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) ds->ds_txstat.ts_status = 0; ds->ds_txstat.ts_flags = 0; + if (ads->ds_txstatus1 & AR_FrmXmitOK) + ds->ds_txstat.ts_status |= ATH9K_TX_ACKED; if (ads->ds_txstatus1 & AR_ExcessiveRetries) ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; if (ads->ds_txstatus1 & AR_Filtered) diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index f56e77da6c3e..ff65f85bd855 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -76,6 +76,7 @@ #define ATH9K_TXERR_FIFO 0x04 #define ATH9K_TXERR_XTXOP 0x08 #define ATH9K_TXERR_TIMER_EXPIRED 0x10 +#define ATH9K_TX_ACKED 0x20 #define ATH9K_TX_BA 0x01 #define ATH9K_TX_PWRMGMT 0x02 diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 43d2be9867fc..59359e348ee3 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2327,6 +2327,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_PS) { if (conf->flags & IEEE80211_CONF_PS) { + sc->sc_flags |= SC_OP_PS_ENABLED; if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { @@ -2334,11 +2335,17 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); } - ath9k_hw_setrxabort(sc->sc_ah, 1); } sc->ps_enabled = true; + if ((sc->sc_flags & SC_OP_NULLFUNC_COMPLETED)) { + sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; + sc->ps_enabled = true; + ath9k_hw_setrxabort(sc->sc_ah, 1); + } } else { sc->ps_enabled = false; + sc->sc_flags &= ~(SC_OP_PS_ENABLED | + SC_OP_NULLFUNC_COMPLETED); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 972e775b3623..e78bd5768075 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1592,6 +1592,13 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, } bf->bf_buf_addr = bf->bf_dmacontext; + + if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) { + bf->bf_isnullfunc = true; + sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; + } else + bf->bf_isnullfunc = false; + return 0; } @@ -1989,6 +1996,15 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) if (ds == txq->axq_gatingds) txq->axq_gatingds = NULL; + if (bf->bf_isnullfunc && + (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { + if ((sc->sc_flags & SC_OP_PS_ENABLED)) { + sc->ps_enabled = true; + ath9k_hw_setrxabort(sc->sc_ah, 1); + } else + sc->sc_flags |= SC_OP_NULLFUNC_COMPLETED; + } + /* * Remove ath_buf's of the same transmit unit from txq, * however leave the last descriptor back as the holding From e82a3a2db53b6df3a211c7b90c793d61fcb6ddae Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 16 Dec 2009 11:51:43 -0500 Subject: [PATCH 154/670] ath9k: Fix maximum tx fifo settings for single stream devices This is a backport of upstream commit: f4709fdf683e1ed37b321c258b614ebe39752bf3 Atheros single stream AR9285 and AR9271 have half the PCU TX FIFO buffer size of that of dual stream devices. Dual stream devices have a max PCU TX FIFO size of 8 KB while single stream devices have 4 KB. Single stream devices have an issue though and require hardware only to use half of the amount of its capable PCU TX FIFO size, 2 KB and this requires a change in software. Technically a change would not have been required (except for frame burst considerations of 128 bytes) if these devices would have been able to use the full 4 KB of the PCU TX FIFO size but our systems engineers recommend 2 KB to be used only. We enforce this through software by reducing the max frame triggger level to 2 KB. Fixing the max frame trigger level should then have a few benefits: * The PER will now be adjusted as designed for underruns when the max trigger level is reached. This should help alleviate the bus as the rate control algorithm chooses a slower rate which should ensure frames are transmitted properly under high system bus load. * The poll we use on our TX queues should now trigger and work as designed for single stream devices. The hardware passes data from each TX queue on the PCU TX FIFO queue respecting each queue's priority. The new trigger level ensures this seeding of the PCU TX FIFO queue occurs as designed which could mean avoiding false resets and actually reseting hw correctly when a TX queue is indeed stuck. * Some undocumented / unsupported behaviour could have been triggered when the max trigger level level was being set to 4 KB on single stream devices. Its not clear what this issue was to me yet. Cc: Kyungwan Nam Cc: Bennyam Malavazi Cc: Stephen Chen Cc: Shan Palanisamy Cc: Paul Shaw Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Luis R. Rodriguez Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/hw.c | 11 ++++++++++- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/mac.c | 4 ++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ca7694caf364..c7aa05a82877 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -937,6 +937,11 @@ int ath9k_hw_init(struct ath_hw *ah) DPRINTF(ah->ah_sc, ATH_DBG_RESET, "serialize_regmode is %d\n", ah->config.serialize_regmode); + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) + ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1; + else + ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; + if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Mac Chip Rev 0x%02x.%x is not supported by " @@ -3670,7 +3675,11 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->keycache_size = AR_KEYTABLE_SIZE; pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; - pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; + + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) + pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; + else + pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; if (AR_SREV_9285_10_OR_LATER(ah)) pCap->num_gpio_pins = AR9285_NUM_GPIO; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b89234571829..57f14630e2a1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -218,6 +218,7 @@ struct ath9k_ops_config { #define AR_SPUR_FEEQ_BOUND_HT20 10 int spurmode; u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; + u8 max_txtrig_level; }; enum ath9k_int { diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 561a40ed0564..d4d9d828aff4 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -70,7 +70,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) u32 txcfg, curLevel, newLevel; enum ath9k_int omask; - if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD) + if (ah->tx_trig_level >= ah->config.max_txtrig_level) return false; omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); @@ -79,7 +79,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) curLevel = MS(txcfg, AR_FTRIG); newLevel = curLevel; if (bIncTrigLevel) { - if (curLevel < MAX_TX_FIFO_THRESHOLD) + if (curLevel < ah->config.max_txtrig_level) newLevel++; } else if (curLevel > MIN_TX_FIFO_THRESHOLD) newLevel--; From 0f77b958dccf9d3b59d986ea160f84b50c646712 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Dec 2009 11:51:44 -0500 Subject: [PATCH 155/670] ath9k: fix tx status reporting This is a backport of upstream commit: e8c6342d989e241513baeba4b05a04b6b1f3bc8b This patch fixes a bug in ath9k's tx status check, which caused mac80211 to consider regularly transmitted unicast frames as un-acked. When checking the ts_status field for errors, it needs to be masked with ATH9K_TXERR_FILT, because this field also contains other fields like ATH9K_TX_ACKED. Without this patch, AP mode is pretty much unusable, as hostapd checks the ACK status for the frames that it injects. Signed-off-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index e78bd5768075..47539094524e 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2020,7 +2020,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) if (bf_isaggr(bf)) txq->axq_aggr_depth--; - txok = (ds->ds_txstat.ts_status == 0); + txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT); txq->axq_tx_inprogress = false; spin_unlock_bh(&txq->axq_lock); From 58cd74bafb36b884abe67998cdef4203ae01769f Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Wed, 16 Dec 2009 11:51:45 -0500 Subject: [PATCH 156/670] mac80211: Fix dynamic power save for scanning. Upstream commit: 7c3f4bbedc241ddcd3abe1f419c356e625231da1 Not only ps_sdata but also IEEE80211_CONF_PS is to be considered before restoring PS in scan_ps_disable(). For instance, when ps_sdata is set but CONF_PS is not set just because the dynamic timer is still running, a sw scan leads to setting of CONF_PS in scan_ps_disable instead of restarting the dynamic PS timer. Also for the above case, a null data frame is to be sent after returning to operating channel which was not happening with the current implementation. This patch fixes this too. Signed-off-by: Vivek Natarajan Reviewed-by: Kalle Valo Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/scan.c | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 10d316e455de..5a461641e94e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -808,6 +808,7 @@ struct ieee80211_local { unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ bool pspolling; + bool scan_ps_enabled; /* * PS can only be enabled when we have exactly one managed * interface (and monitors) in PS, this then points there. diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 736537fc03dd..1a4190947970 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -196,7 +196,8 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; - bool ps = false; + + local->scan_ps_enabled = false; /* FIXME: what to do when local->pspolling is true? */ @@ -204,12 +205,13 @@ static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata) cancel_work_sync(&local->dynamic_ps_enable_work); if (local->hw.conf.flags & IEEE80211_CONF_PS) { - ps = true; + local->scan_ps_enabled = true; local->hw.conf.flags &= ~IEEE80211_CONF_PS; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); } - if (!ps || !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) + if (!(local->scan_ps_enabled) || + !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) /* * If power save was enabled, no need to send a nullfunc * frame because AP knows that we are sleeping. But if the @@ -230,7 +232,7 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) if (!local->ps_sdata) ieee80211_send_nullfunc(local, sdata, 0); - else { + else if (local->scan_ps_enabled) { /* * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware * will send a nullfunc frame with the powersave bit set @@ -246,6 +248,16 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) */ local->hw.conf.flags |= IEEE80211_CONF_PS; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } else if (local->hw.conf.dynamic_ps_timeout > 0) { + /* + * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer + * had been running before leaving the operating channel, + * restart the timer now and send a nullfunc frame to inform + * the AP that we are awake. + */ + ieee80211_send_nullfunc(local, sdata, 0); + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); } } From e8d9252227536dc8bd4e2d254d16b5feef542496 Mon Sep 17 00:00:00 2001 From: Li Peng Date: Wed, 16 Dec 2009 16:33:25 +0100 Subject: [PATCH 157/670] drm/i915: Fix sync to vblank when VGA output is turned off commit 778c902640530371a169ad1c03566e7c51b09874 upstream In current vblank-wait implementation, if we turn off VGA output, drm_wait_vblank will still wait on the disabled pipe until timeout, because vblank on the pipe is assumed be enabled. This would cause slow system response on some system such as moblin. This patch resolve the issue by adding a drm helper function drm_vblank_off which explicitly clear vblank_enabled[crtc], wake up any waiting queue and save last vblank counter before turning off crtc. It also slightly change drm_vblank_get to ensure that we will will return immediately if trying to wait on a disabled pipe. Signed-off-by: Li Peng Reviewed-by: Jesse Barnes [anholt: hand-applied for conflicts with overlay changes] Signed-off-by: Eric Anholt Cc: Stefan Bader Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_irq.c | 34 +++++++++++++++++++++------- drivers/gpu/drm/i915/intel_display.c | 1 + include/drm/drmP.h | 1 + 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 0a6f0b3bdc78..332d743a9a8c 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -429,15 +429,21 @@ int drm_vblank_get(struct drm_device *dev, int crtc) spin_lock_irqsave(&dev->vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ - if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 && - !dev->vblank_enabled[crtc]) { - ret = dev->driver->enable_vblank(dev, crtc); - DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); - if (ret) + if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { + if (!dev->vblank_enabled[crtc]) { + ret = dev->driver->enable_vblank(dev, crtc); + DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); + if (ret) + atomic_dec(&dev->vblank_refcount[crtc]); + else { + dev->vblank_enabled[crtc] = 1; + drm_update_vblank_count(dev, crtc); + } + } + } else { + if (!dev->vblank_enabled[crtc]) { atomic_dec(&dev->vblank_refcount[crtc]); - else { - dev->vblank_enabled[crtc] = 1; - drm_update_vblank_count(dev, crtc); + ret = -EINVAL; } } spin_unlock_irqrestore(&dev->vbl_lock, irqflags); @@ -464,6 +470,18 @@ void drm_vblank_put(struct drm_device *dev, int crtc) } EXPORT_SYMBOL(drm_vblank_put); +void drm_vblank_off(struct drm_device *dev, int crtc) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev->vbl_lock, irqflags); + DRM_WAKEUP(&dev->vbl_queue[crtc]); + dev->vblank_enabled[crtc] = 0; + dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); +} +EXPORT_SYMBOL(drm_vblank_off); + /** * drm_vblank_pre_modeset - account for vblanks across mode sets * @dev: DRM device diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 099f420de57a..355b637a5437 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1845,6 +1845,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) intel_update_watermarks(dev); /* Give the overlay scaler a chance to disable if it's on this pipe */ //intel_crtc_dpms_video(crtc, FALSE); TODO + drm_vblank_off(dev, pipe); if (dev_priv->cfb_plane == plane && dev_priv->display.disable_fbc) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index c8e64bbadbcf..9d3d684103f6 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1295,6 +1295,7 @@ extern u32 drm_vblank_count(struct drm_device *dev, int crtc); extern void drm_handle_vblank(struct drm_device *dev, int crtc); extern int drm_vblank_get(struct drm_device *dev, int crtc); extern void drm_vblank_put(struct drm_device *dev, int crtc); +extern void drm_vblank_off(struct drm_device *dev, int crtc); extern void drm_vblank_cleanup(struct drm_device *dev); /* Modesetting support */ extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); From 3dac78c65b4c503199f1ef157e2934eea33425e8 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 15 Dec 2009 16:47:01 -0800 Subject: [PATCH 158/670] memcg: fix memory.memsw.usage_in_bytes for root cgroup commit cd9b45b78a61e8df250e69385c74e729e5b66abf upstream. A memory cgroup has a memory.memsw.usage_in_bytes file. It shows the sum of the usage of pages and swapents in the cgroup. Presently the root cgroup's memsw.usage_in_bytes shows the wrong value - the number of swapents are not added. So take MEM_CGROUP_STAT_SWAPOUT into account. Signed-off-by: Kirill A. Shutemov Reviewed-by: Daisuke Nishimura Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memcontrol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index f99f5991d6bb..63140151b618 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2541,6 +2541,7 @@ static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) val += idx_val; mem_cgroup_get_recursive_idx_stat(mem, MEM_CGROUP_STAT_SWAPOUT, &idx_val); + val += idx_val; val <<= PAGE_SHIFT; } else val = res_counter_read_u64(&mem->memsw, name); From 5279bfc6293bd98c3adaf94e5861e9001669c432 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Wed, 9 Dec 2009 01:36:21 +0000 Subject: [PATCH 159/670] thinkpad-acpi: fix default brightness_mode for R50e/R51 commit a9f8eacca4e9e8693de9b896c1fa7aadaa9402e8 upstream. According to a report, the R50e wants EC-based brightness control, even if it uses an Intel GPU. The current driver default was reported to not work at all. This bug can be worked around by the "brightness_mode=3" module parameter. Change the default of the R50e and R51 2xxx models (which use the same EC firmware, 1V) to TPACPI_BRGHT_Q_EC, but keep TPACPI_BRGHT_Q_ASK set for now, as I'd like to get more reports. This fixes a regression caused by commit 59fe4fe34d7afdf63208124f313be9056feaa2f4, "thinkpad-acpi: fix incorrect use of TPACPI_BRGHT_MODE_ECNVRAM" Kernel 2.6.31 also needs this fix. Reported-by: Ferenc Wagner Tested-by: Ferenc Wagner Signed-off-by: Henrique de Moraes Holschuh Cc: stable@kernel.org Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/thinkpad_acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index a848c7e20aeb..9c6d5a929e96 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6123,8 +6123,8 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = { /* Models with Intel Extreme Graphics 2 */ TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), - TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), - TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), + TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), + TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), /* Models with Intel GMA900 */ TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ From 1794daecdb3e628cb1fcb8aee8d3ac30571aa753 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Wed, 9 Dec 2009 01:36:22 +0000 Subject: [PATCH 160/670] thinkpad-acpi: preserve rfkill state across suspend/resume commit 208b996b6c460285650d39b2330f8ef82c007d10 upstream. Since the rfkill rework in 2.6.31, the driver is always resuming with the radios disabled. Change thinkpad-acpi to ask the firmware to resume with the radios in the last state. This fixes the Bluetooth and WWAN rfkill switches. Note that it means we respect the firmware's oddities. Should the user toggle the hardware rfkill switch on and off, it might cause the radios to resume enabled. UWB is an unknown quantity since it has nowhere the same level of firmware support (no control over state storage in NVRAM, for example), and might need further fixing. Testers welcome. This change fixes a regression from 2.6.30. Reported-by: Jerone Young Reported-by: Ian Molton Signed-off-by: Henrique de Moraes Holschuh Tested-by: Ian Molton Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/thinkpad_acpi.c | 32 +++++----------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 9c6d5a929e96..1ee734c14cc1 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3866,15 +3866,6 @@ enum { #define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw" -static void bluetooth_suspend(pm_message_t state) -{ - /* Try to make sure radio will resume powered off */ - if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd", - TP_ACPI_BLTH_PWR_OFF_ON_RESUME)) - vdbg_printk(TPACPI_DBG_RFKILL, - "bluetooth power down on resume request failed\n"); -} - static int bluetooth_get_status(void) { int status; @@ -3908,10 +3899,9 @@ static int bluetooth_set_status(enum tpacpi_rfkill_state state) #endif /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */ + status = TP_ACPI_BLUETOOTH_RESUMECTRL; if (state == TPACPI_RFK_RADIO_ON) - status = TP_ACPI_BLUETOOTH_RADIOSSW; - else - status = 0; + status |= TP_ACPI_BLUETOOTH_RADIOSSW; if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) return -EIO; @@ -4050,7 +4040,6 @@ static struct ibm_struct bluetooth_driver_data = { .read = bluetooth_read, .write = bluetooth_write, .exit = bluetooth_exit, - .suspend = bluetooth_suspend, .shutdown = bluetooth_shutdown, }; @@ -4068,15 +4057,6 @@ enum { #define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" -static void wan_suspend(pm_message_t state) -{ - /* Try to make sure radio will resume powered off */ - if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd", - TP_ACPI_WGSV_PWR_OFF_ON_RESUME)) - vdbg_printk(TPACPI_DBG_RFKILL, - "WWAN power down on resume request failed\n"); -} - static int wan_get_status(void) { int status; @@ -4109,11 +4089,10 @@ static int wan_set_status(enum tpacpi_rfkill_state state) } #endif - /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */ + /* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */ + status = TP_ACPI_WANCARD_RESUMECTRL; if (state == TPACPI_RFK_RADIO_ON) - status = TP_ACPI_WANCARD_RADIOSSW; - else - status = 0; + status |= TP_ACPI_WANCARD_RADIOSSW; if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) return -EIO; @@ -4251,7 +4230,6 @@ static struct ibm_struct wan_driver_data = { .read = wan_read, .write = wan_write, .exit = wan_exit, - .suspend = wan_suspend, .shutdown = wan_shutdown, }; From 67f3bf7f5b9ae151ef227b31d343c677d1f9b789 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Wed, 2 Dec 2009 14:24:37 +0800 Subject: [PATCH 161/670] ipw2100: fix rebooting hang with driver loaded commit 52ce3e9a7db754b78cf2cbabc87013f921b25b28 upstream. Add PCI .shutdown method so that we can disable the device during shutdown or reboot. Without this, the reboot doesn't work well on some platforms. This fixes http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2124 Tested-by: pablo Signed-off-by: Zhu Yi Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ipw2x00/ipw2100.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 6e2fc0cb6f8a..43102bff8dee 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6487,6 +6487,16 @@ static int ipw2100_resume(struct pci_dev *pci_dev) } #endif +static void ipw2100_shutdown(struct pci_dev *pci_dev) +{ + struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); + + /* Take down the device; powers it off, etc. */ + ipw2100_down(priv); + + pci_disable_device(pci_dev); +} + #define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x } static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = { @@ -6550,6 +6560,7 @@ static struct pci_driver ipw2100_pci_driver = { .suspend = ipw2100_suspend, .resume = ipw2100_resume, #endif + .shutdown = ipw2100_shutdown, }; /** From 6088ca9288f87655ceac3bde1dbb921bf4ce5d86 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 15 Dec 2009 16:46:40 -0800 Subject: [PATCH 162/670] matroxfb: fix problems with display stability commit 8c651311a3a08c1e4815de6933e00a760e498dae upstream. Regression caused in 2.6.23 and then despite repeated requests never fixed or dealt with (Petr promised to sort it in 2008 but seems to have forgotten). Enough is enough - remove the problem line that was added. If it upsets someone they've had two years to deal with it and at the very least it'll rattle their cage and wake them up. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=9709 Signed-off-by: Alan Cox Reported-by: Damon Tested-by: Ruud van Melick Cc: Petr Vandrovec Cc: Pekka Enberg Cc: Paul A. Clarke Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/matrox/g450_pll.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c index 09f6e045d5be..c15f8a57498e 100644 --- a/drivers/video/matrox/g450_pll.c +++ b/drivers/video/matrox/g450_pll.c @@ -368,7 +368,8 @@ static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, M1064_XDVICLKCTRL_C1DVICLKEN | M1064_XDVICLKCTRL_DVILOOPCTL | M1064_XDVICLKCTRL_P1LOOPBWDTCTL; - matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); + /* Setting this breaks PC systems so don't do it */ + /* matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); */ matroxfb_DAC_out(minfo, M1064_XPWRCTRL, xpwrctrl); From 9bcfc6c08e4c9c29b24311307d7d4714572810ec Mon Sep 17 00:00:00 2001 From: Peter Feuerer Date: Tue, 17 Nov 2009 14:27:37 -0800 Subject: [PATCH 163/670] acerhdf: add new BIOS versions commit 360657463679dee44f0b167ffa61f563b4fee101 upstream. Added new BIOS versions for following netbooks: Acer 1410, Gateway LT31, Packard Bell DOA150. As the Gateway LT31 machines have different register values for setting and checking the off-state, the "cmd_off" variable has been splitted up to "cmd_off" and "chk_off". Signed-off-by: Peter Feuerer Cc: Borislav Petkov Cc: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/acerhdf.c | 63 ++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index ab64522aaa64..d8b4229108b8 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -52,7 +52,7 @@ */ #undef START_IN_KERNEL_MODE -#define DRV_VER "0.5.18" +#define DRV_VER "0.5.20" /* * According to the Atom N270 datasheet, @@ -112,12 +112,14 @@ module_param_string(force_product, force_product, 16, 0); MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check"); /* - * cmd_off: to switch the fan completely off / to check if the fan is off + * cmd_off: to switch the fan completely off + * chk_off: to check if the fan is off * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then * the fan speed depending on the temperature */ struct fancmd { u8 cmd_off; + u8 chk_off; u8 cmd_auto; }; @@ -134,32 +136,41 @@ struct bios_settings_t { /* Register addresses and values for different BIOS versions */ static const struct bios_settings_t bios_tbl[] = { /* AOA110 */ - {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, - {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, - {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, - {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, - {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, + {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, + {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, + {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, + {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, + {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, + {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, + {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x21, 0x00} }, + {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x21, 0x00} }, + {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x21, 0x00} }, /* AOA150 */ - {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} }, + {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} }, + /* Acer 1410 */ + {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, /* special BIOS / other */ - {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, - {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} }, - {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} }, - {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, - {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, + {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} }, + {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Gateway ", "LT31 ", "v1.3103 ", 0x55, 0x58, + {0x10, 0x0f, 0x00} }, + {"Gateway ", "LT31 ", "v1.3201 ", 0x55, 0x58, + {0x10, 0x0f, 0x00} }, + {"Gateway ", "LT31 ", "v1.3302 ", 0x55, 0x58, + {0x10, 0x0f, 0x00} }, + {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} }, + {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} }, + {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, /* pewpew-terminator */ - {"", "", "", 0, 0, {0, 0} } + {"", "", "", 0, 0, {0, 0, 0} } }; static const struct bios_settings_t *bios_cfg __read_mostly; @@ -183,7 +194,7 @@ static int acerhdf_get_fanstate(int *state) if (ec_read(bios_cfg->fanreg, &fan)) return -EINVAL; - if (fan != bios_cfg->cmd.cmd_off) + if (fan != bios_cfg->cmd.chk_off) *state = ACERHDF_FAN_AUTO; else *state = ACERHDF_FAN_OFF; From f996ff1a936f66ea00ecc760ab19e5f663579278 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Mon, 7 Dec 2009 22:05:50 +0100 Subject: [PATCH 164/670] asus-laptop: change light sens default values. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d951d4cc84e8b5ddb8e0ab81cf6a72cc73fdd668 upstream. The light sensor disable brightness key and /sys/class/backlight/ control. There was a lot of report from users who didn't understand why they couldn't change their brightness, including: https://bugs.launchpad.net/bugs/222171 https://bugzilla.novell.com/show_bug.cgi?id=514747 http://bugzilla.kernel.org/show_bug.cgi?id=13671 http://bugzilla.kernel.org/show_bug.cgi?id=14432 Now the light sensor is disabled, and if the user want to enable it, the level should be ok. The funny thing is that comments where ok, not code. Cc: stable@kernel.org Cc: Thomas Renninger Cc: Peter Küppers Cc: Michael Franzl Cc: Ian Turner Signed-off-by: Corentin Chary Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/asus-laptop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index b39d2bb3e75b..849359a80942 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1283,8 +1283,8 @@ static int asus_hotk_add(struct acpi_device *device) hotk->ledd_status = 0xFFF; /* Set initial values of light sensor and level */ - hotk->light_switch = 1; /* Default to light sensor disabled */ - hotk->light_level = 0; /* level 5 for sensor sensitivity */ + hotk->light_switch = 0; /* Default to light sensor disabled */ + hotk->light_level = 5; /* level 5 for sensor sensitivity */ if (ls_switch_handle) set_light_sens_switch(hotk->light_switch); From f0cc8412be0a164f9472f161dfd74fc1ca6ac284 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 10 Dec 2009 08:43:16 +0900 Subject: [PATCH 165/670] vmalloc: conditionalize build of pcpu_get_vm_areas() No matching upstream commit as it was resolved differently there. pcpu_get_vm_areas() is used only when dynamic percpu allocator is used by the architecture. In 2.6.32, ia64 doesn't use dynamic percpu allocator and has a macro which makes pcpu_get_vm_areas() buggy via local/global variable aliasing and triggers compile warning. The problem is fixed in upstream and ia64 uses dynamic percpu allocators, so the only left issue is inclusion of unnecessary code and compile warning on ia64 on 2.6.32. Don't build pcpu_get_vm_areas() if legacy percpu allocator is in use. Signed-off-by: Tejun Heo Reported-by: Jan Beulich Signed-off-by: Greg Kroah-Hartman --- include/linux/vmalloc.h | 2 ++ mm/vmalloc.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 227c2a585e4f..3c123c35c94e 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -115,9 +115,11 @@ extern rwlock_t vmlist_lock; extern struct vm_struct *vmlist; extern __init void vm_area_register_early(struct vm_struct *vm, size_t align); +#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets, const size_t *sizes, int nr_vms, size_t align, gfp_t gfp_mask); +#endif void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 0f551a4a44cd..775872681d0c 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1993,6 +1993,7 @@ void free_vm_area(struct vm_struct *area) } EXPORT_SYMBOL_GPL(free_vm_area); +#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA static struct vmap_area *node_to_va(struct rb_node *n) { return n ? rb_entry(n, struct vmap_area, rb_node) : NULL; @@ -2257,6 +2258,7 @@ struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets, kfree(vms); return NULL; } +#endif /** * pcpu_free_vm_areas - free vmalloc areas for percpu allocator From 383073d49fc78aa793c51018e29253c83410401e Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 11 Dec 2009 15:17:20 +0800 Subject: [PATCH 166/670] ACPI: Use the ARB_DISABLE for the CPU which model id is less than 0x0f. commit 03a05ed1152944000151d57b71000de287a1eb02 upstream. Currently, ARB_DISABLE is a NOP on all of the recent Intel platforms. For such platforms, reduce contention on c3_lock by skipping the fake ARB_DISABLE. The cpu model id on one laptop is 14. If we disable ARB_DISABLE on this box, the box can't be booted correctly. But if we still enable ARB_DISABLE on this box, the box can be booted correctly. So we still use the ARB_DISABLE for the cpu which mode id is less than 0x0f. http://bugzilla.kernel.org/show_bug.cgi?id=14700 Signed-off-by: Zhao Yakui Acked-by: Venkatesh Pallipadi Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/acpi/cstate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c index 59cdfa4686b2..2e837f5080fe 100644 --- a/arch/x86/kernel/acpi/cstate.c +++ b/arch/x86/kernel/acpi/cstate.c @@ -48,7 +48,7 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, * P4, Core and beyond CPUs */ if (c->x86_vendor == X86_VENDOR_INTEL && - (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 14))) + (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 0x0f))) flags->bm_control = 0; } EXPORT_SYMBOL(acpi_processor_power_init_bm_check); From ad496b34c6835a89dd3a8f6c07dfcf8a0dd7c277 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 13 Dec 2009 22:39:28 -0800 Subject: [PATCH 167/670] net: Fix userspace RTM_NEWLINK notifications. commit d90a909e1f3e006a1d57fe11fd417173b6494701 upstream. I received some bug reports about userspace programs having problems because after RTM_NEWLINK was received they could not immeidate access files under /proc/sys/net/ because they had not been registered yet. The problem was trivailly fixed by moving the userspace notification from rtnetlink_event to the end of register_netdevice. Signed-off-by: Eric W. Biederman Cc: David Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 11 +++++++++++ net/core/rtnetlink.c | 4 +--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index fe10551d3671..584046eef9cb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4860,6 +4860,11 @@ int register_netdevice(struct net_device *dev) rollback_registered(dev); dev->reg_state = NETREG_UNREGISTERED; } + /* + * Prevent userspace races by waiting until the network + * device is fully setup before sending notifications. + */ + rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); out: return ret; @@ -5398,6 +5403,12 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* Notify protocols, that a new device appeared. */ call_netdevice_notifiers(NETDEV_REGISTER, dev); + /* + * Prevent userspace races by waiting until the network + * device is fully setup before sending notifications. + */ + rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); + synchronize_net(); err = 0; out: diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index eb42873f2a3a..d4fd895e8712 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1334,13 +1334,11 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi case NETDEV_UNREGISTER: rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); break; - case NETDEV_REGISTER: - rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); - break; case NETDEV_UP: case NETDEV_DOWN: rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); break; + case NETDEV_REGISTER: case NETDEV_CHANGE: case NETDEV_GOING_DOWN: break; From 62965d8347a071c72f4dae96e65be5fb68dd052f Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 1 Dec 2009 16:53:06 +0100 Subject: [PATCH 168/670] ext3: Fix data / filesystem corruption when write fails to copy data commit 68eb3db08344286733adac48304d9fb7a0e53b27 upstream. When ext3_write_begin fails after allocating some blocks or generic_perform_write fails to copy data to write, we truncate blocks already instantiated beyond i_size. Although these blocks were never inside i_size, we have to truncate pagecache of these blocks so that corresponding buffers get unmapped. Otherwise subsequent __block_prepare_write (called because we are retrying the write) will find the buffers mapped, not call ->get_block, and thus the page will be backed by already freed blocks leading to filesystem and data corruption. Reported-by: James Y Knight Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/ext3/inode.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 354ed3b47b30..f9d69378caaa 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1151,6 +1151,16 @@ static int do_journal_get_write_access(handle_t *handle, return ext3_journal_get_write_access(handle, bh); } +/* + * Truncate blocks that were not used by write. We have to truncate the + * pagecache as well so that corresponding buffers get properly unmapped. + */ +static void ext3_truncate_failed_write(struct inode *inode) +{ + truncate_inode_pages(inode->i_mapping, inode->i_size); + ext3_truncate(inode); +} + static int ext3_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) @@ -1209,7 +1219,7 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping, unlock_page(page); page_cache_release(page); if (pos + len > inode->i_size) - ext3_truncate(inode); + ext3_truncate_failed_write(inode); } if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) goto retry; @@ -1304,7 +1314,7 @@ static int ext3_ordered_write_end(struct file *file, page_cache_release(page); if (pos + len > inode->i_size) - ext3_truncate(inode); + ext3_truncate_failed_write(inode); return ret ? ret : copied; } @@ -1330,7 +1340,7 @@ static int ext3_writeback_write_end(struct file *file, page_cache_release(page); if (pos + len > inode->i_size) - ext3_truncate(inode); + ext3_truncate_failed_write(inode); return ret ? ret : copied; } @@ -1383,7 +1393,7 @@ static int ext3_journalled_write_end(struct file *file, page_cache_release(page); if (pos + len > inode->i_size) - ext3_truncate(inode); + ext3_truncate_failed_write(inode); return ret ? ret : copied; } From 21bcbffae11d48b81ca7b4fd0c873e4d8607de34 Mon Sep 17 00:00:00 2001 From: Rafal Milecki Date: Fri, 2 Oct 2009 03:54:44 -0300 Subject: [PATCH 169/670] V4L/DVB (13116): gspca - ov519: Webcam 041e:4067 added. commit 518c8df77c21b7d1690dd8b96eb0e54c4ec1c9c1 upstream. Signed-off-by: Rafal Milecki Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab Cc: Surbhi Palande Signed-off-by: Greg Kroah-Hartman --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/ov519.c | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 3f61825be499..90e85a8a8817 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -37,6 +37,7 @@ ov519 041e:405f Creative Live! VISTA VF0330 ov519 041e:4060 Creative Live! VISTA VF0350 ov519 041e:4061 Creative Live! VISTA VF0400 ov519 041e:4064 Creative Live! VISTA VF0420 +ov519 041e:4067 Creative Live! Cam Video IM (VF0350) ov519 041e:4068 Creative Live! VISTA VF0470 spca561 0458:7004 Genius VideoCAM Express V2 sunplus 0458:7006 Genius Dsc 1.3 Smart diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index a5c190e93799..e16557819782 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -3364,6 +3364,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, From 2e20f8fadd921fa3d664bb120f99b380a1b05cbd Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 15 Dec 2009 06:45:06 +0000 Subject: [PATCH 170/670] bcm63xx_enet: fix compilation failure after get_stats_count removal commit a3f92eea04101d9a8e14d50f8048cc5b7bca07a8 upstream. This patch converts bcm63xx_enet to uset get_sset_count like the other drivers do. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bcm63xx_enet.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index ba29dc319b34..d110c1b978a5 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -1248,9 +1248,15 @@ static void bcm_enet_get_drvinfo(struct net_device *netdev, drvinfo->n_stats = BCM_ENET_STATS_LEN; } -static int bcm_enet_get_stats_count(struct net_device *netdev) +static int bcm_enet_get_sset_count(struct net_device *netdev, + int string_set) { - return BCM_ENET_STATS_LEN; + switch (string_set) { + case ETH_SS_STATS: + return BCM_ENET_STATS_LEN; + default: + return -EINVAL; + } } static void bcm_enet_get_strings(struct net_device *netdev, @@ -1476,7 +1482,7 @@ static int bcm_enet_set_pauseparam(struct net_device *dev, static struct ethtool_ops bcm_enet_ethtool_ops = { .get_strings = bcm_enet_get_strings, - .get_stats_count = bcm_enet_get_stats_count, + .get_sset_count = bcm_enet_get_sset_count, .get_ethtool_stats = bcm_enet_get_ethtool_stats, .get_settings = bcm_enet_get_settings, .set_settings = bcm_enet_set_settings, From 21fc7b8d8c49b0f6ce7a45ae44361d31e93e629a Mon Sep 17 00:00:00 2001 From: Yong Wang Date: Wed, 16 Dec 2009 12:58:46 +0800 Subject: [PATCH 171/670] x86: Under BIOS control, restore AP's APIC_LVTTHMR to the BSP value Upstream commit a2202aa29289db64ca7988b12343158b67b27f10. On platforms where bios handles the thermal monitor interrupt, APIC_LVTTHMR on each logical CPU is programmed to generate a SMI and OS can't touch it. Unfortunately AP bringup sequence using INIT-SIPI-SIPI clear all the LVT entries except the mask bit. Essentially this results in all LVT entries including the thermal monitoring interrupt set to masked (clearing the bios programmed value for APIC_LVTTHMR). And this leads to kernel take over the thermal monitoring interrupt on AP's but not on BSP (leaving the bios programmed value only on BSP). As a result of this, we have seen system hangs when the thermal monitoring interrupt is generated. Fix this by reading the initial value of thermal LVT entry on BSP and if bios has taken over the control, then program the same value on all AP's and leave the thermal monitoring interrupt control on all the logical cpu's to the bios. Signed-off-by: Yong Wang Reviewed-by: Suresh Siddha Cc: Borislav Petkov Cc: Arjan van de Ven LKML-Reference: <20091110013824.GA24940@ywang-moblin2.bj.intel.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/mce.h | 6 +++++ arch/x86/kernel/cpu/mcheck/therm_throt.c | 29 +++++++++++++++++++++++- arch/x86/kernel/setup.c | 3 +++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index f1363b72364f..a47902354261 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -214,5 +214,11 @@ void intel_init_thermal(struct cpuinfo_x86 *c); void mce_log_therm_throt_event(__u64 status); +#ifdef CONFIG_X86_THERMAL_VECTOR +extern void mcheck_intel_therm_init(void); +#else +static inline void mcheck_intel_therm_init(void) { } +#endif + #endif /* __KERNEL__ */ #endif /* _ASM_X86_MCE_H */ diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index b3a1dba75330..4fef985fc221 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -49,6 +49,8 @@ static DEFINE_PER_CPU(struct thermal_state, thermal_state); static atomic_t therm_throt_en = ATOMIC_INIT(0); +static u32 lvtthmr_init __read_mostly; + #ifdef CONFIG_SYSFS #define define_therm_throt_sysdev_one_ro(_name) \ static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) @@ -254,6 +256,18 @@ asmlinkage void smp_thermal_interrupt(struct pt_regs *regs) ack_APIC_irq(); } +void __init mcheck_intel_therm_init(void) +{ + /* + * This function is only called on boot CPU. Save the init thermal + * LVT value on BSP and use that value to restore APs' thermal LVT + * entry BIOS programmed later + */ + if (cpu_has(&boot_cpu_data, X86_FEATURE_ACPI) && + cpu_has(&boot_cpu_data, X86_FEATURE_ACC)) + lvtthmr_init = apic_read(APIC_LVTTHMR); +} + void intel_init_thermal(struct cpuinfo_x86 *c) { unsigned int cpu = smp_processor_id(); @@ -270,7 +284,20 @@ void intel_init_thermal(struct cpuinfo_x86 *c) * since it might be delivered via SMI already: */ rdmsr(MSR_IA32_MISC_ENABLE, l, h); - h = apic_read(APIC_LVTTHMR); + + /* + * The initial value of thermal LVT entries on all APs always reads + * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI + * sequence to them and LVT registers are reset to 0s except for + * the mask bits which are set to 1s when APs receive INIT IPI. + * Always restore the value that BIOS has programmed on AP based on + * BSP's info we saved since BIOS is always setting the same value + * for all threads/cores + */ + apic_write(APIC_LVTTHMR, lvtthmr_init); + + h = lvtthmr_init; + if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n", cpu); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 2a34f9c5be21..51aa5b211c67 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -109,6 +109,7 @@ #ifdef CONFIG_X86_64 #include #endif +#include /* * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. @@ -1031,6 +1032,8 @@ void __init setup_arch(char **cmdline_p) #endif #endif x86_init.oem.banner(); + + mcheck_intel_therm_init(); } #ifdef CONFIG_X86_32 From 452a68706c276224ce1c91fff9ca88158d53c426 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 27 Nov 2009 13:06:56 +0000 Subject: [PATCH 172/670] drm/i915: Avoid NULL dereference with component_only tv_modes commit d271817baecbccb47da0d9f28c285a0dae8a06b7 upstream. In commit d2d9f2324, the guard for a valid video mode was removed. This caused the regression: kernel crash during kms graphic boot on Intel GM4500 platform https://bugzilla.redhat.com/show_bug.cgi?id=540218 This patches changes the logic slightly not to rely on a coupled variable, but to just check whether the video_modes is valid before dereferencing. Signed-off-by: Chris Wilson Cc: David Woodhouse Cc: Zhenyu Wang [ickle: Actually reference the correct bug report] Acked-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_tv.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 9ca917931afb..5b28b4e7ebe7 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1213,20 +1213,17 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, tv_ctl |= TV_TRILEVEL_SYNC; if (tv_mode->pal_burst) tv_ctl |= TV_PAL_BURST; - scctl1 = 0; - /* dda1 implies valid video levels */ - if (tv_mode->dda1_inc) { - scctl1 |= TV_SC_DDA1_EN; - } + scctl1 = 0; + if (tv_mode->dda1_inc) + scctl1 |= TV_SC_DDA1_EN; if (tv_mode->dda2_inc) scctl1 |= TV_SC_DDA2_EN; - if (tv_mode->dda3_inc) scctl1 |= TV_SC_DDA3_EN; - scctl1 |= tv_mode->sc_reset; - scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT; + if (video_levels) + scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT; scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT; scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT | From fb79085d52de31fa0e2fe6cb9d1aab332caec16a Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 27 Nov 2009 11:44:36 +0800 Subject: [PATCH 173/670] drm/i915: PineView only has LVDS and CRT ports commit 103a196f4224dc6872081305cf7f82ebf67aa7bd upstream. PineView only has 2 ports for LVDS and CRT. Don't enable other ports for it. Cc: Shaohua Li Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_drv.h | 4 ++++ drivers/gpu/drm/i915/intel_display.c | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a725f6591192..ecbafd036858 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -957,6 +957,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define IS_I85X(dev) ((dev)->pci_device == 0x3582) #define IS_I855(dev) ((dev)->pci_device == 0x3582) #define IS_I865G(dev) ((dev)->pci_device == 0x2572) +#define IS_I8XX(dev) (IS_I830(dev) || IS_845G(dev) || IS_I85X(dev) || IS_I865G(dev)) #define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a) #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) @@ -1018,9 +1019,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); */ #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ IS_I915GM(dev))) +#define SUPPORTS_DIGITAL_OUTPUTS(dev) (IS_I9XX(dev) && !IS_IGD(dev)) #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define SUPPORTS_EDP(dev) (IS_IGDNG_M(dev)) +#define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \ + !IS_IGDNG(dev) && !IS_IGD(dev)) #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev) || IS_I965G(dev)) /* dsparb controlled by hw only */ #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev)) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 355b637a5437..a77404a4f752 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4119,7 +4119,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(PCH_DP_D) & DP_DETECTED) intel_dp_init(dev, PCH_DP_D); - } else if (IS_I9XX(dev)) { + } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { bool found = false; if (I915_READ(SDVOB) & SDVO_DETECTED) { @@ -4146,10 +4146,10 @@ static void intel_setup_outputs(struct drm_device *dev) if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) intel_dp_init(dev, DP_D); - } else + } else if (IS_I8XX(dev)) intel_dvo_init(dev); - if (IS_I9XX(dev) && IS_MOBILE(dev) && !IS_IGDNG(dev)) + if (SUPPORTS_TV(dev)) intel_tv_init(dev); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { From ac34851f4dac996125b1cf7c5acdb14310b0f525 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 25 Nov 2009 13:09:38 +0800 Subject: [PATCH 174/670] drm/i915: Fix LVDS stability issue on Ironlake commit 1b3c7a47f993bf9ab6c4c7cc3bbf5588052b58f4 upstream. In disable sequence, all output ports on PCH have to be disabled before PCH transcoder, but LVDS port was left always enabled. This one fixes that by disable LVDS port properly during pipe disable process, and resolved stability issue seen on Ironlake. Also move panel fitting disable time just after pipe disable to align with the spec. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 60 +++++++++++++++++++--------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a77404a4f752..f1de53b2f49b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1482,6 +1482,15 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: DRM_DEBUG("crtc %d dpms on\n", pipe); + + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { + temp = I915_READ(PCH_LVDS); + if ((temp & LVDS_PORT_EN) == 0) { + I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); + POSTING_READ(PCH_LVDS); + } + } + if (HAS_eDP) { /* enable eDP PLL */ igdng_enable_pll_edp(crtc); @@ -1666,8 +1675,6 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_OFF: DRM_DEBUG("crtc %d dpms off\n", pipe); - i915_disable_vga(dev); - /* Disable display plane */ temp = I915_READ(dspcntr_reg); if ((temp & DISPLAY_PLANE_ENABLE) != 0) { @@ -1677,6 +1684,8 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(dspbase_reg); } + i915_disable_vga(dev); + /* disable cpu pipe, disable after all planes disabled */ temp = I915_READ(pipeconf_reg); if ((temp & PIPEACONF_ENABLE) != 0) { @@ -1697,9 +1706,15 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) } else DRM_DEBUG("crtc %d is disabled\n", pipe); - if (HAS_eDP) { - igdng_disable_pll_edp(crtc); + udelay(100); + + /* Disable PF */ + temp = I915_READ(pf_ctl_reg); + if ((temp & PF_ENABLE) != 0) { + I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); + I915_READ(pf_ctl_reg); } + I915_WRITE(pf_win_size, 0); /* disable CPU FDI tx and PCH FDI rx */ temp = I915_READ(fdi_tx_reg); @@ -1725,6 +1740,13 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(100); + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { + temp = I915_READ(PCH_LVDS); + I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN); + I915_READ(PCH_LVDS); + udelay(100); + } + /* disable PCH transcoder */ temp = I915_READ(transconf_reg); if ((temp & TRANS_ENABLE) != 0) { @@ -1744,6 +1766,8 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) } } + udelay(100); + /* disable PCH DPLL */ temp = I915_READ(pch_dpll_reg); if ((temp & DPLL_VCO_ENABLE) != 0) { @@ -1751,14 +1775,20 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(pch_dpll_reg); } - temp = I915_READ(fdi_rx_reg); - if ((temp & FDI_RX_PLL_ENABLE) != 0) { - temp &= ~FDI_SEL_PCDCLK; - temp &= ~FDI_RX_PLL_ENABLE; - I915_WRITE(fdi_rx_reg, temp); - I915_READ(fdi_rx_reg); + if (HAS_eDP) { + igdng_disable_pll_edp(crtc); } + temp = I915_READ(fdi_rx_reg); + temp &= ~FDI_SEL_PCDCLK; + I915_WRITE(fdi_rx_reg, temp); + I915_READ(fdi_rx_reg); + + temp = I915_READ(fdi_rx_reg); + temp &= ~FDI_RX_PLL_ENABLE; + I915_WRITE(fdi_rx_reg, temp); + I915_READ(fdi_rx_reg); + /* Disable CPU FDI TX PLL */ temp = I915_READ(fdi_tx_reg); if ((temp & FDI_TX_PLL_ENABLE) != 0) { @@ -1767,16 +1797,8 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(100); } - /* Disable PF */ - temp = I915_READ(pf_ctl_reg); - if ((temp & PF_ENABLE) != 0) { - I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); - I915_READ(pf_ctl_reg); - } - I915_WRITE(pf_win_size, 0); - /* Wait for the clocks to turn off. */ - udelay(150); + udelay(100); break; } } From 1c723eb018de64d2159e9ce66ec6df0d1798e1e3 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 14 Dec 2009 17:59:04 -0800 Subject: [PATCH 175/670] mm: sigbus instead of abusing oom commit d99be1a8ecf377c2c9b3372d36411ad6547bbd4c upstream. When do_nonlinear_fault() realizes that the page table must have been corrupted for it to have been called, it does print_bad_pte() and returns ... VM_FAULT_OOM, which is hard to understand. It made some sense when I did it for 2.6.15, when do_page_fault() just killed the current process; but nowadays it lets the OOM killer decide who to kill - so page table corruption in one process would be liable to kill another. Change it to return VM_FAULT_SIGBUS instead: that doesn't guarantee that the process will be killed, but is good enough for such a rare abnormality, accompanied as it is by the "BUG: Bad page map" message. And recent HWPOISON work has copied that code into do_swap_page(), when it finds an impossible swap entry: fix that to VM_FAULT_SIGBUS too. Signed-off-by: Hugh Dickins Cc: Izik Eidus Cc: Andrea Arcangeli Cc: Nick Piggin Reviewed-by: KOSAKI Motohiro Cc: Rik van Riel Cc: Lee Schermerhorn Cc: Andi Kleen Reviewed-by: KAMEZAWA Hiroyuki Reviewed-by: Wu Fengguang Reviewed-by: Minchan Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 6ab19dd4a199..4e5945588c73 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2514,7 +2514,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, ret = VM_FAULT_HWPOISON; } else { print_bad_pte(vma, address, orig_pte, NULL); - ret = VM_FAULT_OOM; + ret = VM_FAULT_SIGBUS; } goto out; } @@ -2910,7 +2910,7 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, * Page table corrupted: show pte and kill process. */ print_bad_pte(vma, address, orig_pte, NULL); - return VM_FAULT_OOM; + return VM_FAULT_SIGBUS; } pgoff = pte_to_pgoff(orig_pte); From 75bc75ed15405655d795a163856158aa2ff9bdbc Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 15 Dec 2009 17:01:25 +0100 Subject: [PATCH 176/670] ipvs: zero usvc and udest commit 258c889362aa95d0ab534b38ce8c15d3009705b1 upstream. Make sure that any otherwise uninitialised fields of usvc are zero. This has been obvserved to cause a problem whereby the port of fwmark services may end up as a non-zero value which causes scheduling of a destination server to fail for persisitent services. As observed by Deon van der Merwe . This fix suggested by Julian Anastasov . For good measure also zero udest. Cc: Deon van der Merwe Acked-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- net/netfilter/ipvs/ip_vs_ctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 446e9bd4b4bc..02b2610c4d2e 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2714,6 +2714,8 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc, if (!(nla_af && (nla_fwmark || (nla_port && nla_protocol && nla_addr)))) return -EINVAL; + memset(usvc, 0, sizeof(*usvc)); + usvc->af = nla_get_u16(nla_af); #ifdef CONFIG_IP_VS_IPV6 if (usvc->af != AF_INET && usvc->af != AF_INET6) @@ -2901,6 +2903,8 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest, if (!(nla_addr && nla_port)) return -EINVAL; + memset(udest, 0, sizeof(*udest)); + nla_memcpy(&udest->addr, nla_addr, sizeof(udest->addr)); udest->port = nla_get_u16(nla_port); From 3a03456dc34ff703e5b7c718b78713577f832116 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 16 Dec 2009 03:27:20 +0000 Subject: [PATCH 177/670] jffs2: Fix long-standing bug with symlink garbage collection. commit 2e16cfca6e17ae37ae21feca080a6f2eca9087dc upstream. Ever since jffs2_garbage_collect_metadata() was first half-written in February 2001, it's been broken on architectures where 'char' is signed. When garbage collecting a symlink with target length above 127, the payload length would end up negative, causing interesting and bad things to happen. Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- fs/jffs2/gc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 090c556ffed2..3b6f2fa12cff 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -700,7 +700,8 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ struct jffs2_raw_inode ri; struct jffs2_node_frag *last_frag; union jffs2_device_node dev; - char *mdata = NULL, mdatalen = 0; + char *mdata = NULL; + int mdatalen = 0; uint32_t alloclen, ilen; int ret; From 518cdfa0f604c285cdb71e1f2e2e14773f80bb01 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 2 Dec 2009 09:17:13 +0000 Subject: [PATCH 178/670] intel-iommu: Detect DMAR in hyperspace at probe time. commit 2c99220810c1c79322034628b993573b088ff2da upstream. Many BIOSes will lie to us about the existence of an IOMMU, and claim that there is one at an address which actually returns all 0xFF. We need to detect this early, so that we know we don't have a viable IOMMU and can set up swiotlb before it's too late. Signed-off-by: Chris Wright Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/pci/dmar.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index b952ebc7a78b..ef58a0a2eaaf 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -601,6 +601,9 @@ int __init check_zero_address(void) } if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) { + void __iomem *addr; + u64 cap, ecap; + drhd = (void *)entry_header; if (!drhd->address) { /* Promote an attitude of violence to a BIOS engineer today */ @@ -609,17 +612,38 @@ int __init check_zero_address(void) dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_PRODUCT_VERSION)); -#ifdef CONFIG_DMAR - dmar_disabled = 1; -#endif - return 0; + goto failed; + } + + addr = early_ioremap(drhd->address, VTD_PAGE_SIZE); + if (!addr ) { + printk("IOMMU: can't validate: %llx\n", drhd->address); + goto failed; + } + cap = dmar_readq(addr + DMAR_CAP_REG); + ecap = dmar_readq(addr + DMAR_ECAP_REG); + early_iounmap(addr, VTD_PAGE_SIZE); + if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) { + /* Promote an attitude of violence to a BIOS engineer today */ + WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + drhd->address, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); + goto failed; } - break; } entry_header = ((void *)entry_header + entry_header->length); } return 1; + +failed: +#ifdef CONFIG_DMAR + dmar_disabled = 1; +#endif + return 0; } void __init detect_intel_iommu(void) From b02375be25be8895f1fdb63a0962fd465d88f998 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 2 Dec 2009 09:20:27 +0000 Subject: [PATCH 179/670] intel-iommu: Apply BIOS sanity checks for interrupt remapping too. commit 6ecbf01c7ce4c0f4c3bdfa0e64ac6258328fda6c upstream. The BIOS errors where an IOMMU is reported either at zero or a bogus address are causing problems even when the IOMMU is disabled -- because interrupt remapping uses the same hardware. Ensure that the checks get applied for the interrupt remapping initialisation too. Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/pci/dmar.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index ef58a0a2eaaf..57530361f15d 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -582,6 +582,8 @@ int __init dmar_table_init(void) return 0; } +static int bios_warned; + int __init check_zero_address(void) { struct acpi_table_dmar *dmar; @@ -612,6 +614,7 @@ int __init check_zero_address(void) dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_PRODUCT_VERSION)); + bios_warned = 1; goto failed; } @@ -631,6 +634,7 @@ int __init check_zero_address(void) dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_PRODUCT_VERSION)); + bios_warned = 1; goto failed; } } @@ -688,6 +692,18 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) int agaw = 0; int msagaw = 0; + if (!drhd->reg_base_addr) { + if (!bios_warned) { + WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); + bios_warned = 1; + } + return -EINVAL; + } + iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); if (!iommu) return -ENOMEM; @@ -704,13 +720,16 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) { - /* Promote an attitude of violence to a BIOS engineer today */ - WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - drhd->reg_base_addr, - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); + if (!bios_warned) { + /* Promote an attitude of violence to a BIOS engineer today */ + WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + drhd->reg_base_addr, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); + bios_warned = 1; + } goto err_unmap; } From 39035f9c09699eea2dd154d170919dcd41c6885d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 2 Dec 2009 09:21:55 +0000 Subject: [PATCH 180/670] intel-iommu: Check for an RMRR which ends before it starts. commit 5595b528b49a702c0428c0762bab60999648254c upstream. Some HP BIOSes report an RMRR region (a region which needs a 1:1 mapping in the IOMMU for a given device) which has an end address lower than its start address. Detect that and warn, rather than triggering the BUG() in dma_pte_clear_range(). Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/pci/intel-iommu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 1840a0578a42..1db5b037edbc 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1991,6 +1991,16 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", pci_name(pdev), start, end); + if (end < start) { + WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); + ret = -EIO; + goto error; + } + if (end >> agaw_to_width(domain->agaw)) { WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n" "BIOS vendor: %s; Ver: %s; Product Version: %s\n", From 020d1eecf345422d34bec8fb4a45299dcc0dcc3f Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 2 Dec 2009 10:18:30 +0000 Subject: [PATCH 181/670] intel-iommu: Fix oops with intel_iommu=igfx_off commit 44cd613c0e4cd93079ea2a93aa06649d8ca0830a upstream. The hotplug notifier will call find_domain() to see if the device in question has been assigned an IOMMU domain. However, this should never be called for devices with a "dummy" domain, such as graphics devices when intel_iommu=igfx_off is set and the corresponding IOMMU isn't even initialised. If you do that, it'll oops as it dereferences the (-1) pointer. The notifier function should check iommu_no_mapping() for the device before doing anything else. Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/pci/intel-iommu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 1db5b037edbc..1b9f76f0193a 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3238,6 +3238,9 @@ static int device_notifier(struct notifier_block *nb, struct pci_dev *pdev = to_pci_dev(dev); struct dmar_domain *domain; + if (iommu_no_mapping(dev)) + return 0; + domain = find_domain(pdev); if (!domain) return 0; From acb724d43ade7509f3dcec679243f88e2902c237 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 2 Dec 2009 12:06:34 -0800 Subject: [PATCH 182/670] intel-iommu: ignore page table validation in pass through mode commit 1672af1164d3d50ba8908014fd34cc0b58afdc1e upstream. We are seeing a bug when booting w/ iommu=pt with current upstream (bisect blames 19943b0e30b05d42e494ae6fef78156ebc8c637e "intel-iommu: Unify hardware and software passthrough support). The issue is specific to this loop during identity map initialization of each device: domain_context_mapping_one(si_domain, ..., CONTEXT_TT_PASS_THROUGH) ... /* Skip top levels of page tables for * iommu which has less agaw than default. */ for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) { pgd = phys_to_virt(dma_pte_addr(pgd)); if (!dma_pte_present(pgd)) { <------ failing here spin_unlock_irqrestore(&iommu->lock, flags); return -ENOMEM; } This box has 2 iommu's in it. The catchall iommu has MGAW == 48, and SAGAW == 4. The other iommu has MGAW == 39, SAGAW == 2. The device that's failing the above pgd test is the only device connected to the non-catchall iommu, which has a smaller address width than the domain default. This test is not necessary since the context is in PT mode and the ASR is ignored. Thanks to Don Dutile for discovering and debugging this one. Signed-off-by: Chris Wright Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- drivers/pci/intel-iommu.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 1b9f76f0193a..2498602151e6 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1523,12 +1523,15 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment, /* Skip top levels of page tables for * iommu which has less agaw than default. + * Unnecessary for PT mode. */ - for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) { - pgd = phys_to_virt(dma_pte_addr(pgd)); - if (!dma_pte_present(pgd)) { - spin_unlock_irqrestore(&iommu->lock, flags); - return -ENOMEM; + if (translation != CONTEXT_TT_PASS_THROUGH) { + for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) { + pgd = phys_to_virt(dma_pte_addr(pgd)); + if (!dma_pte_present(pgd)) { + spin_unlock_irqrestore(&iommu->lock, flags); + return -ENOMEM; + } } } } From 60a48f8c19f1de13a99ad6d1972bbde8d193f3bd Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 14 Dec 2009 14:52:10 +0100 Subject: [PATCH 183/670] netfilter: xtables: document minimal required version commit 7a92263705435d046d37a0990d0edfcb517f7ad3 upstream. For both .33 and .32-stable. Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- Documentation/Changes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/Changes b/Documentation/Changes index 6d0f1efc5bf6..f08b313cd235 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -49,6 +49,8 @@ o oprofile 0.9 # oprofiled --version o udev 081 # udevinfo -V o grub 0.93 # grub --version o mcelog 0.6 +o iptables 1.4.1 # iptables -V + Kernel compilation ================== From 517361c51d4a762531e669ebb2c081a1e678455a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 15 Dec 2009 19:40:32 +1100 Subject: [PATCH 184/670] perf_event: Fix incorrect range check on cpu number commit 0f624e7e5625f4c30c836b7a5decfe2553582391 upstream. It is quite legitimate for CPUs to be numbered sparsely, meaning that it possible for an online CPU to have a number which is greater than the total count of possible CPUs. Currently find_get_context() has a sanity check on the cpu number where it checks it against num_possible_cpus(). This test can fail for a legitimate cpu number if the cpu_possible_mask is sparsely populated. This fixes the problem by checking the CPU number against nr_cpumask_bits instead, since that is the appropriate check to ensure that the cpu number is same to pass to cpu_isset() subsequently. Reported-by: Michael Neuling Signed-off-by: Paul Mackerras Tested-by: Michael Neuling Acked-by: Peter Zijlstra LKML-Reference: <20091215084032.GA18661@brick.ozlabs.ibm.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/perf_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 61c35f583b90..6eee915a939e 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -1583,7 +1583,7 @@ static struct perf_event_context *find_get_context(pid_t pid, int cpu) if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN)) return ERR_PTR(-EACCES); - if (cpu < 0 || cpu > num_possible_cpus()) + if (cpu < 0 || cpu >= nr_cpumask_bits) return ERR_PTR(-EINVAL); /* From 80c0299b8cfdf7aa31b88118b75de6b7bb1aba63 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Mon, 14 Dec 2009 20:00:36 +0000 Subject: [PATCH 185/670] implement early_io{re,un}map for ia64 commit cd7bcf32d42b15891620b3f1387a00178b54291a upstream. Needed for commit 2c992208 ("intel-iommu: Detect DMAR in hyperspace at probe time.) to build on IA64. Signed-off-by: Tony Luck Signed-off-by: David Woodhouse Signed-off-by: Greg Kroah-Hartman --- arch/ia64/include/asm/io.h | 2 ++ arch/ia64/mm/ioremap.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h index 0d9d16e2d949..cc8335eb3110 100644 --- a/arch/ia64/include/asm/io.h +++ b/arch/ia64/include/asm/io.h @@ -424,6 +424,8 @@ __writeq (unsigned long val, volatile void __iomem *addr) extern void __iomem * ioremap(unsigned long offset, unsigned long size); extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size); extern void iounmap (volatile void __iomem *addr); +extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size); +extern void early_iounmap (volatile void __iomem *addr, unsigned long size); /* * String version of IO memory access ops: diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c index 2a140627dfd6..3dccdd8eb275 100644 --- a/arch/ia64/mm/ioremap.c +++ b/arch/ia64/mm/ioremap.c @@ -21,6 +21,12 @@ __ioremap (unsigned long phys_addr) return (void __iomem *) (__IA64_UNCACHED_OFFSET | phys_addr); } +void __iomem * +early_ioremap (unsigned long phys_addr, unsigned long size) +{ + return __ioremap(phys_addr); +} + void __iomem * ioremap (unsigned long phys_addr, unsigned long size) { @@ -101,6 +107,11 @@ ioremap_nocache (unsigned long phys_addr, unsigned long size) } EXPORT_SYMBOL(ioremap_nocache); +void +early_iounmap (volatile void __iomem *addr, unsigned long size) +{ +} + void iounmap (volatile void __iomem *addr) { From a1092bf3809c7ec7b730d0cca3bdba964a813147 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 18 Dec 2009 14:27:07 -0800 Subject: [PATCH 186/670] Linux 2.6.32.2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d0d7e9c7abec..23803ce63eee 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = .1 +EXTRAVERSION = .2 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* From c1d17da3cf8a961254fd18f4ddc8bbb743a33ab7 Mon Sep 17 00:00:00 2001 From: Kleber Sacilotto de Souza Date: Wed, 25 Nov 2009 20:13:43 -0200 Subject: [PATCH 187/670] SCSI: ipr: fix EEH recovery commit 99c965dd9ee1a004efc083c3d760ba982bb76adf upstream. After commits c82f63e411f1b58427c103bd95af2863b1c96dd1 (PCI: check saved state before restore) and 4b77b0a2ba27d64f58f16d8d4d48d8319dda36ff (PCI: Clear saved_state after the state has been restored) PCI drivers are prevented from restoring the device standard configuration registers twice in a row. These changes introduced a regression on ipr EEH recovery. The ipr device driver saves the PCI state only during the device probe and restores it on ipr_reset_restore_cfg_space() during IOA resets. This behavior is causing the EEH recovery to fail after the second error detected, since the registers are not being restored. One possible solution would be saving the registers after restoring them. The problem with this approach is that while recovering from an EEH error if pci_save_state() results in an EEH error, the adapter/slot will be reset, and end up back in ipr_reset_restore_cfg_space(), but it won't have a valid saved state to restore, so pci_restore_state() will fail. The following patch introduces a workaround for this problem, hacking around the PCI API by setting pdev->state_saved = true before we do the restore. It fixes the EEH regression and prevents that we hit another EEH error during EEH recovery. [jejb: fix is a hack ... Jesse and Rafael will fix properly] Signed-off-by: Kleber Sacilotto de Souza Acked-by: Brian King Cc: Jesse Barnes Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/ipr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 76d294fc7846..c3ff9a64c192 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -6516,6 +6516,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) int rc; ENTER; + ioa_cfg->pdev->state_saved = true; rc = pci_restore_state(ioa_cfg->pdev); if (rc != PCIBIOS_SUCCESSFUL) { From 9f63d27c1b21cb24b7c2e9f79196a4f72f7b193e Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Wed, 2 Dec 2009 09:11:16 -0600 Subject: [PATCH 188/670] SCSI: qla2xxx: dpc thread can execute before scsi host has been added commit 1486400f7edd009d49550da968d5744e246dc7f8 upstream. Fix crash in qla2x00_fdmi_register() due to the dpc thread executing before the scsi host has been fully added. Unable to handle kernel NULL pointer dereference (address 00000000000001d0) qla2xxx_7_dpc[4140]: Oops 8813272891392 [1] Call Trace: [] show_stack+0x50/0xa0 sp=e00000b07c59f930 bsp=e00000b07c591400 [] show_regs+0x820/0x860 sp=e00000b07c59fb00 bsp=e00000b07c5913a0 [] die+0x1a0/0x2e0 sp=e00000b07c59fb00 bsp=e00000b07c591360 [] ia64_do_page_fault+0x8c0/0x9e0 sp=e00000b07c59fb00 bsp=e00000b07c591310 [] ia64_native_leave_kernel+0x0/0x270 sp=e00000b07c59fb90 bsp=e00000b07c591310 [] qla2x00_fdmi_register+0x850/0xbe0 [qla2xxx] sp=e00000b07c59fd60 bsp=e00000b07c591290 [] qla2x00_configure_loop+0x1930/0x34c0 [qla2xxx] sp=e00000b07c59fd60 bsp=e00000b07c591128 [] qla2x00_loop_resync+0x1b0/0x2e0 [qla2xxx] sp=e00000b07c59fdf0 bsp=e00000b07c5910c0 [] qla2x00_do_dpc+0x9a0/0xce0 [qla2xxx] sp=e00000b07c59fdf0 bsp=e00000b07c590fa0 [] kthread+0x110/0x140 sp=e00000b07c59fe00 bsp=e00000b07c590f68 [] kernel_thread_helper+0xd0/0x100 sp=e00000b07c59fe30 bsp=e00000b07c590f40 [] start_kernel_thread+0x20/0x40 sp=e00000b07c59fe30 bsp=e00000b07c590f40 crash> dis a000000207197350 0xa000000207197350 : [MMI] ld1 r45=[r14];; crash> scsi_qla_host.host 0xe00000b058c73ff8 host = 0xe00000b058c73be0, crash> Scsi_Host.shost_data 0xe00000b058c73be0 shost_data = 0x0, <<<<<<<<<<< The fc_transport fc_* workqueue threads have yet to be created. crash> ps | grep _7 3891 2 2 e00000b075c80000 IN 0.0 0 0 [scsi_eh_7] 4140 2 3 e00000b07c590000 RU 0.0 0 0 [qla2xxx_7_dpc] The thread creating adding the Scsi_Host is blocked due to other activity in sysfs. crash> bt 3762 PID: 3762 TASK: e00000b071e70000 CPU: 3 COMMAND: "modprobe" #0 [BSP:e00000b071e71548] schedule at a000000100727e00 #1 [BSP:e00000b071e714c8] __mutex_lock_slowpath at a0000001007295a0 #2 [BSP:e00000b071e714a8] mutex_lock at a000000100729830 #3 [BSP:e00000b071e71478] sysfs_addrm_start at a0000001002584f0 #4 [BSP:e00000b071e71440] create_dir at a000000100259350 #5 [BSP:e00000b071e71410] sysfs_create_subdir at a000000100259510 #6 [BSP:e00000b071e713b0] internal_create_group at a00000010025c880 #7 [BSP:e00000b071e71388] sysfs_create_group at a00000010025cc50 #8 [BSP:e00000b071e71368] dpm_sysfs_add at a000000100425050 #9 [BSP:e00000b071e71310] device_add at a000000100417d90 #10 [BSP:e00000b071e712d8] scsi_add_host at a00000010045a380 #11 [BSP:e00000b071e71268] qla2x00_probe_one at a0000002071be950 #12 [BSP:e00000b071e71248] local_pci_probe at a00000010032e490 #13 [BSP:e00000b071e71218] pci_device_probe at a00000010032ecd0 #14 [BSP:e00000b071e711d8] driver_probe_device at a00000010041d480 #15 [BSP:e00000b071e711a8] __driver_attach at a00000010041d6e0 #16 [BSP:e00000b071e71170] bus_for_each_dev at a00000010041c240 #17 [BSP:e00000b071e71150] driver_attach at a00000010041d0a0 #18 [BSP:e00000b071e71108] bus_add_driver at a00000010041b080 #19 [BSP:e00000b071e710c0] driver_register at a00000010041dea0 #20 [BSP:e00000b071e71088] __pci_register_driver at a00000010032f610 #21 [BSP:e00000b071e71058] (unknown) at a000000207200270 #22 [BSP:e00000b071e71018] do_one_initcall at a00000010000a9c0 #23 [BSP:e00000b071e70f98] sys_init_module at a0000001000fef00 #24 [BSP:e00000b071e70f98] ia64_ret_from_syscall at a00000010000c740 So, it appears that qla2xxx dpc thread is moving forward before the scsi host has been completely added. This patch moves the setting of the init_done (and online) flag to after the call to scsi_add_host() to hold off the dpc thread. Found via large lun count testing using 2.6.31. Signed-off-by: Michael Reed Acked-by: Giridhar Malavali Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_os.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b79fca7d461b..06bbe0d8b6d7 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2016,13 +2016,13 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", base_vha->host_no, ha)); - base_vha->flags.init_done = 1; - base_vha->flags.online = 1; - ret = scsi_add_host(host, &pdev->dev); if (ret) goto probe_failed; + base_vha->flags.init_done = 1; + base_vha->flags.online = 1; + ha->isp_ops->enable_intrs(ha); scsi_scan_host(host); From 1ab0714daac27c962256b969823e3d82c67e4b52 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 26 Nov 2009 09:24:13 +0900 Subject: [PATCH 189/670] SCSI: st: fix mdata->page_order handling commit c982c368bb90adbd312faa05d0cfd842e9ab45a7 upstream. dio transfer always resets mdata->page_order to zero. It breaks high-order pages previously allocated for non-dio transfer. This patches adds reserved_page_order to st_buffer structure to save page order for non-dio transfer. http://bugzilla.kernel.org/show_bug.cgi?id=14563 When enlarge_buffer() allocates 524288 from 0, st uses six-order page allocation. So mdata->page_order is 6 and frp_seg is 2. After that, if st uses dio, sgl_map_user_pages() sets mdata->page_order to 0 for st_do_scsi(). After that, when we call normalize_buffer(), it frees only free frp_seg * PAGE_SIZE (2 * 4096) though we should free frp_seg * PAGE_SIZE << 6 (2 * 4096 << 6). So we see buffer_size is set to 516096 (524288 - 8192). Reported-by: Joachim Breuer Tested-by: Joachim Breuer Acked-by: Kai Makisara Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/st.c | 23 ++++++++++++----------- drivers/scsi/st.h | 1 + 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 12d58a7ed6bc..5081f97cbdaa 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -552,13 +552,15 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd SRpnt->waiting = waiting; if (STp->buffer->do_dio) { + mdata->page_order = 0; mdata->nr_entries = STp->buffer->sg_segs; mdata->pages = STp->buffer->mapped_pages; } else { + mdata->page_order = STp->buffer->reserved_page_order; mdata->nr_entries = DIV_ROUND_UP(bytes, PAGE_SIZE << mdata->page_order); - STp->buffer->map_data.pages = STp->buffer->reserved_pages; - STp->buffer->map_data.offset = 0; + mdata->pages = STp->buffer->reserved_pages; + mdata->offset = 0; } memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd)); @@ -3718,7 +3720,7 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm priority |= __GFP_ZERO; if (STbuffer->frp_segs) { - order = STbuffer->map_data.page_order; + order = STbuffer->reserved_page_order; b_size = PAGE_SIZE << order; } else { for (b_size = PAGE_SIZE, order = 0; @@ -3751,7 +3753,7 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm segs++; } STbuffer->b_data = page_address(STbuffer->reserved_pages[0]); - STbuffer->map_data.page_order = order; + STbuffer->reserved_page_order = order; return 1; } @@ -3764,7 +3766,7 @@ static void clear_buffer(struct st_buffer * st_bp) for (i=0; i < st_bp->frp_segs; i++) memset(page_address(st_bp->reserved_pages[i]), 0, - PAGE_SIZE << st_bp->map_data.page_order); + PAGE_SIZE << st_bp->reserved_page_order); st_bp->cleared = 1; } @@ -3772,7 +3774,7 @@ static void clear_buffer(struct st_buffer * st_bp) /* Release the extra buffer */ static void normalize_buffer(struct st_buffer * STbuffer) { - int i, order = STbuffer->map_data.page_order; + int i, order = STbuffer->reserved_page_order; for (i = 0; i < STbuffer->frp_segs; i++) { __free_pages(STbuffer->reserved_pages[i], order); @@ -3780,7 +3782,7 @@ static void normalize_buffer(struct st_buffer * STbuffer) } STbuffer->frp_segs = 0; STbuffer->sg_segs = 0; - STbuffer->map_data.page_order = 0; + STbuffer->reserved_page_order = 0; STbuffer->map_data.offset = 0; } @@ -3790,7 +3792,7 @@ static void normalize_buffer(struct st_buffer * STbuffer) static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count) { int i, cnt, res, offset; - int length = PAGE_SIZE << st_bp->map_data.page_order; + int length = PAGE_SIZE << st_bp->reserved_page_order; for (i = 0, offset = st_bp->buffer_bytes; i < st_bp->frp_segs && offset >= length; i++) @@ -3822,7 +3824,7 @@ static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, in static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count) { int i, cnt, res, offset; - int length = PAGE_SIZE << st_bp->map_data.page_order; + int length = PAGE_SIZE << st_bp->reserved_page_order; for (i = 0, offset = st_bp->read_pointer; i < st_bp->frp_segs && offset >= length; i++) @@ -3855,7 +3857,7 @@ static void move_buffer_data(struct st_buffer * st_bp, int offset) { int src_seg, dst_seg, src_offset = 0, dst_offset; int count, total; - int length = PAGE_SIZE << st_bp->map_data.page_order; + int length = PAGE_SIZE << st_bp->reserved_page_order; if (offset == 0) return; @@ -4577,7 +4579,6 @@ static int sgl_map_user_pages(struct st_buffer *STbp, } mdata->offset = uaddr & ~PAGE_MASK; - mdata->page_order = 0; STbp->mapped_pages = pages; return nr_pages; diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 544dc6b1f548..f91a67c6d968 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -46,6 +46,7 @@ struct st_buffer { struct st_request *last_SRpnt; struct st_cmdstatus cmdstat; struct page **reserved_pages; + int reserved_page_order; struct page **mapped_pages; struct rq_map_data map_data; unsigned char *b_data; From fdf26751111406e31e5fcb3eb8b06f299ce3a06b Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 17 Nov 2009 21:25:16 -0600 Subject: [PATCH 190/670] SCSI: fc class: fix fc_transport_init error handling commit 48de68a40aef032a2e198437f4781a83bfb938db upstream. If transport_class_register fails we should unregister any registered classes, or we will leak memory or other resources. I did a quick modprobe of scsi_transport_fc to test the patch. Signed-off-by: Mike Christie Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_transport_fc.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index c6f70dae9b2e..45be82f46321 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -648,11 +648,22 @@ static __init int fc_transport_init(void) return error; error = transport_class_register(&fc_vport_class); if (error) - return error; + goto unreg_host_class; error = transport_class_register(&fc_rport_class); if (error) - return error; - return transport_class_register(&fc_transport_class); + goto unreg_vport_class; + error = transport_class_register(&fc_transport_class); + if (error) + goto unreg_rport_class; + return 0; + +unreg_rport_class: + transport_class_unregister(&fc_rport_class); +unreg_vport_class: + transport_class_unregister(&fc_vport_class); +unreg_host_class: + transport_class_unregister(&fc_host_class); + return error; } static void __exit fc_transport_exit(void) From 14ae08205860c0a902639ed2c0a601eef9c6d171 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 16 Dec 2009 18:04:33 +0100 Subject: [PATCH 191/670] sched: Fix task_hot() test order commit e6c8fba7771563b2f3dfb96a78f36ec17e15bdf0 upstream. Make sure not to access sched_fair fields before verifying it is indeed a sched_fair task. Signed-off-by: Peter Zijlstra Cc: Mike Galbraith LKML-Reference: <20091216170517.577998058@chello.nl> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index d079a9f64a8e..279785961eae 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2036,6 +2036,9 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd) { s64 delta; + if (p->sched_class != &fair_sched_class) + return 0; + /* * Buddy candidates are cache hot: */ @@ -2044,9 +2047,6 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd) &p->se == cfs_rq_of(&p->se)->last)) return 1; - if (p->sched_class != &fair_sched_class) - return 0; - if (sysctl_sched_migration_cost == -1) return 1; if (sysctl_sched_migration_cost == 0) From c9ac6a9e841f2c82cb2a1f3adeb00858acc1c5c7 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 16 Dec 2009 16:25:42 -0800 Subject: [PATCH 192/670] x86, cpuid: Add "volatile" to asm in native_cpuid() commit 45a94d7cd45ed991914011919e7d40eb6d2546d1 upstream. xsave_cntxt_init() does something like: cpuid(0xd, ..); // find out what features FP/SSE/.. etc are supported xsetbv(); // enable the features known to OS cpuid(0xd, ..); // find out the size of the context for features enabled Depending on what features get enabled in xsetbv(), value of the cpuid.eax=0xd.ecx=0.ebx changes correspondingly (representing the size of the context that is enabled). As we don't have volatile keyword for native_cpuid(), gcc 4.1.2 optimizes away the second cpuid and the kernel continues to use the cpuid information obtained before xsetbv(), ultimately leading to kernel crash on processors supporting more state than the legacy FP/SSE. Add "volatile" for native_cpuid(). Signed-off-by: Suresh Siddha LKML-Reference: <1261009542.2745.55.camel@sbs-t61.sc.intel.com> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index c9786480f0fe..13b1885fe276 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -180,7 +180,7 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { /* ecx is often an input as well as an output. */ - asm("cpuid" + asm volatile("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), From 8e04c81a2240ac2fc5d9efe804388526331ccac7 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 16 Dec 2009 18:04:34 +0100 Subject: [PATCH 193/670] sched: Select_task_rq_fair() must honour SD_LOAD_BALANCE commit e4f4288842ee12747e10c354d72be7d424c0b627 upstream. We should skip !SD_LOAD_BALANCE domains. Signed-off-by: Peter Zijlstra Cc: Mike Galbraith LKML-Reference: <20091216170517.653578430@chello.nl> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched_fair.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 5488a5d3bc0e..199228b24bbc 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1374,6 +1374,9 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag rcu_read_lock(); for_each_domain(cpu, tmp) { + if (!(tmp->flags & SD_LOAD_BALANCE)) + continue; + /* * If power savings logic is enabled for a domain, see if we * are not overloaded, if so, don't balance wider. From fa3f5a5c1c8e6a2cbc7e21755ea7c215f8cf0577 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 10 Dec 2009 15:35:10 +0100 Subject: [PATCH 194/670] clockevents: Prevent clockevent_devices list corruption on cpu hotplug commit bb6eddf7676e1c1f3e637aa93c5224488d99036f upstream. Xiaotian Feng triggered a list corruption in the clock events list on CPU hotplug and debugged the root cause. If a CPU registers more than one per cpu clock event device, then only the active clock event device is removed on CPU_DEAD. The unused devices are kept in the clock events device list. On CPU up the clock event devices are registered again, which means that we list_add an already enqueued list_head. That results in list corruption. Resolve this by removing all devices which are associated to the dead CPU on CPU_DEAD. Reported-by: Xiaotian Feng Signed-off-by: Thomas Gleixner Tested-by: Xiaotian Feng Signed-off-by: Greg Kroah-Hartman --- kernel/time/clockevents.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 620b58abdc32..9484be456d69 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -237,8 +237,9 @@ void clockevents_exchange_device(struct clock_event_device *old, */ void clockevents_notify(unsigned long reason, void *arg) { - struct list_head *node, *tmp; + struct clock_event_device *dev, *tmp; unsigned long flags; + int cpu; spin_lock_irqsave(&clockevents_lock, flags); clockevents_do_notify(reason, arg); @@ -249,8 +250,19 @@ void clockevents_notify(unsigned long reason, void *arg) * Unregister the clock event devices which were * released from the users in the notify chain. */ - list_for_each_safe(node, tmp, &clockevents_released) - list_del(node); + list_for_each_entry_safe(dev, tmp, &clockevents_released, list) + list_del(&dev->list); + /* + * Now check whether the CPU has left unused per cpu devices + */ + cpu = *((int *)arg); + list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) { + if (cpumask_test_cpu(cpu, dev->cpumask) && + cpumask_weight(dev->cpumask) == 1) { + BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); + list_del(&dev->list); + } + } break; default: break; From f31733a7aa32257dac6390f080814a7f76b419bf Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 17 Dec 2009 01:11:27 -0500 Subject: [PATCH 195/670] pata_hpt3x2n: fix clock turnaround commit 256ace9bbd4cdb6d48d5f55d55d42fa20527fad1 upstream. The clock turnaround code still doesn't work for several reasons: - 'USE_DPLL' flag in 'ap->host->private_data' is never initialized or updated, so the driver can only set the chip to the DPLL clock mode, not the PCI mode; - the driver doesn't serialize access to the channels depending on the current clock mode like the vendor drivers, so the clock turnaround is only executed "optionally", not always as it should be; - the wrong ports are written to when hpt3x2n_set_clock() is called for the secondary channel; - hpt3x2n_set_clock() can inadvertently enable the disabled channels when resetting the channel state machines. Signed-off-by: Sergei Shtylyov Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/pata_hpt3x2n.c | 64 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index 21c5bd6084fa..d16e87e29189 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -8,7 +8,7 @@ * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2003 Red Hat Inc - * Portions Copyright (C) 2005-2007 MontaVista Software, Inc. + * Portions Copyright (C) 2005-2009 MontaVista Software, Inc. * * * TODO @@ -25,7 +25,7 @@ #include #define DRV_NAME "pata_hpt3x2n" -#define DRV_VERSION "0.3.7" +#define DRV_VERSION "0.3.8" enum { HPT_PCI_FAST = (1 << 31), @@ -262,7 +262,7 @@ static void hpt3x2n_bmdma_stop(struct ata_queued_cmd *qc) static void hpt3x2n_set_clock(struct ata_port *ap, int source) { - void __iomem *bmdma = ap->ioaddr.bmdma_addr; + void __iomem *bmdma = ap->ioaddr.bmdma_addr - ap->port_no * 8; /* Tristate the bus */ iowrite8(0x80, bmdma+0x73); @@ -272,9 +272,9 @@ static void hpt3x2n_set_clock(struct ata_port *ap, int source) iowrite8(source, bmdma+0x7B); iowrite8(0xC0, bmdma+0x79); - /* Reset state machines */ - iowrite8(0x37, bmdma+0x70); - iowrite8(0x37, bmdma+0x74); + /* Reset state machines, avoid enabling the disabled channels */ + iowrite8(ioread8(bmdma+0x70) | 0x32, bmdma+0x70); + iowrite8(ioread8(bmdma+0x74) | 0x32, bmdma+0x74); /* Complete reset */ iowrite8(0x00, bmdma+0x79); @@ -284,21 +284,10 @@ static void hpt3x2n_set_clock(struct ata_port *ap, int source) iowrite8(0x00, bmdma+0x77); } -/* Check if our partner interface is busy */ - -static int hpt3x2n_pair_idle(struct ata_port *ap) -{ - struct ata_host *host = ap->host; - struct ata_port *pair = host->ports[ap->port_no ^ 1]; - - if (pair->hsm_task_state == HSM_ST_IDLE) - return 1; - return 0; -} - static int hpt3x2n_use_dpll(struct ata_port *ap, int writing) { long flags = (long)ap->host->private_data; + /* See if we should use the DPLL */ if (writing) return USE_DPLL; /* Needed for write */ @@ -307,20 +296,35 @@ static int hpt3x2n_use_dpll(struct ata_port *ap, int writing) return 0; } +static int hpt3x2n_qc_defer(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ata_port *alt = ap->host->ports[ap->port_no ^ 1]; + int rc, flags = (long)ap->host->private_data; + int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE); + + /* First apply the usual rules */ + rc = ata_std_qc_defer(qc); + if (rc != 0) + return rc; + + if ((flags & USE_DPLL) != dpll && alt->qc_active) + return ATA_DEFER_PORT; + return 0; +} + static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc) { - struct ata_taskfile *tf = &qc->tf; struct ata_port *ap = qc->ap; int flags = (long)ap->host->private_data; + int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE); - if (hpt3x2n_pair_idle(ap)) { - int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE)); - if ((flags & USE_DPLL) != dpll) { - if (dpll == 1) - hpt3x2n_set_clock(ap, 0x21); - else - hpt3x2n_set_clock(ap, 0x23); - } + if ((flags & USE_DPLL) != dpll) { + flags &= ~USE_DPLL; + flags |= dpll; + ap->host->private_data = (void *)(long)flags; + + hpt3x2n_set_clock(ap, dpll ? 0x21 : 0x23); } return ata_sff_qc_issue(qc); } @@ -337,6 +341,8 @@ static struct ata_port_operations hpt3x2n_port_ops = { .inherits = &ata_bmdma_port_ops, .bmdma_stop = hpt3x2n_bmdma_stop, + + .qc_defer = hpt3x2n_qc_defer, .qc_issue = hpt3x2n_qc_issue, .cable_detect = hpt3x2n_cable_detect, @@ -454,7 +460,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) unsigned int f_low, f_high; int adjust; unsigned long iobase = pci_resource_start(dev, 4); - void *hpriv = NULL; + void *hpriv = (void *)USE_DPLL; int rc; rc = pcim_enable_device(dev); @@ -542,7 +548,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* Set our private data up. We only need a few flags so we use it directly */ if (pci_mhz > 60) { - hpriv = (void *)PCI66; + hpriv = (void *)(PCI66 | USE_DPLL); /* * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in * the MISC. register to stretch the UltraDMA Tss timing. From 1ee0552bc1fa0fe88b39743920bdd5f8715a3e47 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 20 Dec 2009 19:22:33 +0100 Subject: [PATCH 196/670] pata_cmd64x: fix overclocking of UDMA0-2 modes commit 509426bd46ad0903dca409803e0ee3d30f99f1e8 upstream. adev->dma_mode stores the transfer mode value not UDMA mode number so the condition in cmd64x_set_dmamode() is always true and the higher UDMA clock is always selected. This can potentially result in data corruption when UDMA33 device is used, when 40-wire cable is used or when the error recovery code decides to lower the device speed down. The issue was introduced in the commit 6a40da0 ("libata cmd64x: whack into a shape that looks like the documentation") which goes back to kernel 2.6.20. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/pata_cmd64x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index f98dffedf4bc..f0bad9be0f65 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -219,7 +219,7 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev) regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift; /* Merge the control bits */ regU |= 1 << adev->devno; /* UDMA on */ - if (adev->dma_mode > 2) /* 15nS timing */ + if (adev->dma_mode > XFER_UDMA_2) /* 15nS timing */ regU |= 4 << adev->devno; } else { regU &= ~ (1 << adev->devno); /* UDMA off */ From e255d3c8a816bfc9e365a39b8b00c4cd79671ee1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 17 Dec 2009 14:51:35 +0100 Subject: [PATCH 197/670] ASoC: wm8974: fix a wrong bit definition commit 48c03ce72f2665f79a3fe54fc6d71b8cc3d30803 upstream. The wm8974 datasheet defines BUFIOEN as bit 2. Signed-off-by: Guennadi Liakhovetski Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8974.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 98d663afc97d..b0bd1c0ac1d0 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -47,7 +47,7 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { }; #define WM8974_POWER1_BIASEN 0x08 -#define WM8974_POWER1_BUFIOEN 0x10 +#define WM8974_POWER1_BUFIOEN 0x04 struct wm8974_priv { struct snd_soc_codec codec; From aec8dc2b5d45b5b4058cfa71d3ca148fdf6c3199 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 18 Dec 2009 09:27:24 +0100 Subject: [PATCH 198/670] sound: sgio2audio/pdaudiocf/usb-audio: initialize PCM buffer commit 3e85fd614c7b6bb7f33bb04a0dcb5a3bfca4c0fe upstream. When allocating the PCM buffer, use vmalloc_user() instead of vmalloc(). Otherwise, it would be possible for applications to play the previous contents of the kernel memory to the speakers, or to read it directly if the buffer is exported to userspace. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/mips/sgio2audio.c | 2 +- sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 2 +- sound/usb/usbaudio.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 8691f4cf6191..f1d9d16b5486 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -609,7 +609,7 @@ static int snd_sgio2audio_pcm_hw_params(struct snd_pcm_substream *substream, /* alloc virtual 'dma' area */ if (runtime->dma_area) vfree(runtime->dma_area); - runtime->dma_area = vmalloc(size); + runtime->dma_area = vmalloc_user(size); if (runtime->dma_area == NULL) return -ENOMEM; runtime->dma_bytes = size; diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index d057e6489643..5cfa608823f7 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -51,7 +51,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s return 0; /* already enough large */ vfree(runtime->dma_area); } - runtime->dma_area = vmalloc_32(size); + runtime->dma_area = vmalloc_32_user(size); if (! runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8db0374e10d5..8803d9d93f84 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -752,7 +752,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s return 0; /* already large enough */ vfree(runtime->dma_area); } - runtime->dma_area = vmalloc(size); + runtime->dma_area = vmalloc_user(size); if (!runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; From 296e9be6e548bc7ede4c6b04b1adfa1d15b8ee12 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 17 Dec 2009 15:00:26 +0100 Subject: [PATCH 199/670] ALSA: hda - Fix missing capsrc_nids for ALC88x commit 035eb0cff0671ada49ba9f3e5c9e7b0cb950efea upstream. Some model quirks missed the corresponding capsrc_nids. This resulted in non-working capture source selection. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 70583719282b..e40d31f1b098 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9141,6 +9141,8 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .num_adc_nids = ARRAY_SIZE(alc889_adc_nids), .adc_nids = alc889_adc_nids, + .capsrc_nids = alc889_capsrc_nids, + .capsrc_nids = alc889_capsrc_nids, .dig_out_nid = ALC883_DIGOUT_NID, .dig_in_nid = ALC883_DIGIN_NID, .slave_dig_outs = alc883_slave_dig_outs, @@ -9187,6 +9189,7 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), + .capsrc_nids = alc883_capsrc_nids, .dig_out_nid = ALC883_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), .channel_mode = alc883_3ST_2ch_modes, @@ -9333,6 +9336,7 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), + .capsrc_nids = alc883_capsrc_nids, .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), .channel_mode = alc883_sixstack_modes, .input_mux = &alc883_capture_source, @@ -9394,6 +9398,7 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), + .capsrc_nids = alc883_capsrc_nids, .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), .channel_mode = alc883_3ST_2ch_modes, .input_mux = &alc883_lenovo_101e_capture_source, @@ -9573,6 +9578,7 @@ static struct alc_config_preset alc882_presets[] = { alc880_gpio1_init_verbs }, .adc_nids = alc883_adc_nids, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), + .capsrc_nids = alc883_capsrc_nids, .dac_nids = alc883_dac_nids, .num_dacs = ARRAY_SIZE(alc883_dac_nids), .channel_mode = alc889A_mb31_6ch_modes, From 5ab8996c82fdb3fa04ca1d72b1fb388ce9c42378 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Mon, 21 Dec 2009 16:20:04 -0800 Subject: [PATCH 200/670] acerhdf: limit modalias matching to supported commit bdc731bc5fcd1794e9ac8ac80c389d302381c123 upstream. BugLink: https://bugs.launchpad.net/ubuntu/+bug/435958 The module alias currently matches any Acer computer but when loaded the BIOS checks will only succeed on Aspire One models. This causes a invalid BIOS warning for all other models (seen on Aspire 4810T). This is not fatal but worries users that see this message. Limiting the moule alias to models starting with AOA or DOA for Packard Bell. Signed-off-by: Stefan Bader Acked-by: Borislav Petkov Acked-by: Peter Feuerer Signed-off-by: Andrew Morton Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/acerhdf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index d8b4229108b8..4d922e42bcd7 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -640,9 +640,10 @@ static void __exit acerhdf_exit(void) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Peter Feuerer"); MODULE_DESCRIPTION("Aspire One temperature and fan driver"); -MODULE_ALIAS("dmi:*:*Acer*:*:"); -MODULE_ALIAS("dmi:*:*Gateway*:*:"); -MODULE_ALIAS("dmi:*:*Packard Bell*:*:"); +MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:"); module_init(acerhdf_init); module_exit(acerhdf_exit); From 3872bf59ad0d88c81d7fb70ac86a5fc2f8aa6d34 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 22 Dec 2009 02:42:52 -0500 Subject: [PATCH 201/670] ACPI: EC: Fix MSI DMI detection commit 55b313f249e11b815fd0be51869f166aaf368f44 upstream. MSI strings should be ORed, not ANDed. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14446 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/ec.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index baef28c1e630..7511029a1e0b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -916,6 +916,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id) /* MSI EC needs special treatment, enable it */ static int ec_flag_msi(const struct dmi_system_id *id) { + printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n"); EC_FLAGS_MSI = 1; EC_FLAGS_VALIDATE_ECDT = 1; return 0; @@ -928,8 +929,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL}, { ec_flag_msi, "MSI hardware", { - DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star"), - DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star") }, NULL}, + DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star")}, NULL}, + { + ec_flag_msi, "MSI hardware", { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star")}, NULL}, + { + ec_flag_msi, "MSI hardware", { + DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL}, { ec_validate_ecdt, "ASUS hardware", { DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL}, From 8aafd7d4acb527c3dfd95d24af190528cc58326b Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 15 Dec 2009 22:01:57 +0800 Subject: [PATCH 202/670] ACPI: Use the return result of ACPI lid notifier chain correctly commit 13c199c0d0cf78b27592991129fb8cbcfc5164de upstream. On some laptops it will return NOTIFY_OK(non-zero) when calling the ACPI LID notifier. Then it is used as the result of ACPI LID resume function, which will complain the following warning message in course of suspend/resume: >PM: Device PNP0C0D:00 failed to resume: error 1 This patch is to eliminate the above warning message. http://bugzilla.kernel.org/show_bug.cgi?id=14782 Signed-off-by: Zhao Yakui Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/button.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 0c9c6a9a002c..8a95e8329df7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -282,6 +282,13 @@ static int acpi_lid_send_state(struct acpi_device *device) if (ret == NOTIFY_DONE) ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); + if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { + /* + * It is also regarded as success if the notifier_chain + * returns NOTIFY_OK or NOTIFY_DONE. + */ + ret = 0; + } return ret; } From d75621cbb1dfadcd6801b39c03867bab60d94dd7 Mon Sep 17 00:00:00 2001 From: Neil Campbell Date: Mon, 14 Dec 2009 04:08:57 +0000 Subject: [PATCH 203/670] powerpc: Handle VSX alignment faults correctly in little-endian mode commit bb7f20b1c639606def3b91f4e4aca6daeee5d80a upstream. This patch fixes the handling of VSX alignment faults in little-endian mode (the current code assumes the processor is in big-endian mode). The patch also makes the handlers clear the top 8 bytes of the register when handling an 8 byte VSX load. This is based on 2.6.32. Signed-off-by: Neil Campbell Acked-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/align.c | 63 +++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index a5b632e52fae..f0c624ff59d1 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -642,10 +642,14 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg, */ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, unsigned int areg, struct pt_regs *regs, - unsigned int flags, unsigned int length) + unsigned int flags, unsigned int length, + unsigned int elsize) { char *ptr; + unsigned long *lptr; int ret = 0; + int sw = 0; + int i, j; flush_vsx_to_thread(current); @@ -654,19 +658,35 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, else ptr = (char *) ¤t->thread.vr[reg - 32]; - if (flags & ST) - ret = __copy_to_user(addr, ptr, length); - else { - if (flags & SPLT){ - ret = __copy_from_user(ptr, addr, length); - ptr += length; + lptr = (unsigned long *) ptr; + + if (flags & SW) + sw = elsize-1; + + for (j = 0; j < length; j += elsize) { + for (i = 0; i < elsize; ++i) { + if (flags & ST) + ret |= __put_user(ptr[i^sw], addr + i); + else + ret |= __get_user(ptr[i^sw], addr + i); } - ret |= __copy_from_user(ptr, addr, length); + ptr += elsize; + addr += elsize; } - if (flags & U) - regs->gpr[areg] = regs->dar; - if (ret) + + if (!ret) { + if (flags & U) + regs->gpr[areg] = regs->dar; + + /* Splat load copies the same data to top and bottom 8 bytes */ + if (flags & SPLT) + lptr[1] = lptr[0]; + /* For 8 byte loads, zero the top 8 bytes */ + else if (!(flags & ST) && (8 == length)) + lptr[1] = 0; + } else return -EFAULT; + return 1; } #endif @@ -767,16 +787,25 @@ int fix_alignment(struct pt_regs *regs) #ifdef CONFIG_VSX if ((instruction & 0xfc00003e) == 0x7c000018) { - /* Additional register addressing bit (64 VSX vs 32 FPR/GPR */ + unsigned int elsize; + + /* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */ reg |= (instruction & 0x1) << 5; /* Simple inline decoder instead of a table */ + /* VSX has only 8 and 16 byte memory accesses */ + nb = 8; if (instruction & 0x200) nb = 16; - else if (instruction & 0x080) - nb = 8; - else - nb = 4; + + /* Vector stores in little-endian mode swap individual + elements, so process them separately */ + elsize = 4; + if (instruction & 0x80) + elsize = 8; + flags = 0; + if (regs->msr & MSR_LE) + flags |= SW; if (instruction & 0x100) flags |= ST; if (instruction & 0x040) @@ -787,7 +816,7 @@ int fix_alignment(struct pt_regs *regs) nb = 8; } PPC_WARN_EMULATED(vsx); - return emulate_vsx(addr, reg, areg, regs, flags, nb); + return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize); } #endif /* A size of 0 indicates an instruction we don't support, with From 474ae5e72b8acc3c79354f0b14e77fb9e09108ff Mon Sep 17 00:00:00 2001 From: Eric Millbrandt Date: Tue, 22 Dec 2009 10:13:24 -0500 Subject: [PATCH 204/670] ASoC: Do not write to invalid registers on the wm9712. commit 48e3cbb3f67a27d9c2db075f3d0f700246c40caa upstream. This patch fixes a bug where "virtual" registers were being written to the ac97 bus. This was causing unrelated registers to become corrupted (headphone 0x04, touchscreen 0x78, etc). This patch duplicates protection that was included in the wm9713 driver. Signed-off-by: Eric Millbrandt Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm9712.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 1fd4e88f50cf..e9123f54202d 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -464,7 +464,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, { u16 *cache = codec->reg_cache; - soc_ac97_ops.write(codec->ac97, reg, val); + if (reg < 0x7c) + soc_ac97_ops.write(codec->ac97, reg, val); reg = reg >> 1; if (reg < (ARRAY_SIZE(wm9712_reg))) cache[reg] = val; From 2d67231fb86da345be96ba212dfeb4d8c912520b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 20 Dec 2009 16:08:40 +1000 Subject: [PATCH 205/670] drm/radeon: fix build on 64-bit with some compilers. commit 794f3141a194a4f4c28c1d417b071a901f78d9bb upstream. drivers/gpu/drm/radeon/radeon_test.c:45: undefined reference to `__udivdi3' Reported-by: Mr. James W. Laferriere Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index f8a465d9a1cf..c8942cae425d 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -42,8 +42,8 @@ void radeon_test_moves(struct radeon_device *rdev) /* Number of tests = * (Total GTT - IB pool - writeback page - ring buffer) / test size */ - n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE - - rdev->cp.ring_size) / size; + n = ((u32)(rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE - + rdev->cp.ring_size)) / size; gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL); if (!gtt_obj) { From 702a0a0aed69a97f7001c67a652f49934ac7de0d Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 21 Dec 2009 15:36:44 -0800 Subject: [PATCH 206/670] USB: emi62: fix crash when trying to load EMI 6|2 firmware commit ac06c06770bb8761b1f1f9bdf2f5420fa6d3e9fa upstream. While converting emi62 to use request_firmware(), the driver was also changed to use the ihex helper functions. However, this broke the loading of the FPGA firmware because the code tries to access the addr field of the EOF record which works with a plain array that has an empty last record but not with the ihex helper functions where the end of the data is signaled with a NULL record pointer, resulting in: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] emi62_load_firmware+0x33c/0x740 [emi62] This can be fixed by changing the loop condition to test the return value of ihex_next_binrec() directly (like in emi26.c). Signed-off-by: Clemens Ladisch Reported-and-tested-by: Der Mickster Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/emi62.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 602ee05ba9ff..59860b328534 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -167,7 +167,7 @@ static int emi62_load_firmware (struct usb_device *dev) err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } - } while (i > 0); + } while (rec); /* Assert reset (stop the CPU in the EMI) */ err = emi62_set_reset(dev,1); From 5a82dd5dcafaf91f894f68cbb16359a1338900f5 Mon Sep 17 00:00:00 2001 From: Donny Kurnia Date: Wed, 23 Dec 2009 19:03:12 +0700 Subject: [PATCH 207/670] USB: option: support hi speed for modem Haier CE100 commit c983202bd03eb82394ef1dce5906702fcbc7bb80 upstream. I made this patch for usbserial driver to add the support for EVDO modem Haier CE100. The bugs report for this is here: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/490068 This patch based on these post: http://blankblondtank.wordpress.com/2009/09/04/mengoptimalkan-koneksi-modem-haier-ce-100-cdma-di-linux/ http://tantos.web.id/blogs/how-to-internet-connection-using-cdma-evdo-modem-and-karmic-koala-ubuntu-9-10 I hope this patch can help other that have the Haier C100 modem, mostly in my country, Indonesia. Signed-off-by: Donny Kurnia Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index dffc8a1e84d7..be3dff16d7c4 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -340,6 +340,10 @@ static int option_resume(struct usb_serial *serial); #define FOUR_G_SYSTEMS_VENDOR_ID 0x1c9e #define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603 +/* Haier products */ +#define HAIER_VENDOR_ID 0x201e +#define HAIER_PRODUCT_CE100 0x2009 + static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -641,6 +645,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) }, + { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); From 3635acd7f7f86d7319c15f3de8be7579b41defc2 Mon Sep 17 00:00:00 2001 From: pancho horrillo Date: Wed, 23 Dec 2009 11:09:13 +0100 Subject: [PATCH 208/670] USB: Fix a bug on appledisplay.c regarding signedness commit 37e9066b2f85480d99d3795373f5ef0b00ac1189 upstream. brightness status is reported by the Apple Cinema Displays as an 'unsigned char' (u8) value, but the code used 'char' instead. Note that he driver was developed on the PowerPC architecture, where the two types are synonymous, which is not always the case. Fixed that. Otherwise the driver will interpret brightness levels > 127 as negative, and fail to load. Signed-off-by: pancho horrillo Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/appledisplay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 1d8e39a557d9..62ff5e729110 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -72,8 +72,8 @@ struct appledisplay { struct usb_device *udev; /* usb device */ struct urb *urb; /* usb request block */ struct backlight_device *bd; /* backlight device */ - char *urbdata; /* interrupt URB data buffer */ - char *msgdata; /* control message data buffer */ + u8 *urbdata; /* interrupt URB data buffer */ + u8 *msgdata; /* control message data buffer */ struct delayed_work work; int button_pressed; From b71bfa6a117e070139ce2cf23175378f276b9dd8 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 15 Dec 2009 13:30:01 +0200 Subject: [PATCH 209/670] USB: musb: gadget_ep0: avoid SetupEnd interrupt commit 17be5c5f5ef99c94374e07f71effa78e93a20eda upstream. Gadget stalling a zero-length SETUP request results in this error message: SetupEnd came in a wrong ep0stage idle In order to avoid it, always set the CSR0.DataEnd bit after detecting a zero- length request. Add the missing '\n' to the error message itself as well... Signed-off-by: Sergei Shtylyov Acked-by: Anand Gadiyar Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget_ep0.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 1c44b975049c..067e5a95b149 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -647,7 +647,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; break; default: - ERR("SetupEnd came in a wrong ep0stage %s", + ERR("SetupEnd came in a wrong ep0stage %s\n", decode_ep0stage(musb->ep0_state)); } csr = musb_readw(regs, MUSB_CSR0); @@ -770,12 +770,18 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) handled = service_zero_data_request( musb, &setup); + /* + * We're expecting no data in any case, so + * always set the DATAEND bit -- doing this + * here helps avoid SetupEnd interrupt coming + * in the idle stage when we're stalling... + */ + musb->ackpend |= MUSB_CSR0_P_DATAEND; + /* status stage might be immediate */ - if (handled > 0) { - musb->ackpend |= MUSB_CSR0_P_DATAEND; + if (handled > 0) musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; - } break; /* sequence #1 (IN to host), includes GET_STATUS From f661c3feba2d9455614d64ba0f73f182a1b39456 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 16 Dec 2009 19:23:43 +0100 Subject: [PATCH 210/670] Bluetooth: Prevent ill-timed autosuspend in USB driver commit 652fd781a52ad6e24b908cd8b83d12699754f253 upstream. The device must be marked busy as it receives data. Signed-off-by: Oliver Neukum Tested-by: Matthew Garrett Signed-off-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 44bc8bbabf54..1be76318f516 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -307,6 +307,7 @@ static void btusb_bulk_complete(struct urb *urb) return; usb_anchor_urb(urb, &data->bulk_anchor); + usb_mark_last_busy(data->udev); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { From c6d7a67b493a4bc990a2c8155787ff70903a2335 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 8 Dec 2009 15:50:41 -0500 Subject: [PATCH 211/670] USB: rename usb_configure_device commit 8d8558d10806b7e805cb80df867ebb0a453d4765 upstream. This patch (as1314) renames usb_configure_device() and usb_configure_device_otg() in the hub driver. Neither name is appropriate because these routines enumerate devices, they don't configure them. That's handled by usb_choose_configuration() and usb_set_configuration(). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0f857e645058..276fc688f98d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1612,12 +1612,12 @@ static inline void announce_device(struct usb_device *udev) { } #endif /** - * usb_configure_device_otg - FIXME (usbcore-internal) + * usb_enumerate_device_otg - FIXME (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) * - * Do configuration for On-The-Go devices + * Finish enumeration for On-The-Go devices */ -static int usb_configure_device_otg(struct usb_device *udev) +static int usb_enumerate_device_otg(struct usb_device *udev) { int err = 0; @@ -1688,7 +1688,7 @@ static int usb_configure_device_otg(struct usb_device *udev) /** - * usb_configure_device - Detect and probe device intfs/otg (usbcore-internal) + * usb_enumerate_device - Read device configs/intfs/otg (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) * * This is only called by usb_new_device() and usb_authorize_device() @@ -1699,7 +1699,7 @@ static int usb_configure_device_otg(struct usb_device *udev) * the string descriptors, as they will be errored out by the device * until it has been authorized. */ -static int usb_configure_device(struct usb_device *udev) +static int usb_enumerate_device(struct usb_device *udev) { int err; @@ -1723,7 +1723,7 @@ static int usb_configure_device(struct usb_device *udev) udev->descriptor.iManufacturer); udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); } - err = usb_configure_device_otg(udev); + err = usb_enumerate_device_otg(udev); fail: return err; } @@ -1733,8 +1733,8 @@ static int usb_configure_device(struct usb_device *udev) * usb_new_device - perform initial device setup (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) * - * This is called with devices which have been enumerated, but not yet - * configured. The device descriptor is available, but not descriptors + * This is called with devices which have been detected but not fully + * enumerated. The device descriptor is available, but not descriptors * for any device configuration. The caller must have locked either * the parent hub (if udev is a normal device) or else the * usb_bus_list_lock (if udev is a root hub). The parent's pointer to @@ -1757,8 +1757,8 @@ int usb_new_device(struct usb_device *udev) if (udev->parent) usb_autoresume_device(udev->parent); - usb_detect_quirks(udev); /* Determine quirks */ - err = usb_configure_device(udev); /* detect & probe dev/intfs */ + usb_detect_quirks(udev); + err = usb_enumerate_device(udev); /* Read descriptors */ if (err < 0) goto fail; dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n", @@ -1849,9 +1849,9 @@ int usb_authorize_device(struct usb_device *usb_dev) goto error_device_descriptor; } usb_dev->authorized = 1; - result = usb_configure_device(usb_dev); + result = usb_enumerate_device(usb_dev); if (result < 0) - goto error_configure; + goto error_enumerate; /* Choose and set the configuration. This registers the interfaces * with the driver core and lets interface drivers bind to them. */ @@ -1866,7 +1866,7 @@ int usb_authorize_device(struct usb_device *usb_dev) } } dev_info(&usb_dev->dev, "authorized to connect\n"); -error_configure: +error_enumerate: error_device_descriptor: error_autoresume: out_authorized: From 526fed8b3c60bd7746de0df7676c83800c36b906 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 8 Dec 2009 15:54:44 -0500 Subject: [PATCH 212/670] USB: fix bugs in usb_(de)authorize_device commit da307123c621b01cce147a4be313d8a754674f63 upstream. This patch (as1315) fixes some bugs in the USB core authorization code: usb_deauthorize_device() should deallocate the device strings instead of leaking them, and it should invoke usb_destroy_configuration() (which does proper reference counting) instead of freeing the config information directly. usb_authorize_device() shouldn't change the device strings until it knows that the authorization will succeed, and it should autosuspend the device at the end (having autoresumed the device at the start). Because the device strings can be changed, the sysfs routines to display the strings must protect the string pointers by locking the device. Signed-off-by: Alan Stern CC: Inaky Perez-Gonzalez Acked-by: David Vrabel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 32 ++++++++++++++++++++------------ drivers/usb/core/sysfs.c | 6 +++++- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 276fc688f98d..8b0c2350d951 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1803,21 +1803,23 @@ int usb_new_device(struct usb_device *udev) */ int usb_deauthorize_device(struct usb_device *usb_dev) { - unsigned cnt; usb_lock_device(usb_dev); if (usb_dev->authorized == 0) goto out_unauthorized; + usb_dev->authorized = 0; usb_set_configuration(usb_dev, -1); + + kfree(usb_dev->product); usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); + kfree(usb_dev->manufacturer); usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); + kfree(usb_dev->serial); usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); - kfree(usb_dev->config); - usb_dev->config = NULL; - for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++) - kfree(usb_dev->rawdescriptors[cnt]); + + usb_destroy_configuration(usb_dev); usb_dev->descriptor.bNumConfigurations = 0; - kfree(usb_dev->rawdescriptors); + out_unauthorized: usb_unlock_device(usb_dev); return 0; @@ -1827,15 +1829,11 @@ int usb_deauthorize_device(struct usb_device *usb_dev) int usb_authorize_device(struct usb_device *usb_dev) { int result = 0, c; + usb_lock_device(usb_dev); if (usb_dev->authorized == 1) goto out_authorized; - kfree(usb_dev->product); - usb_dev->product = NULL; - kfree(usb_dev->manufacturer); - usb_dev->manufacturer = NULL; - kfree(usb_dev->serial); - usb_dev->serial = NULL; + result = usb_autoresume_device(usb_dev); if (result < 0) { dev_err(&usb_dev->dev, @@ -1848,6 +1846,14 @@ int usb_authorize_device(struct usb_device *usb_dev) "authorization: %d\n", result); goto error_device_descriptor; } + + kfree(usb_dev->product); + usb_dev->product = NULL; + kfree(usb_dev->manufacturer); + usb_dev->manufacturer = NULL; + kfree(usb_dev->serial); + usb_dev->serial = NULL; + usb_dev->authorized = 1; result = usb_enumerate_device(usb_dev); if (result < 0) @@ -1866,8 +1872,10 @@ int usb_authorize_device(struct usb_device *usb_dev) } } dev_info(&usb_dev->dev, "authorized to connect\n"); + error_enumerate: error_device_descriptor: + usb_autosuspend_device(usb_dev); error_autoresume: out_authorized: usb_unlock_device(usb_dev); // complements locktree diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 7ec3041ae79e..8752e5532369 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -82,9 +82,13 @@ static ssize_t show_##name(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ struct usb_device *udev; \ + int retval; \ \ udev = to_usb_device(dev); \ - return sprintf(buf, "%s\n", udev->name); \ + usb_lock_device(udev); \ + retval = sprintf(buf, "%s\n", udev->name); \ + usb_unlock_device(udev); \ + return retval; \ } \ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); From 4ba51fe7d303115c0eef7cfe4a326fdff536302f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 13 Dec 2009 05:47:04 +0000 Subject: [PATCH 213/670] drivers/net/usb: Correct code taking the size of a pointer commit 6057912d7baad31be9819518674ffad349a065b1 upstream. sizeof(dev->dev_addr) is the size of a pointer. A few lines above, the size of this field is obtained using netdev->addr_len for a call to memcpy, so do the same here. A simplified version of the semantic patch that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression *x; expression f; type T; @@ *f(...,(T)x,...) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/rtl8150.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index b091e20ca167..f14d225404da 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -324,7 +324,7 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p) dbg("%02X:", netdev->dev_addr[i]); dbg("%02X\n", netdev->dev_addr[i]); /* Set the IDR registers. */ - set_registers(dev, IDR, sizeof(netdev->dev_addr), netdev->dev_addr); + set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr); #ifdef EEPROM_WRITE { u8 cr; From acb8be461bc008fea70999310812a4f4638d9596 Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Mon, 28 Dec 2009 13:28:25 -0800 Subject: [PATCH 214/670] x86: SGI UV: Fix writes to led registers on remote uv hubs commit 39d30770992895d55789de64bad2349510af68d0 upstream. The wrong address was being used to write the SCIR led regs on remote hubs. Also, there was an inconsistency between how BIOS and the kernel indexed these regs. Standardize on using the lower 6 bits of the APIC ID as the index. This patch fixes the problem of writing to an errant address to a cpu # >= 64. Signed-off-by: Mike Travis Reviewed-by: Jack Steiner Cc: Robin Holt Cc: Linus Torvalds LKML-Reference: <4B3922F9.3060905@sgi.com> [ v2: fix a number of annoying checkpatch artifacts and whitespace noise ] Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/uv/uv_hub.h | 86 +++++++++++++++++------------- arch/x86/kernel/apic/x2apic_uv_x.c | 12 ++--- 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h index d1414af98559..e90a8a969765 100644 --- a/arch/x86/include/asm/uv/uv_hub.h +++ b/arch/x86/include/asm/uv/uv_hub.h @@ -31,20 +31,20 @@ * contiguous (although various IO spaces may punch holes in * it).. * - * N - Number of bits in the node portion of a socket physical - * address. + * N - Number of bits in the node portion of a socket physical + * address. * - * NASID - network ID of a router, Mbrick or Cbrick. Nasid values of - * routers always have low bit of 1, C/MBricks have low bit - * equal to 0. Most addressing macros that target UV hub chips - * right shift the NASID by 1 to exclude the always-zero bit. - * NASIDs contain up to 15 bits. + * NASID - network ID of a router, Mbrick or Cbrick. Nasid values of + * routers always have low bit of 1, C/MBricks have low bit + * equal to 0. Most addressing macros that target UV hub chips + * right shift the NASID by 1 to exclude the always-zero bit. + * NASIDs contain up to 15 bits. * * GNODE - NASID right shifted by 1 bit. Most mmrs contain gnodes instead * of nasids. * - * PNODE - the low N bits of the GNODE. The PNODE is the most useful variant - * of the nasid for socket usage. + * PNODE - the low N bits of the GNODE. The PNODE is the most useful variant + * of the nasid for socket usage. * * * NumaLink Global Physical Address Format: @@ -71,12 +71,12 @@ * * * APICID format - * NOTE!!!!!! This is the current format of the APICID. However, code - * should assume that this will change in the future. Use functions - * in this file for all APICID bit manipulations and conversion. + * NOTE!!!!!! This is the current format of the APICID. However, code + * should assume that this will change in the future. Use functions + * in this file for all APICID bit manipulations and conversion. * - * 1111110000000000 - * 5432109876543210 + * 1111110000000000 + * 5432109876543210 * pppppppppplc0cch * sssssssssss * @@ -89,9 +89,9 @@ * Note: Processor only supports 12 bits in the APICID register. The ACPI * tables hold all 16 bits. Software needs to be aware of this. * - * Unless otherwise specified, all references to APICID refer to - * the FULL value contained in ACPI tables, not the subset in the - * processor APICID register. + * Unless otherwise specified, all references to APICID refer to + * the FULL value contained in ACPI tables, not the subset in the + * processor APICID register. */ @@ -151,16 +151,16 @@ struct uv_hub_info_s { }; DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); -#define uv_hub_info (&__get_cpu_var(__uv_hub_info)) +#define uv_hub_info (&__get_cpu_var(__uv_hub_info)) #define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu)) /* * Local & Global MMR space macros. - * Note: macros are intended to be used ONLY by inline functions - * in this file - not by other kernel code. - * n - NASID (full 15-bit global nasid) - * g - GNODE (full 15-bit global nasid, right shifted 1) - * p - PNODE (local part of nsids, right shifted 1) + * Note: macros are intended to be used ONLY by inline functions + * in this file - not by other kernel code. + * n - NASID (full 15-bit global nasid) + * g - GNODE (full 15-bit global nasid, right shifted 1) + * p - PNODE (local part of nsids, right shifted 1) */ #define UV_NASID_TO_PNODE(n) (((n) >> 1) & uv_hub_info->pnode_mask) #define UV_PNODE_TO_GNODE(p) ((p) |uv_hub_info->gnode_extra) @@ -213,8 +213,8 @@ DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); /* * Macros for converting between kernel virtual addresses, socket local physical * addresses, and UV global physical addresses. - * Note: use the standard __pa() & __va() macros for converting - * between socket virtual and socket physical addresses. + * Note: use the standard __pa() & __va() macros for converting + * between socket virtual and socket physical addresses. */ /* socket phys RAM --> UV global physical address */ @@ -265,21 +265,18 @@ static inline int uv_apicid_to_pnode(int apicid) * Access global MMRs using the low memory MMR32 space. This region supports * faster MMR access but not all MMRs are accessible in this space. */ -static inline unsigned long *uv_global_mmr32_address(int pnode, - unsigned long offset) +static inline unsigned long *uv_global_mmr32_address(int pnode, unsigned long offset) { return __va(UV_GLOBAL_MMR32_BASE | UV_GLOBAL_MMR32_PNODE_BITS(pnode) | offset); } -static inline void uv_write_global_mmr32(int pnode, unsigned long offset, - unsigned long val) +static inline void uv_write_global_mmr32(int pnode, unsigned long offset, unsigned long val) { writeq(val, uv_global_mmr32_address(pnode, offset)); } -static inline unsigned long uv_read_global_mmr32(int pnode, - unsigned long offset) +static inline unsigned long uv_read_global_mmr32(int pnode, unsigned long offset) { return readq(uv_global_mmr32_address(pnode, offset)); } @@ -288,25 +285,32 @@ static inline unsigned long uv_read_global_mmr32(int pnode, * Access Global MMR space using the MMR space located at the top of physical * memory. */ -static inline unsigned long *uv_global_mmr64_address(int pnode, - unsigned long offset) +static inline unsigned long *uv_global_mmr64_address(int pnode, unsigned long offset) { return __va(UV_GLOBAL_MMR64_BASE | UV_GLOBAL_MMR64_PNODE_BITS(pnode) | offset); } -static inline void uv_write_global_mmr64(int pnode, unsigned long offset, - unsigned long val) +static inline void uv_write_global_mmr64(int pnode, unsigned long offset, unsigned long val) { writeq(val, uv_global_mmr64_address(pnode, offset)); } -static inline unsigned long uv_read_global_mmr64(int pnode, - unsigned long offset) +static inline unsigned long uv_read_global_mmr64(int pnode, unsigned long offset) { return readq(uv_global_mmr64_address(pnode, offset)); } +static inline void uv_write_global_mmr8(int pnode, unsigned long offset, unsigned char val) +{ + writeb(val, uv_global_mmr64_address(pnode, offset)); +} + +static inline unsigned char uv_read_global_mmr8(int pnode, unsigned long offset) +{ + return readb(uv_global_mmr64_address(pnode, offset)); +} + /* * Access hub local MMRs. Faster than using global space but only local MMRs * are accessible. @@ -426,11 +430,17 @@ static inline void uv_set_scir_bits(unsigned char value) } } +static inline unsigned long uv_scir_offset(int apicid) +{ + return SCIR_LOCAL_MMR_BASE | (apicid & 0x3f); +} + static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value) { if (uv_cpu_hub_info(cpu)->scir.state != value) { + uv_write_global_mmr8(uv_cpu_to_pnode(cpu), + uv_cpu_hub_info(cpu)->scir.offset, value); uv_cpu_hub_info(cpu)->scir.state = value; - uv_write_local_mmr8(uv_cpu_hub_info(cpu)->scir.offset, value); } } diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 326c25477d3d..2ab35358985e 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -607,8 +607,10 @@ void __init uv_system_init(void) uv_rtc_init(); for_each_present_cpu(cpu) { + int apicid = per_cpu(x86_cpu_to_apicid, cpu); + nid = cpu_to_node(cpu); - pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu)); + pnode = uv_apicid_to_pnode(apicid); blade = boot_pnode_to_blade(pnode); lcpu = uv_blade_info[blade].nr_possible_cpus; uv_blade_info[blade].nr_possible_cpus++; @@ -629,15 +631,13 @@ void __init uv_system_init(void) uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra; uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base; uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id; - uv_cpu_hub_info(cpu)->scir.offset = SCIR_LOCAL_MMR_BASE + lcpu; + uv_cpu_hub_info(cpu)->scir.offset = uv_scir_offset(apicid); uv_node_to_blade[nid] = blade; uv_cpu_to_blade[cpu] = blade; max_pnode = max(pnode, max_pnode); - printk(KERN_DEBUG "UV: cpu %d, apicid 0x%x, pnode %d, nid %d, " - "lcpu %d, blade %d\n", - cpu, per_cpu(x86_cpu_to_apicid, cpu), pnode, nid, - lcpu, blade); + printk(KERN_DEBUG "UV: cpu %d, apicid 0x%x, pnode %d, nid %d, lcpu %d, blade %d\n", + cpu, apicid, pnode, nid, lcpu, blade); } /* Add blade/pnode info for nodes without cpus */ From ed8f6eb171b6965d5372f008c3b2267f1da57a92 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 30 Dec 2009 12:08:49 +1100 Subject: [PATCH 215/670] md: Fix unfortunate interaction with evms commit cbd1998377504df005302ac90d49db72a48552a6 upstream. evms configures md arrays by: open device send ioctl close device for each different ioctl needed. Since 2.6.29, the device can disappear after the 'close' unless a significant configuration has happened to the device. The change made by "SET_ARRAY_INFO" can too minor to stop the device from disappearing, but important enough that losing the change is bad. So: make sure SET_ARRAY_INFO sets mddev->ctime, and keep the device active as long as ctime is non-zero (it gets zeroed with lots of other things when the array is stopped). This is suitable for -stable kernels since 2.6.29. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 02e45513789b..c6a6685b0806 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -282,7 +282,9 @@ static void mddev_put(mddev_t *mddev) if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) return; if (!mddev->raid_disks && list_empty(&mddev->disks) && - !mddev->hold_active) { + mddev->ctime == 0 && !mddev->hold_active) { + /* Array is not configured at all, and not held active, + * so destroy it */ list_del(&mddev->all_mddevs); if (mddev->gendisk) { /* we did a probe so need to clean up. @@ -5071,6 +5073,10 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) mddev->minor_version = info->minor_version; mddev->patch_version = info->patch_version; mddev->persistent = !info->not_persistent; + /* ensure mddev_put doesn't delete this now that there + * is some minimal configuration. + */ + mddev->ctime = get_seconds(); return 0; } mddev->major_version = MD_MAJOR_VERSION; From c4ddbba638a74b9110801026517e892e5a8db6ad Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 16 Dec 2009 16:28:03 +0100 Subject: [PATCH 216/670] dma: at_hdmac: correct incompatible type for argument 1 of 'spin_lock_bh' commit 4297a462f455e38f08976df7b16c849614a287da upstream. Correct a typo error in locking calls. Signed-off-by: Nicolas Ferre Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dma/at_hdmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 7585c4164bd5..c558fa13b4b7 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -815,7 +815,7 @@ atc_is_tx_complete(struct dma_chan *chan, dev_vdbg(chan2dev(chan), "is_tx_complete: %d (d%d, u%d)\n", cookie, done ? *done : 0, used ? *used : 0); - spin_lock_bh(atchan->lock); + spin_lock_bh(&atchan->lock); last_complete = atchan->completed_cookie; last_used = chan->cookie; @@ -830,7 +830,7 @@ atc_is_tx_complete(struct dma_chan *chan, ret = dma_async_is_complete(cookie, last_complete, last_used); } - spin_unlock_bh(atchan->lock); + spin_unlock_bh(&atchan->lock); if (done) *done = last_complete; From 120dbaa5f31dfea13be03da90d90dc2cfed77841 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Thu, 17 Dec 2009 18:00:36 -0600 Subject: [PATCH 217/670] dma-debug: Do not add notifier when dma debugging is disabled. commit f797d9881b62c2ddb1d2e7bd80d87141949c84aa upstream. If CONFIG_HAVE_DMA_API_DEBUG is defined and "dma_debug=off" is specified on the kernel command line, when you detach a driver from a device you can cause the following NULL pointer dereference: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] dma_debug_device_change+0x5d/0x117 The problem is that the dma_debug_device_change notifier function is added to the bus notifier chain even though the dma_entry_hash array was never initialized. If dma debugging is disabled, this patch both prevents dma_debug_device_change notifiers from being added to the chain, and additionally ensures that the dma_debug_device_change notifier function is a no-op. Signed-off-by: Shaun Ruffell Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- lib/dma-debug.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index ce6b7eabf674..dcd43e30968e 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -676,6 +676,8 @@ static int dma_debug_device_change(struct notifier_block *nb, struct device *dev = data; int count; + if (global_disable) + return; switch (action) { case BUS_NOTIFY_UNBOUND_DRIVER: @@ -697,6 +699,9 @@ void dma_debug_add_bus(struct bus_type *bus) { struct notifier_block *nb; + if (global_disable) + return; + nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL); if (nb == NULL) { pr_err("dma_debug_add_bus: out of memory\n"); From 6cb5fcc95450e4a8e7423128dec3d43caac8f42b Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 31 Dec 2009 15:16:23 +0100 Subject: [PATCH 218/670] dma-debug: Fix bug causing build warning commit a8fe9ea200ea21421ea750423d1d4d4f7ce037cf upstream. Stephen Rothwell reported the following build warning: lib/dma-debug.c: In function 'dma_debug_device_change': lib/dma-debug.c:680: warning: 'return' with no value, in function returning non-void Introduced by commit f797d9881b62c2ddb1d2e7bd80d87141949c84aa ("dma-debug: Do not add notifier when dma debugging is disabled"). Return 0 [notify-done] when disabled. (this is standard bus notifier behavior.) Signed-off-by: Shaun Ruffell Signed-off-by: Joerg Roedel Cc: Linus Torvalds LKML-Reference: <20091231125624.GA14666@liondog.tnic> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- lib/dma-debug.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index dcd43e30968e..5a77c7cfb59e 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -670,14 +670,13 @@ static int device_dma_allocations(struct device *dev) return count; } -static int dma_debug_device_change(struct notifier_block *nb, - unsigned long action, void *data) +static int dma_debug_device_change(struct notifier_block *nb, unsigned long action, void *data) { struct device *dev = data; int count; if (global_disable) - return; + return 0; switch (action) { case BUS_NOTIFY_UNBOUND_DRIVER: From cd7bc18e0908a287e64cf4593a480b613b07fdce Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 3 Dec 2009 08:09:41 -0500 Subject: [PATCH 219/670] cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS referrals commit a2934c7b363ddcc001964f2444649f909e583bef upstream. The scenario is this: The kernel gets EREMOTE and starts chasing a DFS referral at mount time. The tcon reference is put, which puts the session reference too, but neither pointer is zeroed out. The mount gets retried (goto try_mount_again) with new mount info. Session setup fails fails and rc ends up being non-zero. The code then falls through to the end and tries to put the previously freed tcon pointer again. Oops at: cifs_put_smb_ses+0x14/0xd0 Fix this by moving the initialization of the rc variable and the tcon, pSesInfo and srvTcp pointers below the try_mount_again label. Also, add a FreeXid() before the goto to prevent xid "leaks". Signed-off-by: Jeff Layton Reported-by: Gustavo Carvalho Homem Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/connect.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 63ea83ff687f..3bbcaa716b3c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2287,12 +2287,12 @@ int cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, char *mount_data_global, const char *devname) { - int rc = 0; + int rc; int xid; struct smb_vol *volume_info; - struct cifsSesInfo *pSesInfo = NULL; - struct cifsTconInfo *tcon = NULL; - struct TCP_Server_Info *srvTcp = NULL; + struct cifsSesInfo *pSesInfo; + struct cifsTconInfo *tcon; + struct TCP_Server_Info *srvTcp; char *full_path; char *mount_data = mount_data_global; #ifdef CONFIG_CIFS_DFS_UPCALL @@ -2301,6 +2301,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, int referral_walks_count = 0; try_mount_again: #endif + rc = 0; + tcon = NULL; + pSesInfo = NULL; + srvTcp = NULL; full_path = NULL; xid = GetXid(); @@ -2597,6 +2601,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cleanup_volume_info(&volume_info); referral_walks_count++; + FreeXid(xid); goto try_mount_again; } #else /* No DFS support, return error on mount */ From e93166f10c741f247c7e172936811bad558b4135 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 21 Dec 2009 15:51:23 +0100 Subject: [PATCH 220/670] x86/amd-iommu: Fix initialization failure panic commit 0f764806438d5576ac58898332e5dcf30bb8a679 upstream. The assumption that acpi_table_parse passes the return value of the hanlder function to the caller proved wrong recently. The return value of the handler function is totally ignored. This makes the initialization code for AMD IOMMU buggy in a way that could cause a kernel panic on initialization. This patch fixes the issue in the AMD IOMMU driver. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/amd_iommu_init.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index e0b3130a1286..c8243f04e62d 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -135,6 +135,11 @@ bool amd_iommu_unmap_flush; /* if true, flush on every unmap */ LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the system */ +/* + * Set to true if ACPI table parsing and hardware intialization went properly + */ +static bool amd_iommu_initialized; + /* * Pointer to the device table which is shared by all AMD IOMMUs * it is indexed by the PCI device id or the HT unit id and contains @@ -913,6 +918,8 @@ static int __init init_iommu_all(struct acpi_table_header *table) } WARN_ON(p != end); + amd_iommu_initialized = true; + return 0; } @@ -1263,6 +1270,9 @@ int __init amd_iommu_init(void) if (acpi_table_parse("IVRS", init_iommu_all) != 0) goto free; + if (!amd_iommu_initialized) + goto free; + if (acpi_table_parse("IVRS", init_memory_definitions) != 0) goto free; From e05a6f0307a79b77319eed3c892a9c09613f1a28 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Dec 2009 13:52:39 -0700 Subject: [PATCH 221/670] ioat3: fix p-disabled q-continuation commit cd78809f6191485a90ea6c92c2b58900ab5c156f upstream. When continuing a pq calculation the driver needs 3 extra sources. The driver can perform a 3 source calculation with a single descriptor, but needs an extended descriptor to process up to 8 sources in one operation. However, in the p-disabled case only one extra source is needed. When continuing a p-disabled operation there are occasions (i.e. 0 < src_cnt % 8 < 3) where the tail operation does not need an extended descriptor. Properly account for this fact otherwise invalid 'dmacount' values will be written to hardware usually causing the channel to halt with 'invalid descriptor' errors. Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dma/ioat/dma_v3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 42f6f10fb0cc..e58ecb29513f 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -650,9 +650,11 @@ __ioat3_prep_pq_lock(struct dma_chan *c, enum sum_check_flags *result, num_descs = ioat2_xferlen_to_descs(ioat, len); /* we need 2x the number of descriptors to cover greater than 3 - * sources + * sources (we need 1 extra source in the q-only continuation + * case and 3 extra sources in the p+q continuation case. */ - if (src_cnt > 3 || flags & DMA_PREP_CONTINUE) { + if (src_cnt + dmaf_p_disabled_continue(flags) > 3 || + (dmaf_continue(flags) && !dmaf_p_disabled_continue(flags))) { with_ext = 1; num_descs *= 2; } else From 8b9f03819c4165799c463b14a30b23f228d13cdb Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 19 Dec 2009 15:36:02 -0700 Subject: [PATCH 222/670] ioat2,3: put channel hardware in known state at init commit a6d52d70677e99bdb89b6921c265d0a58c22e597 upstream. Put the ioat2 and ioat3 state machines in the halted state with all errors cleared. The ioat1 init path is not disturbed for stability, there are no reported ioat1 initiaization issues. Reported-by: Roland Dreier Tested-by: Roland Dreier Acked-by: Simon Horman Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dma/ioat/dma.c | 2 +- drivers/dma/ioat/dma.h | 18 ++++++++++ drivers/dma/ioat/dma_v2.c | 69 +++++++++++++++++++++++++++--------- drivers/dma/ioat/dma_v2.h | 2 ++ drivers/dma/ioat/dma_v3.c | 54 ++++++++++++++++++++-------- drivers/dma/ioat/registers.h | 1 + 6 files changed, 114 insertions(+), 32 deletions(-) diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index c524d36d3c2e..dcc4ab78b32b 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -1032,7 +1032,7 @@ int __devinit ioat_probe(struct ioatdma_device *device) dma->dev = &pdev->dev; if (!dma->chancnt) { - dev_err(dev, "zero channels detected\n"); + dev_err(dev, "channel enumeration error\n"); goto err_setup_interrupts; } diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 45edde996480..bbc3e78ef333 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -60,6 +60,7 @@ * @dca: direct cache access context * @intr_quirk: interrupt setup quirk (for ioat_v1 devices) * @enumerate_channels: hw version specific channel enumeration + * @reset_hw: hw version specific channel (re)initialization * @cleanup_tasklet: select between the v2 and v3 cleanup routines * @timer_fn: select between the v2 and v3 timer watchdog routines * @self_test: hardware version specific self test for each supported op type @@ -78,6 +79,7 @@ struct ioatdma_device { struct dca_provider *dca; void (*intr_quirk)(struct ioatdma_device *device); int (*enumerate_channels)(struct ioatdma_device *device); + int (*reset_hw)(struct ioat_chan_common *chan); void (*cleanup_tasklet)(unsigned long data); void (*timer_fn)(unsigned long data); int (*self_test)(struct ioatdma_device *device); @@ -264,6 +266,22 @@ static inline void ioat_suspend(struct ioat_chan_common *chan) writeb(IOAT_CHANCMD_SUSPEND, chan->reg_base + IOAT_CHANCMD_OFFSET(ver)); } +static inline void ioat_reset(struct ioat_chan_common *chan) +{ + u8 ver = chan->device->version; + + writeb(IOAT_CHANCMD_RESET, chan->reg_base + IOAT_CHANCMD_OFFSET(ver)); +} + +static inline bool ioat_reset_pending(struct ioat_chan_common *chan) +{ + u8 ver = chan->device->version; + u8 cmd; + + cmd = readb(chan->reg_base + IOAT_CHANCMD_OFFSET(ver)); + return (cmd & IOAT_CHANCMD_RESET) == IOAT_CHANCMD_RESET; +} + static inline void ioat_set_chainaddr(struct ioat_dma_chan *ioat, u64 addr) { struct ioat_chan_common *chan = &ioat->base; diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 8f1f7f05deaa..5f7a500e18d0 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -239,20 +239,50 @@ void __ioat2_restart_chan(struct ioat2_dma_chan *ioat) __ioat2_start_null_desc(ioat); } -static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) +int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo) { - struct ioat_chan_common *chan = &ioat->base; - unsigned long phys_complete; + unsigned long end = jiffies + tmo; + int err = 0; u32 status; status = ioat_chansts(chan); if (is_ioat_active(status) || is_ioat_idle(status)) ioat_suspend(chan); while (is_ioat_active(status) || is_ioat_idle(status)) { + if (end && time_after(jiffies, end)) { + err = -ETIMEDOUT; + break; + } status = ioat_chansts(chan); cpu_relax(); } + return err; +} + +int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo) +{ + unsigned long end = jiffies + tmo; + int err = 0; + + ioat_reset(chan); + while (ioat_reset_pending(chan)) { + if (end && time_after(jiffies, end)) { + err = -ETIMEDOUT; + break; + } + cpu_relax(); + } + + return err; +} + +static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) +{ + struct ioat_chan_common *chan = &ioat->base; + unsigned long phys_complete; + + ioat2_quiesce(chan, 0); if (ioat_cleanup_preamble(chan, &phys_complete)) __cleanup(ioat, phys_complete); @@ -318,6 +348,19 @@ void ioat2_timer_event(unsigned long data) spin_unlock_bh(&chan->cleanup_lock); } +static int ioat2_reset_hw(struct ioat_chan_common *chan) +{ + /* throw away whatever the channel was doing and get it initialized */ + u32 chanerr; + + ioat2_quiesce(chan, msecs_to_jiffies(100)); + + chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); + writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); + + return ioat2_reset_sync(chan, msecs_to_jiffies(200)); +} + /** * ioat2_enumerate_channels - find and initialize the device's channels * @device: the device to be enumerated @@ -360,6 +403,10 @@ int ioat2_enumerate_channels(struct ioatdma_device *device) (unsigned long) ioat); ioat->xfercap_log = xfercap_log; spin_lock_init(&ioat->ring_lock); + if (device->reset_hw(&ioat->base)) { + i = 0; + break; + } } dma->chancnt = i; return i; @@ -467,7 +514,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) struct ioat2_dma_chan *ioat = to_ioat2_chan(c); struct ioat_chan_common *chan = &ioat->base; struct ioat_ring_ent **ring; - u32 chanerr; int order; /* have we already been set up? */ @@ -477,12 +523,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) /* Setup register to interrupt and write completion status on error */ writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET); - chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); - if (chanerr) { - dev_err(to_dev(chan), "CHANERR = %x, clearing\n", chanerr); - writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); - } - /* allocate a completion writeback area */ /* doing 2 32bit writes to mmio since 1 64b write doesn't work */ chan->completion = pci_pool_alloc(chan->device->completion_pool, @@ -746,13 +786,7 @@ void ioat2_free_chan_resources(struct dma_chan *c) tasklet_disable(&chan->cleanup_task); del_timer_sync(&chan->timer); device->cleanup_tasklet((unsigned long) ioat); - - /* Delay 100ms after reset to allow internal DMA logic to quiesce - * before removing DMA descriptor resources. - */ - writeb(IOAT_CHANCMD_RESET, - chan->reg_base + IOAT_CHANCMD_OFFSET(chan->device->version)); - mdelay(100); + device->reset_hw(chan); spin_lock_bh(&ioat->ring_lock); descs = ioat2_ring_space(ioat); @@ -839,6 +873,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) int err; device->enumerate_channels = ioat2_enumerate_channels; + device->reset_hw = ioat2_reset_hw; device->cleanup_tasklet = ioat2_cleanup_tasklet; device->timer_fn = ioat2_timer_event; device->self_test = ioat_dma_self_test; diff --git a/drivers/dma/ioat/dma_v2.h b/drivers/dma/ioat/dma_v2.h index 1d849ef74d5f..3afad8da43cc 100644 --- a/drivers/dma/ioat/dma_v2.h +++ b/drivers/dma/ioat/dma_v2.h @@ -185,6 +185,8 @@ bool reshape_ring(struct ioat2_dma_chan *ioat, int order); void __ioat2_issue_pending(struct ioat2_dma_chan *ioat); void ioat2_cleanup_tasklet(unsigned long data); void ioat2_timer_event(unsigned long data); +int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo); +int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo); extern struct kobj_type ioat2_ktype; extern struct kmem_cache *ioat2_cache; #endif /* IOATDMA_V2_H */ diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index e58ecb29513f..9908c9e94b2d 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -1130,6 +1130,45 @@ static int __devinit ioat3_dma_self_test(struct ioatdma_device *device) return 0; } +static int ioat3_reset_hw(struct ioat_chan_common *chan) +{ + /* throw away whatever the channel was doing and get it + * initialized, with ioat3 specific workarounds + */ + struct ioatdma_device *device = chan->device; + struct pci_dev *pdev = device->pdev; + u32 chanerr; + u16 dev_id; + int err; + + ioat2_quiesce(chan, msecs_to_jiffies(100)); + + chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); + writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); + + /* -= IOAT ver.3 workarounds =- */ + /* Write CHANERRMSK_INT with 3E07h to mask out the errors + * that can cause stability issues for IOAT ver.3, and clear any + * pending errors + */ + pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07); + err = pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr); + if (err) { + dev_err(&pdev->dev, "channel error register unreachable\n"); + return err; + } + pci_write_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, chanerr); + + /* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit + * (workaround for spurious config parity error after restart) + */ + pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id); + if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) + pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10); + + return ioat2_reset_sync(chan, msecs_to_jiffies(200)); +} + int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) { struct pci_dev *pdev = device->pdev; @@ -1139,10 +1178,10 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) struct ioat_chan_common *chan; bool is_raid_device = false; int err; - u16 dev_id; u32 cap; device->enumerate_channels = ioat2_enumerate_channels; + device->reset_hw = ioat3_reset_hw; device->self_test = ioat3_dma_self_test; dma = &device->common; dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock; @@ -1218,19 +1257,6 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) dma->device_prep_dma_xor_val = NULL; #endif - /* -= IOAT ver.3 workarounds =- */ - /* Write CHANERRMSK_INT with 3E07h to mask out the errors - * that can cause stability issues for IOAT ver.3 - */ - pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07); - - /* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit - * (workaround for spurious config parity error after restart) - */ - pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id); - if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) - pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10); - err = ioat_probe(device); if (err) return err; diff --git a/drivers/dma/ioat/registers.h b/drivers/dma/ioat/registers.h index f015ec196700..e8ae63baf588 100644 --- a/drivers/dma/ioat/registers.h +++ b/drivers/dma/ioat/registers.h @@ -27,6 +27,7 @@ #define IOAT_PCI_DEVICE_ID_OFFSET 0x02 #define IOAT_PCI_DMAUNCERRSTS_OFFSET 0x148 +#define IOAT_PCI_CHANERR_INT_OFFSET 0x180 #define IOAT_PCI_CHANERRMASK_INT_OFFSET 0x184 /* MMIO Device Registers */ From 3a9f99234194d5f6c987098c288f29f200dabf5e Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Sat, 5 Dec 2009 12:34:11 -0200 Subject: [PATCH 223/670] KVM: MMU: remove prefault from invlpg handler commit fb341f572d26e0786167cd96b90cc4febed830cf upstream. The invlpg prefault optimization breaks Windows 2008 R2 occasionally. The visible effect is that the invlpg handler instantiates a pte which is, microseconds later, written with a different gfn by another vcpu. The OS could have other mechanisms to prevent a present translation from being used, which the hypervisor is unaware of. While the documentation states that the cpu is at liberty to prefetch tlb entries, it looks like this is not heeded, so remove tlb prefetch from invlpg. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/paging_tmpl.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 72558f8ff3f5..85e12cd6fb48 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -455,8 +455,6 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) { struct kvm_shadow_walk_iterator iterator; - pt_element_t gpte; - gpa_t pte_gpa = -1; int level; u64 *sptep; int need_flush = 0; @@ -471,10 +469,6 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) if (level == PT_PAGE_TABLE_LEVEL || ((level == PT_DIRECTORY_LEVEL && is_large_pte(*sptep))) || ((level == PT_PDPE_LEVEL && is_large_pte(*sptep)))) { - struct kvm_mmu_page *sp = page_header(__pa(sptep)); - - pte_gpa = (sp->gfn << PAGE_SHIFT); - pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t); if (is_shadow_present_pte(*sptep)) { rmap_remove(vcpu->kvm, sptep); @@ -493,18 +487,6 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) if (need_flush) kvm_flush_remote_tlbs(vcpu->kvm); spin_unlock(&vcpu->kvm->mmu_lock); - - if (pte_gpa == -1) - return; - if (kvm_read_guest_atomic(vcpu->kvm, pte_gpa, &gpte, - sizeof(pt_element_t))) - return; - if (is_present_gpte(gpte) && (gpte & PT_ACCESSED_MASK)) { - if (mmu_topup_memory_caches(vcpu)) - return; - kvm_mmu_pte_write(vcpu, pte_gpa, (const u8 *)&gpte, - sizeof(pt_element_t), 0); - } } static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr) From 3b96f9a68db8401e73955a6f6c33ec08ffed9e96 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 14 Dec 2009 17:37:35 -0200 Subject: [PATCH 224/670] KVM: LAPIC: make sure IRR bitmap is scanned after vm load commit 6e24a6eff4571002cd48b99a2b92dc829ce39cb9 upstream. The vcpus are initialized with irr_pending set to false, but loading the LAPIC registers with pending IRR fails to reset the irr_pending variable. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/lapic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 23c217692ea9..41659fb080ba 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1156,6 +1156,7 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu) hrtimer_cancel(&apic->lapic_timer.timer); update_divide_count(apic); start_apic_timer(apic); + apic->irr_pending = true; } void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) From 08a93783c334ec4b42532b0dad62dc480a6ec823 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 16 Dec 2009 05:12:58 +0100 Subject: [PATCH 225/670] Libertas: fix buffer overflow in lbs_get_essid() commit 45b241689179a6065384260242637cf21dabfb2d upstream. The libertas driver copies the SSID buffer back to the wireless core and appends a trailing NULL character for termination. This is a) unnecessary because the buffer is allocated with kzalloc and is hence already NULLed when this function is called, and b) for priv->curbssparams.ssid_len == 32, it writes back one byte too much which causes memory corruptions. Fix this by removing the extra write. Signed-off-by: Daniel Mack Cc: Stephen Hemminger Cc: Maithili Hinge Cc: Kiran Divekar Cc: Michael Hirsch Cc: netdev@vger.kernel.org Cc: libertas-dev@lists.infradead.org Cc: linux-wireless@lists.infradead.org Acked-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/libertas/wext.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index be837a0d2517..01c738b8e22c 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -1953,10 +1953,8 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, if (priv->connect_status == LBS_CONNECTED) { memcpy(extra, priv->curbssparams.ssid, priv->curbssparams.ssid_len); - extra[priv->curbssparams.ssid_len] = '\0'; } else { memset(extra, 0, 32); - extra[priv->curbssparams.ssid_len] = '\0'; } /* * If none, we may want to get the one that was set From 38cf2a039fec0233c1ab81b09125e56311574016 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 28 Dec 2009 14:23:11 +0800 Subject: [PATCH 226/670] iwmc3200wifi: fix array out-of-boundary access commit 6c853da3f30c93eae847ecbcd9fdf10ba0da04c2 upstream. Allocate priv->rx_packets[IWM_RX_ID_HASH + 1] because the max array index is IWM_RX_ID_HASH according to IWM_RX_ID_GET_HASH(). Signed-off-by: Zhu Yi Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwmc3200wifi/iwm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 1b02a4e2a1ac..93c898990cce 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -258,7 +258,7 @@ struct iwm_priv { struct sk_buff_head rx_list; struct list_head rx_tickets; - struct list_head rx_packets[IWM_RX_ID_HASH]; + struct list_head rx_packets[IWM_RX_ID_HASH + 1]; struct workqueue_struct *rx_wq; struct work_struct rx_worker; From 330b9373f9b62fcad200f470be7f64c99322d7ef Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 24 Dec 2009 15:38:22 -0500 Subject: [PATCH 227/670] mac80211: fix propagation of failed hardware reconfigurations commit 24feda0084722189468a65e20019cdd8ef99702b upstream. mac80211 does not propagate failed hardware reconfiguration requests. For suspend and resume this is important due to all the possible issues that can come out of the suspend <-> resume cycle. Not propagating the error means cfg80211 will assume the resume for the device went through fine and mac80211 will continue on trying to poke at the hardware, enable timers, queue work, and so on for a device which is completley unfunctional. The least we can do is to propagate device start issues and warn when this occurs upon resume. A side effect of this patch is we also now propagate the start errors upon harware reconfigurations (non-suspend), but this should also be desirable anyway, there is not point in continuing to reconfigure a device if mac80211 was unable to start the device. For further details refer to the thread: http://marc.info/?t=126151038700001&r=1&w=2 Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/util.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index cbc5d2057dbf..51e0bd278e66 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1031,7 +1031,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* restart hardware */ if (local->open_count) { + /* + * Upon resume hardware can sometimes be goofy due to + * various platform / driver / bus issues, so restarting + * the device may at times not work immediately. Propagate + * the error. + */ res = drv_start(local); + if (res) { + WARN(local->suspended, "Harware became unavailable " + "upon resume. This is could be a software issue" + "prior to suspend or a harware issue\n"); + return res; + } ieee80211_led_radio(local, true); } From 0b41c5a957e4fb2be4a8ef960e4e50c8791999f3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 17 Dec 2009 16:16:53 +0100 Subject: [PATCH 228/670] mac80211: fix WMM AP settings application commit 0183826b58a2712ffe608bc3302447be3e6a3ab8 upstream. My commit 77fdaa12cea26c204cc12c312fe40bc0f3dcdfd8 Author: Johannes Berg Date: Tue Jul 7 03:45:17 2009 +0200 mac80211: rework MLME for multiple authentications inadvertedly broke WMM because it removed, along with a bunch of other now useless initialisations, the line initialising sdata->u.mgd.wmm_last_param_set to -1 which would make it adopt any WMM parameter set. If, as is usually the case, the AP uses WMM parameter set sequence number zero, we'd never update it until the AP changes the sequence number. Add the missing initialisation back to get the WMM settings from the AP applied locally. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mlme.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index dc5049d58c51..f13d181c0644 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -904,6 +904,14 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | IEEE80211_STA_BEACON_POLL); + /* + * Always handle WMM once after association regardless + * of the first value the AP uses. Setting -1 here has + * that effect because the AP values is an unsigned + * 4-bit value. + */ + sdata->u.mgd.wmm_last_param_set = -1; + ieee80211_led_assoc(local, 1); sdata->vif.bss_conf.assoc = 1; From 9f7028e71d940aadcdea9f777286b066971ba5da Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 2 Nov 2009 12:33:23 +0530 Subject: [PATCH 229/670] mac80211: Fix IBSS merge commit 450aae3d7b60a970f266349a837dfb30a539198b upstream. Currently, in IBSS mode, a single creator would go into a loop trying to merge/scan. This happens because the IBSS timer is rearmed on finishing a scan and the subsequent timer invocation requests another scan immediately. This patch fixes this issue by checking if we have just completed a scan run trying to merge with other IBSS networks. Signed-off-by: Sujith Signed-off-by: John W. Linville Cc: Luis Rodriguez Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ibss.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f1362f32c17d..fbffce90edbc 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -455,6 +455,10 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); + if (time_before(jiffies, ifibss->last_scan_completed + + IEEE80211_IBSS_MERGE_INTERVAL)) + return; + if (ieee80211_sta_active_ibss(sdata)) return; From 477702056912abc2120a18e8494fb2204ccdd958 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:12:05 +0100 Subject: [PATCH 230/670] cfg80211: fix race between deauth and assoc response commit 3bdb2d48c5f58c781a4099c99044384a23620884 upstream. Joseph Nahmias reported, in http://bugs.debian.org/562016, that he was getting the following warning (with some log around the issue): ath0: direct probe to AP 00:11:95:77:e0:b0 (try 1) ath0: direct probe responded ath0: authenticate with AP 00:11:95:77:e0:b0 (try 1) ath0: authenticated ath0: associate with AP 00:11:95:77:e0:b0 (try 1) ath0: deauthenticating from 00:11:95:77:e0:b0 by local choice (reason=3) ath0: direct probe to AP 00:11:95:77:e0:b0 (try 1) ath0: RX AssocResp from 00:11:95:77:e0:b0 (capab=0x421 status=0 aid=2) ath0: associated ------------[ cut here ]------------ WARNING: at net/wireless/mlme.c:97 cfg80211_send_rx_assoc+0x14d/0x152 [cfg80211]() Hardware name: 7658CTO ... Pid: 761, comm: phy0 Not tainted 2.6.32-trunk-686 #1 Call Trace: [] ? warn_slowpath_common+0x5e/0x8a [] ? warn_slowpath_null+0xa/0xc [] ? cfg80211_send_rx_assoc+0x14d/0x152 ... ath0: link becomes ready ath0: deauthenticating from 00:11:95:77:e0:b0 by local choice (reason=3) ath0: no IPv6 routers present ath0: link is not ready ath0: direct probe to AP 00:11:95:77:e0:b0 (try 1) ath0: direct probe responded ath0: authenticate with AP 00:11:95:77:e0:b0 (try 1) ath0: authenticated ath0: associate with AP 00:11:95:77:e0:b0 (try 1) ath0: RX ReassocResp from 00:11:95:77:e0:b0 (capab=0x421 status=0 aid=2) ath0: associated It is not clear to me how the first "direct probe" here happens, but this seems to be a race condition, if the user requests to deauth after requesting assoc, but before the assoc response is received. In that case, it may happen that mac80211 tries to report the assoc success to cfg80211, but gets blocked on the wdev lock that is held because the user is requesting the deauth. The result is that we run into a warning. This is mostly harmless, but maybe cause an unexpected event to be sent to userspace; we'd send an assoc success event although userspace was no longer expecting that. To fix this, remove the warning and check whether the race happened and in that case abort processing. Reported-by: Joseph Nahmias Cc: 562016-quiet@bugs.debian.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/mlme.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 0a6b7a0eca6b..0d862482def8 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -94,7 +94,18 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) } } - WARN_ON(!bss); + /* + * We might be coming here because the driver reported + * a successful association at the same time as the + * user requested a deauth. In that case, we will have + * removed the BSS from the auth_bsses list due to the + * deauth request when the assoc response makes it. If + * the two code paths acquire the lock the other way + * around, that's just the standard situation of a + * deauth being requested while connected. + */ + if (!bss) + goto out; } else if (wdev->conn) { cfg80211_sme_failed_assoc(wdev); need_connect_result = false; From d5086b90c5986d33308b1ee99546a86ff1571d07 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 21 Dec 2009 22:26:48 -0500 Subject: [PATCH 231/670] ath5k: fix SWI calibration interrupt storm commit 242ab7ad689accafd5e87ffd22b85cf1bf7fbbef upstream. The calibration period is now invoked by triggering a software interrupt from within the ISR by ath5k_hw_calibration_poll() instead of via a timer. However, the calibration interval isn't initialized before interrupts are enabled, so we can have a situation where an interrupt occurs before the interval is assigned, so the interval is actually negative. As a result, the ISR will arm a software interrupt to schedule the tasklet, and then rearm it when the SWI is processed, and so on, leading to a softlockup at modprobe time. Move the initialization order around so the calibration interval is set before interrupts are active. Another possible fix is to schedule the tasklet directly from the poll routine, but I think there are additional plans for the SWI. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath5k/base.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 95a8e232b58f..8a82c757ea63 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2349,6 +2349,9 @@ ath5k_init(struct ath5k_softc *sc) */ ath5k_stop_locked(sc); + /* Set PHY calibration interval */ + ah->ah_cal_intval = ath5k_calinterval; + /* * The basic interface to setting the hardware in a good * state is ``reset''. On return the hardware is known to @@ -2376,10 +2379,6 @@ ath5k_init(struct ath5k_softc *sc) /* Set ack to be sent at low bit-rates */ ath5k_hw_set_ack_bitrate_high(ah, false); - - /* Set PHY calibration inteval */ - ah->ah_cal_intval = ath5k_calinterval; - ret = 0; done: mmiowb(); From 0ebbdd734f2509bae17f4340fc4fd07c530dbc59 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 23 Dec 2009 20:03:28 -0500 Subject: [PATCH 232/670] ath9k: wake hardware for interface IBSS/AP/Mesh removal commit 5f70a88f631c3480107853cae12925185eb4c598 upstream. When we remove a IBSS/AP/Mesh interface we stop DMA but to do this we should ensure hardware is on. Awaken the device prior to these calls. This should ensure DMA is stopped upon suspend and plain device removal. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 59359e348ee3..909e8399abff 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2277,8 +2277,10 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { + ath9k_ps_wakeup(sc); ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); ath_beacon_return(sc, avp); + ath9k_ps_restore(sc); } sc->sc_flags &= ~SC_OP_BEACONS; From bef82b626e39357fd28b8303e9f88ea5c5d1b51f Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 14 Dec 2009 14:57:08 +0530 Subject: [PATCH 233/670] ath9k: Fix TX queue draining commit e8009e9850d59000d518296af372888911a129bd upstream. When TX DMA termination has failed, the HW has to be reset completely. Doing a fast channel change in this case is insufficient. Also, change the debug level of a couple of messages to FATAL. Signed-off-by: Sujith Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/mac.c | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index d4d9d828aff4..110c16dd465c 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -155,7 +155,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) wait = wait_time; while (ath9k_hw_numtxpending(ah, q)) { if ((--wait) == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Failed to stop TX DMA in 100 " "msec after killing last frame\n"); break; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 47539094524e..2e0b86be382e 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1076,10 +1076,10 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) if (npend) { int r; - DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n"); + DPRINTF(sc, ATH_DBG_FATAL, "Unable to stop TxDMA. Reset HAL!\n"); spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true); + r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); if (r) DPRINTF(sc, ATH_DBG_FATAL, "Unable to reset hardware; reset status %d\n", From 463a7f9b2752b659f93272c0067dcbc10bd73674 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 24 Dec 2009 14:04:32 +0100 Subject: [PATCH 234/670] ath9k: fix missed error codes in the tx status check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 5b479a076de091590423a9e6dfc2584126b28761 upstream. My previous change added in: commit 815833e7ecf0b9a017315cae6aef4d7cd9517681 ath9k: fix tx status reporting was not checking all possible tx error conditions. This could possibly lead to throughput issues due to slow rate control adaption or missed retransmissions of failed A-MPDU frames. This patch adds a mask for all possible error conditions and uses it in the xmit ok check. Reported-by: Björn Smedman Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/mac.h | 3 +++ drivers/net/wireless/ath/ath9k/xmit.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index ff65f85bd855..9720c4dc9599 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -77,6 +77,9 @@ #define ATH9K_TXERR_XTXOP 0x08 #define ATH9K_TXERR_TIMER_EXPIRED 0x10 #define ATH9K_TX_ACKED 0x20 +#define ATH9K_TXERR_MASK \ + (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \ + ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED) #define ATH9K_TX_BA 0x01 #define ATH9K_TX_PWRMGMT 0x02 diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2e0b86be382e..2c6b06343333 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2020,7 +2020,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) if (bf_isaggr(bf)) txq->axq_aggr_depth--; - txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT); + txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK); txq->axq_tx_inprogress = false; spin_unlock_bh(&txq->axq_lock); From c965e1efdb88a1c42afb119b276d649cddb70387 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 23 Dec 2009 20:03:29 -0500 Subject: [PATCH 235/670] ath9k: wake hardware during AMPDU TX actions commit 8b685ba9de803f210936400612a32a2003f47cd3 upstream. AMDPDU actions poke hardware for TX operation, as such we want to turn hardware on for these actions. AMDPU RX operations do not require hardware on as nothing is done in hardware for those actions. Without this we cannot guarantee hardware has been programmed correctly for each AMPDU TX action. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 909e8399abff..91f97103bfea 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2726,15 +2726,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: + ath9k_ps_wakeup(sc); ath_tx_aggr_start(sc, sta, tid, ssn); ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); + ath9k_ps_restore(sc); break; case IEEE80211_AMPDU_TX_STOP: + ath9k_ps_wakeup(sc); ath_tx_aggr_stop(sc, sta, tid); ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); + ath9k_ps_restore(sc); break; case IEEE80211_AMPDU_TX_OPERATIONAL: + ath9k_ps_wakeup(sc); ath_tx_aggr_resume(sc, sta, tid); + ath9k_ps_restore(sc); break; default: DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n"); From 12ba7097e0996b27d768504ae4b337ae3e892221 Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 23 Dec 2009 20:03:27 -0500 Subject: [PATCH 236/670] ath9k: fix suspend by waking device prior to stop commit 3867cf6a8c699846e928e8f5a9f31013708df192 upstream. Ensure the device is awake prior to trying to tell hardware to stop it. Impact of not doing this is we can likely leave the device in an undefined state likely causing issues with suspend and resume. This patch ensures harware is where it should be prior to suspend. Signed-off-by: Sujith Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 91f97103bfea..80df8f36c4ef 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2147,6 +2147,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) return; /* another wiphy still in use */ } + /* Ensure HW is awake when we try to shut it down. */ + ath9k_ps_wakeup(sc); + if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) { ath9k_hw_btcoex_disable(sc->sc_ah); if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) @@ -2167,6 +2170,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) /* disable HAL and put h/w to sleep */ ath9k_hw_disable(sc->sc_ah); ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1); + ath9k_ps_restore(sc); + + /* Finally, put the chip in FULL SLEEP mode */ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); sc->sc_flags |= SC_OP_INVALID; From a6d8cc616a9058b2e08776f971febf5c84534551 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 13 Nov 2009 14:32:39 +0530 Subject: [PATCH 237/670] ath9k_hw: Fix possible OOB array indexing in gen_timer_index[] on 64-bit commit c90017dd43f0cdb42134b9229761e8be02bcd524 upstream. debruijn32 (0x077CB531) is used to index gen_timer_index[] which is an array of 32 u32. Having debruijn32 as unsigned long on a 64-bit platform will result in indexing more than 32 in gen_timer_index[] and there by causing a crash. Make it unsigned to fix this issue. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/hw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 57f14630e2a1..ff4383bb3ac3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -408,7 +408,7 @@ struct ath9k_hw_version { * Using de Bruijin sequence to to look up 1's index in a 32 bit number * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001 */ -#define debruijn32 0x077CB531UL +#define debruijn32 0x077CB531U struct ath_gen_timer_configuration { u32 next_addr; From 87d512cacd0aff44719736ef6d583cafd5c0e1be Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 13 Nov 2009 14:32:40 +0530 Subject: [PATCH 238/670] ath9k_hw: Fix AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB and its shift value in 0x4054 commit c37919bfe0a5c1bee9a31701a31e05a2f8840936 upstream. The bit value of AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB is wrong, it should be 0x400 and the number of bits to be right shifted is 10. Having this wrong value in 0x4054 sometimes affects bt quality on btcoex environment. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d83b77f821e9..c0d7e65bf6d4 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -969,10 +969,10 @@ enum { #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00000400 +#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 10 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00001000 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 1 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 From 66c9e44e5740fe9024e3ed02fd66ad6e0e57408f Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 14 Dec 2009 14:12:10 -0800 Subject: [PATCH 239/670] iwl3945: disable power save commit bc45a67079c916a9bd0a95b0b879cc0f259bac6e upstream. we see from http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2125 that power saving does not work well on 3945. Since then power saving has also been connected with association problems where an AP deathenticates a 3945 after it is unable to transmit data to it - this happens when 3945 enters power savings mode. Disable power save support until issues are resolved. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f059b49dc691..9d60f6cfa1d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2895,6 +2895,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .mod_params = &iwl3945_mod_params, .use_isr_legacy = true, .ht_greenfield_support = false, + .broken_powersave = true, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2909,6 +2910,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .mod_params = &iwl3945_mod_params, .use_isr_legacy = true, .ht_greenfield_support = false, + .broken_powersave = true, }; struct pci_device_id iwl3945_hw_card_ids[] = { diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d00a80334095..9bf94f0e88a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3854,9 +3854,11 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | - IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + IEEE80211_HW_SPECTRUM_MGMT; + + if (!priv->cfg->broken_powersave) + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | From 0c0cdaff83704490511b462c7ba76d3ff2d0eedb Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 14 Dec 2009 14:12:12 -0800 Subject: [PATCH 240/670] iwl3945: fix panic in iwl3945 driver commit dc57a303faab8562b92e85df0d79c4a05d7e2a61 upstream. 3945 updated write_ptr without regard to read_ptr on the Tx path. This messes up our TFD on high load and result in the following: <1>[ 7290.414172] IP: [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.414205] PGD 0 <1>[ 7290.414214] Thread overran stack, or stack corrupted <0>[ 7290.414229] Oops: 0002 [#1] PREEMPT SMP <0>[ 7290.414246] last sysfs file: /sys/devices/platform/coretemp.1/temp1_input <4>[ 7290.414265] CPU 0 <4>[ 7290.414274] Modules linked in: af_packet nfsd usb_storage usb_libusual cpufreq_powersave exportfs cpufreq_conservative iwl3945 nfs cpufreq_userspace snd_hda_codec_realtek acpi_cpufreq uvcvideo lockd iwlcore snd_hda_intel joydev coretemp nfs_acl videodev snd_hda_codec mac80211 v4l1_compat snd_hwdep sbp2 v4l2_compat_ioctl32 uhci_hcd psmouse auth_rpcgss ohci1394 cfg80211 ehci_hcd video ieee1394 snd_pcm serio_raw battery ac nvidia(P) usbcore output sunrpc evdev lirc_ene0100 snd_page_alloc rfkill tg3 libphy fuse lzo lzo_decompress lzo_compress <6>[ 7290.414486] Pid: 0, comm: swapper Tainted: P 2.6.32-rc8-wl #213 Aspire 5720 <6>[ 7290.414507] RIP: 0010:[] [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <6>[ 7290.414541] RSP: 0018:ffff880002203d60 EFLAGS: 00010246 <6>[ 7290.414557] RAX: 000000000000004f RBX: ffff880064c11600 RCX: 0000000000000013 <6>[ 7290.414576] RDX: ffffffffa0ddcf20 RSI: ffff8800512b7008 RDI: 0000000000000038 <6>[ 7290.414596] RBP: ffff880002203dd0 R08: 0000000000000000 R09: 0000000000000100 <6>[ 7290.414616] R10: 0000000000000001 R11: 0000000000000000 R12: 00000000000000a0 <6>[ 7290.414635] R13: 0000000000000002 R14: 0000000000000013 R15: 0000000000020201 <6>[ 7290.414655] FS: 0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000 <6>[ 7290.414677] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b <6>[ 7290.414693] CR2: 0000000000000041 CR3: 0000000001001000 CR4: 00000000000006f0 <6>[ 7290.414712] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 <6>[ 7290.414732] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 <4>[ 7290.414752] Process swapper (pid: 0, threadinfo ffffffff81524000, task ffffffff81528b60) <0>[ 7290.414772] Stack: <4>[ 7290.414780] ffff880002203da0 0000000000000046 0000000000000000 0000000000000046 <4>[ 7290.414804] <0> 0000000000000282 0000000000000282 0000000000000282 ffff880064c12010 <4>[ 7290.414830] <0> ffff880002203db0 ffff880064c11600 ffff880064c12e50 ffff8800512b7000 <0>[ 7290.414858] Call Trace: <0>[ 7290.414867] <4>[ 7290.414884] [] iwl3945_irq_tasklet+0x657/0x1740 [iwl3945] <4>[ 7290.414910] [] ? _spin_unlock+0x30/0x60 <4>[ 7290.414931] [] tasklet_action+0x101/0x110 <4>[ 7290.414950] [] __do_softirq+0xc0/0x160 <4>[ 7290.414968] [] call_softirq+0x1c/0x30 <4>[ 7290.414986] [] do_softirq+0x75/0xb0 <4>[ 7290.415003] [] irq_exit+0x95/0xa0 <4>[ 7290.415020] [] do_IRQ+0x77/0xf0 <4>[ 7290.415038] [] ret_from_intr+0x0/0xf <0>[ 7290.415052] <4>[ 7290.415067] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415087] [] ? acpi_idle_enter_bm+0x27a/0x2a5 <4>[ 7290.415107] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415130] [] ? cpuidle_idle_call+0x93/0xf0 <4>[ 7290.415149] [] ? cpu_idle+0xa7/0x110 <4>[ 7290.415168] [] ? rest_init+0x75/0x80 <4>[ 7290.415187] [] ? start_kernel+0x3a7/0x3b3 <4>[ 7290.415206] [] ? x86_64_start_reservations+0x125/0x129 <4>[ 7290.415227] [] ? x86_64_start_kernel+0xe4/0xeb <0>[ 7290.415243] Code: 00 41 39 ce 0f 8d e8 01 00 00 48 8b 47 40 48 63 d2 48 69 d2 98 00 00 00 4c 8b 04 02 48 c7 c2 20 cf dd a0 49 8d 78 38 49 8d 40 4f 47 09 00 c6 47 0c 00 c6 47 0f 00 c6 47 12 00 c6 47 15 00 49 <1>[ 7290.415382] RIP [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.415410] RSP <0>[ 7290.415421] CR2: 0000000000000041 <4>[ 7290.415436] ---[ end trace ec46807277caa515 ]--- <0>[ 7290.415450] Kernel panic - not syncing: Fatal exception in interrupt <4>[ 7290.415468] Pid: 0, comm: swapper Tainted: P D 2.6.32-rc8-wl #213 <4>[ 7290.415486] Call Trace: <4>[ 7290.415495] [] panic+0x7d/0x13a <4>[ 7290.415519] [] oops_end+0xda/0xe0 <4>[ 7290.415538] [] no_context+0xea/0x250 <4>[ 7290.415557] [] ? select_task_rq_fair+0x511/0x780 <4>[ 7290.415578] [] __bad_area_nosemaphore+0x125/0x1e0 <4>[ 7290.415597] [] ? __enqueue_entity+0x7c/0x80 <4>[ 7290.415616] [] ? enqueue_task_fair+0x111/0x150 <4>[ 7290.415636] [] bad_area_nosemaphore+0xe/0x10 <4>[ 7290.415656] [] do_page_fault+0x26a/0x320 <4>[ 7290.415674] [] page_fault+0x1f/0x30 <4>[ 7290.415697] [] ? iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.415723] [] iwl3945_irq_tasklet+0x657/0x1740 [iwl3945] <4>[ 7290.415746] [] ? _spin_unlock+0x30/0x60 <4>[ 7290.415764] [] tasklet_action+0x101/0x110 <4>[ 7290.415783] [] __do_softirq+0xc0/0x160 <4>[ 7290.415801] [] call_softirq+0x1c/0x30 <4>[ 7290.415818] [] do_softirq+0x75/0xb0 <4>[ 7290.415835] [] irq_exit+0x95/0xa0 <4>[ 7290.415852] [] do_IRQ+0x77/0xf0 <4>[ 7290.415869] [] ret_from_intr+0x0/0xf <4>[ 7290.415883] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415911] [] ? acpi_idle_enter_bm+0x27a/0x2a5 <4>[ 7290.415931] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415952] [] ? cpuidle_idle_call+0x93/0xf0 <4>[ 7290.415971] [] ? cpu_idle+0xa7/0x110 <4>[ 7290.415989] [] ? rest_init+0x75/0x80 <4>[ 7290.416007] [] ? start_kernel+0x3a7/0x3b3 <4>[ 7290.416026] [] ? x86_64_start_reservations+0x125/0x129 <4>[ 7290.416047] [] ? x86_64_start_kernel+0xe4/0xeb Reported-by: Maxim Levitsky Tested-by: Maxim Levitsky Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 9bf94f0e88a8..5f26c93d3516 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -562,6 +562,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq = &priv->txq[txq_id]; q = &txq->q; + if ((iwl_queue_space(q) < q->high_mark)) + goto drop; + spin_lock_irqsave(&priv->lock, flags); idx = get_cmd_index(q, q->write_ptr, 0); From df5d119f46660631b9d50b91b1b888cdb512bdb2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 14 Dec 2009 14:12:08 -0800 Subject: [PATCH 241/670] iwlwifi: fix EEPROM/OTP reading endian annotations and a bug commit af6b8ee38833b39f70946f767740565ceb126961 upstream. The construct "le16_to_cpu((__force __le16)(r >> 16))" has always bothered me when looking through the iwlwifi code, it shouldn't be necessary to __force anything, and before this code, "r" was obtained with an ioread32, which swaps each of the two u16 values in it properly when swapping the entire u32 value. I've had arguments about this code with people before, but always conceded they were right because removing it only made things not work at all on big endian platforms. However, analysing a failure of the OTP reading code, I now finally figured out what is going on, and why my intuition about that code being wrong was right all along. It turns out that the 'priv->eeprom' u8 array really wants to have the data in it in little endian. So the force code above and all really converts *to* little endian, not from it. Cf., for instance, the function iwl_eeprom_query16() -- it reads two u8 values and combines them into a u16, in a little-endian way. And considering it more, it makes sense to have the eeprom array as on the device, after all not all values really are 16-bit values, the MAC address for instance is not. Now, what this really means is that all the annotations are completely wrong. The eeprom reading code should fill the priv->eeprom array as a __le16 array, with __le16 values. This also means that iwl_read_otp_word() should really have a __le16 pointer as the data argument, since it should be filling that in a format suitable for priv->eeprom. Propagating these changes throughout, iwl_find_otp_image() is found to be, now obviously visible, defective -- it uses the data returned by iwl_read_otp_word() directly as if it was CPU endianness. Fixing that, which is this hunk of the patch: - next_link_addr = link_value * sizeof(u16); + next_link_addr = le16_to_cpu(link_value) * sizeof(u16); is the only real change of this patch. Everything else is just fixing the sparse annotations. Also, the bug only shows up on big endian platforms with a 1000 series card. 5000 and previous series do not use OTP, and 6000 series has shadow RAM support which means we don't ever use the defective code on any cards but 1000. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 028d50599550..c2d9b7a5ef64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1149,7 +1149,7 @@ struct iwl_priv { u32 last_beacon_time; u64 last_tsf; - /* eeprom */ + /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; struct iwl_eeprom_calib_info *calib_info; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index e14c9952a935..622b636aefae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -337,7 +337,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv) return ret; } -static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) +static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_data) { int ret = 0; u32 r; @@ -370,7 +370,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); } - *eeprom_data = le16_to_cpu((__force __le16)(r >> 16)); + *eeprom_data = cpu_to_le16(r >> 16); return 0; } @@ -379,7 +379,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) */ static bool iwl_is_otp_empty(struct iwl_priv *priv) { - u16 next_link_addr = 0, link_value; + u16 next_link_addr = 0; + __le16 link_value; bool is_empty = false; /* locate the beginning of OTP link list */ @@ -409,7 +410,8 @@ static bool iwl_is_otp_empty(struct iwl_priv *priv) static int iwl_find_otp_image(struct iwl_priv *priv, u16 *validblockaddr) { - u16 next_link_addr = 0, link_value = 0, valid_addr; + u16 next_link_addr = 0, valid_addr; + __le16 link_value = 0; int usedblocks = 0; /* set addressing mode to absolute to traverse the link list */ @@ -429,7 +431,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, * check for more block on the link list */ valid_addr = next_link_addr; - next_link_addr = link_value * sizeof(u16); + next_link_addr = le16_to_cpu(link_value) * sizeof(u16); IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", usedblocks, next_link_addr); if (iwl_read_otp_word(priv, next_link_addr, &link_value)) @@ -463,7 +465,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, */ int iwl_eeprom_init(struct iwl_priv *priv) { - u16 *e; + __le16 *e; u32 gp = iwl_read32(priv, CSR_EEPROM_GP); int sz; int ret; @@ -482,7 +484,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = -ENOMEM; goto alloc_err; } - e = (u16 *)priv->eeprom; + e = (__le16 *)priv->eeprom; ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); if (ret < 0) { @@ -521,7 +523,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) } for (addr = validblockaddr; addr < validblockaddr + sz; addr += sizeof(u16)) { - u16 eeprom_data; + __le16 eeprom_data; ret = iwl_read_otp_word(priv, addr, &eeprom_data); if (ret) @@ -545,7 +547,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) goto done; } r = _iwl_read_direct32(priv, CSR_EEPROM_REG); - e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); + e[addr / 2] = cpu_to_le16(r >> 16); } } ret = 0; From c4ae8aea88809050e8ae76a8c3e252ba3fe6e2cc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 14 Dec 2009 14:12:09 -0800 Subject: [PATCH 242/670] iwlwifi: fix more eeprom endian bugs commit b7bb1756cb6a610cdbac8cfdad9e79bb5670b63b upstream. I've also for a long time had a problem with the temperature calculation code, which I had fixed by byte-swapping the values, and now it turns out that was the correct fix after all. Also, any use of iwl_eeprom_query_addr() that is for more than a u8 must be cast to little endian, and some structs as well. Fix all this. Again, no real impact on platforms that already are little endian. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000-hw.h | 14 +++++++++----- drivers/net/wireless/iwlwifi/iwl-5000.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 4 ++-- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6f703a041847..f4e2e84e1296 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1337,7 +1337,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); /* calculate tx gain adjustment based on power supply voltage */ - voltage = priv->calib_info->voltage; + voltage = le16_to_cpu(priv->calib_info->voltage); init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage); voltage_compensation = iwl4965_get_voltage_compensation(voltage, init_voltage); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 4ef6804a455a..bc056e9ab85f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -92,11 +92,15 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) { - u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv, - EEPROM_5000_TEMPERATURE); - /* offset = temperature - voltage / coef */ - s32 offset = (s32)(temp_calib[0] - temp_calib[1] / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); - return offset; + u16 temperature, voltage; + __le16 *temp_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE); + + temperature = le16_to_cpu(temp_calib[0]); + voltage = le16_to_cpu(temp_calib[1]); + + /* offset = temp - volt / coeff */ + return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); } /* Fixed (non-configurable) rx data from phy */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 6e6f516ba404..94a1225f9872 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -460,14 +460,15 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) { struct iwl_calib_xtal_freq_cmd cmd; - u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); + __le16 *xtal_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; - cmd.cap_pin1 = (u8)xtal_calib[0]; - cmd.cap_pin2 = (u8)xtal_calib[1]; + cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); + cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], (u8 *)&cmd, sizeof(cmd)); } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 80b9e45d9b9c..fc93f12853ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -133,7 +133,7 @@ struct iwl_eeprom_channel { * */ struct iwl_eeprom_enhanced_txpwr { - u16 reserved; + __le16 common; s8 chain_a_max; s8 chain_b_max; s8 chain_c_max; @@ -347,7 +347,7 @@ struct iwl_eeprom_calib_subband_info { struct iwl_eeprom_calib_info { u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ u8 saturation_power52; /* half-dBm */ - s16 voltage; /* signed */ + __le16 voltage; /* signed */ struct iwl_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS]; } __attribute__ ((packed)); From 14b4d749ab35158853bca4868b42c0a8cb947206 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 14 Dec 2009 14:12:13 -0800 Subject: [PATCH 243/670] iwlwifi: fix 40MHz operation setting on cards that do not allow it commit 6c3069b1e7e983e176a5f826e2edffefdd404a08 upstream. Some devices have 40MHz operation disabled entirely. Ensure that driver do not enable 40MHz operation if a channel does not allow this. This fixes http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2135 Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 622b636aefae..18dc3a4b7948 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -711,7 +711,8 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, ch_info->ht40_min_power = 0; ch_info->ht40_scan_power = eeprom_ch->max_power_avg; ch_info->ht40_flags = eeprom_ch->flags; - ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; + if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) + ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; return 0; } From 1cfe005024b5c820f9b37c9045ec87ee75a8cfb6 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 24 Dec 2009 15:26:09 -0500 Subject: [PATCH 244/670] mac80211: fix race with suspend and dynamic_ps_disable_work commit b98c06b6debfe84c90200143bb1102f312f50a33 upstream. When mac80211 suspends it calls a driver's suspend callback as a last step and after that the driver assumes no calls will be made to it until we resume and its start callback is kicked. If such calls are made, however, suspend can end up throwing hardware in an unexpected state and making the device unusable upon resume. Fix this by preventing mac80211 to schedule dynamic_ps_disable_work by checking for when mac80211 starts to suspend and starts quiescing. Frames should be allowed to go through though as that is part of the quiescing steps and we do not flush the mac80211 workqueue since it was already done towards the beginning of suspend cycle. The other mac80211 issue will be hanled in the next patch. For further details see refer to the thread: http://marc.info/?t=126144866100001&r=1&w=2 Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/tx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index eaa4118de988..d39819745abf 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1401,6 +1401,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && local->hw.conf.dynamic_ps_timeout > 0 && + !local->quiescing && !(local->scanning) && local->ps_sdata) { if (local->hw.conf.flags & IEEE80211_CONF_PS) { ieee80211_stop_queues_by_reason(&local->hw, From 0399123f3dcce1a515d021107ec0fb4413ca3efa Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 15 Dec 2009 19:27:45 +0000 Subject: [PATCH 245/670] NOMMU: Optimise away the {dac_,}mmap_min_addr tests commit 6e1415467614e854fee660ff6648bd10fa976e95 upstream. In NOMMU mode clamp dac_mmap_min_addr to zero to cause the tests on it to be skipped by the compiler. We do this as the minimum mmap address doesn't make any sense in NOMMU mode. mmap_min_addr and round_hint_to_min() can be discarded entirely in NOMMU mode. Signed-off-by: David Howells Acked-by: Eric Paris Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- include/linux/security.h | 7 +++++++ kernel/sysctl.c | 2 ++ mm/Kconfig | 1 + security/Makefile | 3 ++- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/linux/security.h b/include/linux/security.h index 239e40d0450b..d40d23fa576a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -95,8 +95,13 @@ struct seq_file; extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); extern int cap_netlink_recv(struct sk_buff *skb, int cap); +#ifdef CONFIG_MMU extern unsigned long mmap_min_addr; extern unsigned long dac_mmap_min_addr; +#else +#define dac_mmap_min_addr 0UL +#endif + /* * Values used in the task_security_ops calls */ @@ -121,6 +126,7 @@ struct request_sock; #define LSM_UNSAFE_PTRACE 2 #define LSM_UNSAFE_PTRACE_CAP 4 +#ifdef CONFIG_MMU /* * If a hint addr is less than mmap_min_addr change hint to be as * low as possible but still greater than mmap_min_addr @@ -135,6 +141,7 @@ static inline unsigned long round_hint_to_min(unsigned long hint) } extern int mmap_min_addr_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); +#endif #ifdef CONFIG_SECURITY diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0d949c517412..db23ab7e56c0 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1200,6 +1200,7 @@ static struct ctl_table vm_table[] = { .extra2 = (void *)&hugetlb_infinity, }, #endif +#ifdef CONFIG_MMU { .ctl_name = VM_LOWMEM_RESERVE_RATIO, .procname = "lowmem_reserve_ratio", @@ -1353,6 +1354,7 @@ static struct ctl_table vm_table[] = { .mode = 0644, .proc_handler = &mmap_min_addr_handler, }, +#endif #ifdef CONFIG_NUMA { .ctl_name = CTL_UNNUMBERED, diff --git a/mm/Kconfig b/mm/Kconfig index 44cf6f0a3a6d..2c19c0bac10e 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -227,6 +227,7 @@ config KSM config DEFAULT_MMAP_MIN_ADDR int "Low address space to protect from user allocation" + depends on MMU default 4096 help This is the portion of low virtual memory which should be protected diff --git a/security/Makefile b/security/Makefile index 95ecc06392d7..510bbc80b9b4 100644 --- a/security/Makefile +++ b/security/Makefile @@ -8,7 +8,8 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo # always enable default capabilities -obj-y += commoncap.o min_addr.o +obj-y += commoncap.o +obj-$(CONFIG_MMU) += min_addr.o # Object file lists obj-$(CONFIG_SECURITY) += security.o capability.o From 3ec268a6828ccc37a15e62a7836433b081342345 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Mon, 14 Dec 2009 17:59:52 -0800 Subject: [PATCH 246/670] 'sysctl_max_map_count' should be non-negative commit 70da2340fbc68e91e701762f785479ab495a0869 upstream. Jan Engelhardt reported we have this problem: setting max_map_count to a value large enough results in programs dying at first try. This is on 2.6.31.6: 15:59 borg:/proc/sys/vm # echo $[1<<31-1] >max_map_count 15:59 borg:/proc/sys/vm # cat max_map_count 1073741824 15:59 borg:/proc/sys/vm # echo $[1<<31] >max_map_count 15:59 borg:/proc/sys/vm # cat max_map_count Killed This is because we have a chance to make 'max_map_count' negative. but it's meaningless. Make it only accept non-negative values. Reported-by: Jan Engelhardt Signed-off-by: WANG Cong Cc: Ingo Molnar Cc: Peter Zijlstra Cc: James Morris Cc: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sysctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index db23ab7e56c0..3928c04965f0 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1607,7 +1607,8 @@ static struct ctl_table debug_table[] = { .data = &show_unhandled_signals, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec + .proc_handler = proc_dointvec, + .extra1 = &zero, }, #endif { .ctl_name = 0 } From 4b6d2635956c1ce642bc5dbfc8f460b516ed7e12 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Thu, 17 Dec 2009 15:27:05 -0800 Subject: [PATCH 247/670] kernel/sysctl.c: fix the incomplete part of sysctl_max_map_count-should-be-non-negative.patch commit 3e26120cc7c819c97bc07281ca1fb9017cfe9a39 upstream. It is a mistake that we used 'proc_dointvec', it should be 'proc_dointvec_minmax', as in the original patch. Signed-off-by: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3928c04965f0..dd84be9ac6e4 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1607,7 +1607,7 @@ static struct ctl_table debug_table[] = { .data = &show_unhandled_signals, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, .extra1 = &zero, }, #endif From 6e2aa7de04f48bd39955fe0939dc2e02b8941839 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 10 Dec 2009 16:44:51 -0300 Subject: [PATCH 248/670] V4L/DVB (13596): ov511.c typo: lock => unlock commit 50e9d31183ed61c787b870cb3ee8f6c3db8c8a1e upstream. This was found with a static checker and has not been tested, but it seems pretty clear that the mutex_lock() was supposed to be mutex_unlock() Signed-off-by: Dan Carpenter Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab Cc: Brandon Philips Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/ov511.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 0bc2cf573c76..2bed9e22968b 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -5878,7 +5878,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) goto error; } - mutex_lock(&ov->lock); + mutex_unlock(&ov->lock); return 0; From b52d85562809f1e8b03d03f6ebc5aa28405d0576 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 17 Dec 2009 07:04:56 -0800 Subject: [PATCH 249/670] x86/ptrace: make genregs[32]_get/set more robust commit 04a1e62c2cec820501f93526ad1e46073b802dc4 upstream. The loop condition is fragile: we compare an unsigned value to zero, and then decrement it by something larger than one in the loop. All the callers should be passing in appropriately aligned buffer lengths, but it's better to just not rely on it, and have some appropriate defensive loop limits. Acked-by: Roland McGrath Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/ptrace.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 7b058a2dc66a..c06acddd6830 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -408,14 +408,14 @@ static int genregs_get(struct task_struct *target, { if (kbuf) { unsigned long *k = kbuf; - while (count > 0) { + while (count >= sizeof(*k)) { *k++ = getreg(target, pos); count -= sizeof(*k); pos += sizeof(*k); } } else { unsigned long __user *u = ubuf; - while (count > 0) { + while (count >= sizeof(*u)) { if (__put_user(getreg(target, pos), u++)) return -EFAULT; count -= sizeof(*u); @@ -434,14 +434,14 @@ static int genregs_set(struct task_struct *target, int ret = 0; if (kbuf) { const unsigned long *k = kbuf; - while (count > 0 && !ret) { + while (count >= sizeof(*k) && !ret) { ret = putreg(target, pos, *k++); count -= sizeof(*k); pos += sizeof(*k); } } else { const unsigned long __user *u = ubuf; - while (count > 0 && !ret) { + while (count >= sizeof(*u) && !ret) { unsigned long word; ret = __get_user(word, u++); if (ret) @@ -1219,14 +1219,14 @@ static int genregs32_get(struct task_struct *target, { if (kbuf) { compat_ulong_t *k = kbuf; - while (count > 0) { + while (count >= sizeof(*k)) { getreg32(target, pos, k++); count -= sizeof(*k); pos += sizeof(*k); } } else { compat_ulong_t __user *u = ubuf; - while (count > 0) { + while (count >= sizeof(*u)) { compat_ulong_t word; getreg32(target, pos, &word); if (__put_user(word, u++)) @@ -1247,14 +1247,14 @@ static int genregs32_set(struct task_struct *target, int ret = 0; if (kbuf) { const compat_ulong_t *k = kbuf; - while (count > 0 && !ret) { + while (count >= sizeof(*k) && !ret) { ret = putreg32(target, pos, *k++); count -= sizeof(*k); pos += sizeof(*k); } } else { const compat_ulong_t __user *u = ubuf; - while (count > 0 && !ret) { + while (count >= sizeof(*u) && !ret) { compat_ulong_t word; ret = __get_user(word, u++); if (ret) From ad46fed9c9b596b6ece5728aad3722a9c4acc8cb Mon Sep 17 00:00:00 2001 From: Daisuke Nishimura Date: Tue, 15 Dec 2009 16:47:12 -0800 Subject: [PATCH 250/670] memcg: avoid oom-killing innocent task in case of use_hierarchy commit d31f56dbf8bafaacb0c617f9a6f137498d5c7aed upstream. task_in_mem_cgroup(), which is called by select_bad_process() to check whether a task can be a candidate for being oom-killed from memcg's limit, checks "curr->use_hierarchy"("curr" is the mem_cgroup the task belongs to). But this check return true(it's false positive) when: /aa use_hierarchy == 0 <- hitting limit /aa/00 use_hierarchy == 1 <- the task belongs to This leads to killing an innocent task in aa/00. This patch is a fix for this bug. And this patch also fixes the arg for mem_cgroup_print_oom_info(). We should print information of mem_cgroup which the task being killed, not current, belongs to. Signed-off-by: Daisuke Nishimura Acked-by: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memcontrol.c | 8 +++++++- mm/oom_kill.c | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 63140151b618..5dc10374d769 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -758,7 +758,13 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem) task_unlock(task); if (!curr) return 0; - if (curr->use_hierarchy) + /* + * We should check use_hierarchy of "mem" not "curr". Because checking + * use_hierarchy of "curr" here make this function true if hierarchy is + * enabled in "curr" and "curr" is a child of "mem" in *cgroup* + * hierarchy(even if use_hierarchy is disabled in "mem"). + */ + if (mem->use_hierarchy) ret = css_is_ancestor(&curr->css, &mem->css); else ret = (curr == mem); diff --git a/mm/oom_kill.c b/mm/oom_kill.c index ea2147dabba6..9092b43f07fa 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -404,7 +404,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, cpuset_print_task_mems_allowed(current); task_unlock(current); dump_stack(); - mem_cgroup_print_oom_info(mem, current); + mem_cgroup_print_oom_info(mem, p); show_mem(); if (sysctl_oom_dump_tasks) dump_tasks(mem); From ee6bfc69e69474840cacb2f665831aff29bdbb40 Mon Sep 17 00:00:00 2001 From: Roger Oksanen Date: Fri, 18 Dec 2009 20:18:21 -0800 Subject: [PATCH 251/670] e100: Fix broken cbs accounting due to missing memset. commit 70abc8cb90e679d8519721e2761d8366a18212a6 upstream. Alan Stern noticed that e100 caused slab corruption. commit 98468efddb101f8a29af974101c17ba513b07be1 changed the allocation of cbs to use dma pools that don't return zeroed memory, especially the cb->status field used to track which cb to clean, causing (the visible) double freeing of skbs and a wrong free cbs count. Now the cbs are explicitly zeroed at allocation time. Reported-by: Alan Stern Tested-by: Alan Stern Signed-off-by: Roger Oksanen Acked-by: Jesse Brandeburg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/e100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index d269a68ce354..0c53c9295ff6 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1817,6 +1817,7 @@ static int e100_alloc_cbs(struct nic *nic) &nic->cbs_dma_addr); if (!nic->cbs) return -ENOMEM; + memset(nic->cbs, 0, count * sizeof(struct cb)); for (cb = nic->cbs, i = 0; i < count; cb++, i++) { cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; @@ -1825,7 +1826,6 @@ static int e100_alloc_cbs(struct nic *nic) cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); cb->link = cpu_to_le32(nic->cbs_dma_addr + ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; } nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; From 89cf4f4c853f1f9619d58d89aa7d1fc56e24ee3a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 15 Dec 2009 16:59:18 +0100 Subject: [PATCH 252/670] ipv6: reassembly: use seperate reassembly queues for conntrack and local delivery commit 0b5ccb2ee250136dd7385b1c7da28417d0d4d32d upstream. Currently the same reassembly queue might be used for packets reassembled by conntrack in different positions in the stack (PREROUTING/LOCAL_OUT), as well as local delivery. This can cause "packet jumps" when the fragment completing a reassembled packet is queued from a different position in the stack than the previous ones. Add a "user" identifier to the reassembly queue key to seperate the queues of each caller, similar to what we do for IPv4. Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- include/net/ipv6.h | 7 +++++++ include/net/netfilter/ipv6/nf_conntrack_ipv6.h | 2 +- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 13 +++++++++++-- net/ipv6/netfilter/nf_conntrack_reasm.c | 7 ++++--- net/ipv6/reassembly.c | 5 ++++- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 8c31d8a0c1fe..a49649906052 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -354,8 +354,15 @@ static inline int ipv6_prefix_equal(const struct in6_addr *a1, struct inet_frag_queue; +enum ip6_defrag_users { + IP6_DEFRAG_LOCAL_DELIVER, + IP6_DEFRAG_CONNTRACK_IN, + IP6_DEFRAG_CONNTRACK_OUT, +}; + struct ip6_create_arg { __be32 id; + u32 user; struct in6_addr *src; struct in6_addr *dst; }; diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h index abc55ad75c2b..1ee717eb5b09 100644 --- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h +++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h @@ -9,7 +9,7 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; extern int nf_ct_frag6_init(void); extern void nf_ct_frag6_cleanup(void); -extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb); +extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, struct net_device *in, struct net_device *out, diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 5f2ec208a8c3..c0a82fe78321 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -187,6 +187,16 @@ static unsigned int ipv6_confirm(unsigned int hooknum, return nf_conntrack_confirm(skb); } +static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, + struct sk_buff *skb) +{ + if (hooknum == NF_INET_PRE_ROUTING) + return IP6_DEFRAG_CONNTRACK_IN; + else + return IP6_DEFRAG_CONNTRACK_OUT; + +} + static unsigned int ipv6_defrag(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, @@ -199,8 +209,7 @@ static unsigned int ipv6_defrag(unsigned int hooknum, if (skb->nfct) return NF_ACCEPT; - reasm = nf_ct_frag6_gather(skb); - + reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); /* queued */ if (reasm == NULL) return NF_STOLEN; diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index f3aba255ad9f..4b6a539cb87a 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -170,13 +170,14 @@ static void nf_ct_frag6_expire(unsigned long data) /* Creation primitives. */ static __inline__ struct nf_ct_frag6_queue * -fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) +fq_find(__be32 id, u32 user, struct in6_addr *src, struct in6_addr *dst) { struct inet_frag_queue *q; struct ip6_create_arg arg; unsigned int hash; arg.id = id; + arg.user = user; arg.src = src; arg.dst = dst; @@ -561,7 +562,7 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff) return 0; } -struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) +struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) { struct sk_buff *clone; struct net_device *dev = skb->dev; @@ -607,7 +608,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) if (atomic_read(&nf_init_frags.mem) > nf_init_frags.high_thresh) nf_ct_frag6_evictor(); - fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr); + fq = fq_find(fhdr->identification, user, &hdr->saddr, &hdr->daddr); if (fq == NULL) { pr_debug("Can't find and can't create new queue\n"); goto ret_orig; diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index da5bd0ed83df..4d18699f93fd 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -72,6 +72,7 @@ struct frag_queue struct inet_frag_queue q; __be32 id; /* fragment id */ + u32 user; struct in6_addr saddr; struct in6_addr daddr; @@ -141,7 +142,7 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a) struct ip6_create_arg *arg = a; fq = container_of(q, struct frag_queue, q); - return (fq->id == arg->id && + return (fq->id == arg->id && fq->user == arg->user && ipv6_addr_equal(&fq->saddr, arg->src) && ipv6_addr_equal(&fq->daddr, arg->dst)); } @@ -163,6 +164,7 @@ void ip6_frag_init(struct inet_frag_queue *q, void *a) struct ip6_create_arg *arg = a; fq->id = arg->id; + fq->user = arg->user; ipv6_addr_copy(&fq->saddr, arg->src); ipv6_addr_copy(&fq->daddr, arg->dst); } @@ -244,6 +246,7 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, unsigned int hash; arg.id = id; + arg.user = IP6_DEFRAG_LOCAL_DELIVER; arg.src = src; arg.dst = dst; From 048a424c2826ccbeb9b08bc3a8c6bc7acbd3116d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 15 Dec 2009 16:59:59 +0100 Subject: [PATCH 253/670] netfilter: fix crashes in bridge netfilter caused by fragment jumps commit 8fa9ff6849bb86c59cc2ea9faadf3cb2d5223497 upstream. When fragments from bridge netfilter are passed to IPv4 or IPv6 conntrack and a reassembly queue with the same fragment key already exists from reassembling a similar packet received on a different device (f.i. with multicasted fragments), the reassembled packet might continue on a different codepath than where the head fragment originated. This can cause crashes in bridge netfilter when a fragment received on a non-bridge device (and thus with skb->nf_bridge == NULL) continues through the bridge netfilter code. Add a new reassembly identifier for packets originating from bridge netfilter and use it to put those packets in insolated queues. Fixes http://bugzilla.kernel.org/show_bug.cgi?id=14805 Reported-and-Tested-by: Chong Qiao Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- include/net/ip.h | 1 + include/net/ipv6.h | 1 + net/ipv4/netfilter/nf_defrag_ipv4.c | 21 +++++++++++++++---- .../netfilter/nf_conntrack_l3proto_ipv6.c | 6 ++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index 2f47e5482b55..69db943058ac 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -342,6 +342,7 @@ enum ip_defrag_users IP_DEFRAG_CALL_RA_CHAIN, IP_DEFRAG_CONNTRACK_IN, IP_DEFRAG_CONNTRACK_OUT, + IP_DEFRAG_CONNTRACK_BRIDGE_IN, IP_DEFRAG_VS_IN, IP_DEFRAG_VS_OUT, IP_DEFRAG_VS_FWD diff --git a/include/net/ipv6.h b/include/net/ipv6.h index a49649906052..639bbf06d378 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -358,6 +358,7 @@ enum ip6_defrag_users { IP6_DEFRAG_LOCAL_DELIVER, IP6_DEFRAG_CONNTRACK_IN, IP6_DEFRAG_CONNTRACK_OUT, + IP6_DEFRAG_CONNTRACK_BRIDGE_IN, }; struct ip6_create_arg { diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index fa2d6b6fc3e5..331ead3ebd1b 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -34,6 +35,20 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) return err; } +static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, + struct sk_buff *skb) +{ +#ifdef CONFIG_BRIDGE_NETFILTER + if (skb->nf_bridge && + skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) + return IP_DEFRAG_CONNTRACK_BRIDGE_IN; +#endif + if (hooknum == NF_INET_PRE_ROUTING) + return IP_DEFRAG_CONNTRACK_IN; + else + return IP_DEFRAG_CONNTRACK_OUT; +} + static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, @@ -50,10 +65,8 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, #endif /* Gather fragments. */ if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { - if (nf_ct_ipv4_gather_frags(skb, - hooknum == NF_INET_PRE_ROUTING ? - IP_DEFRAG_CONNTRACK_IN : - IP_DEFRAG_CONNTRACK_OUT)) + enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb); + if (nf_ct_ipv4_gather_frags(skb, user)) return NF_STOLEN; } return NF_ACCEPT; diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index c0a82fe78321..0956ebabbff2 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -190,6 +191,11 @@ static unsigned int ipv6_confirm(unsigned int hooknum, static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, struct sk_buff *skb) { +#ifdef CONFIG_BRIDGE_NETFILTER + if (skb->nf_bridge && + skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) + return IP6_DEFRAG_CONNTRACK_BRIDGE_IN; +#endif if (hooknum == NF_INET_PRE_ROUTING) return IP6_DEFRAG_CONNTRACK_IN; else From a8e3ec9aa0f527e759ab056952a1cb3ed102220d Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 16 Dec 2009 21:38:28 +0100 Subject: [PATCH 254/670] hwmon: (sht15) Off-by-one error in array index + incorrect constants commit 4235f684b66d6f00d2cd8849c884cf8f8b57ecad upstream. Fix an off-by-one error in array index + incorrect constants. Signed-off-by: Christoph Walser Signed-off-by: Jonathan Cameron Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/sht15.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index ebe38b680ee3..864a371f6eb9 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -305,7 +305,7 @@ static inline int sht15_calc_temp(struct sht15_data *data) int d1 = 0; int i; - for (i = 1; i < ARRAY_SIZE(temppoints) - 1; i++) + for (i = 1; i < ARRAY_SIZE(temppoints); i++) /* Find pointer to interpolate */ if (data->supply_uV > temppoints[i - 1].vdd) { d1 = (data->supply_uV/1000 - temppoints[i - 1].vdd) @@ -332,12 +332,12 @@ static inline int sht15_calc_humid(struct sht15_data *data) const int c1 = -4; const int c2 = 40500; /* x 10 ^ -6 */ - const int c3 = 2800; /* x10 ^ -9 */ + const int c3 = -2800; /* x10 ^ -9 */ RHlinear = c1*1000 + c2 * data->val_humid/1000 + (data->val_humid * data->val_humid * c3)/1000000; - return (temp - 25000) * (10000 + 800 * data->val_humid) + return (temp - 25000) * (10000 + 80 * data->val_humid) / 1000000 + RHlinear; } From 7fcb55881eb7a15e58ccfe81b4fe35fb06b12a7e Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 23 Nov 2009 18:40:45 -0600 Subject: [PATCH 255/670] b43: avoid PPC fault during resume commit c2ff581acab16c6af56d9e8c1a579bf041ec00b1 upstream. The routine b43_is_hw_radio_enabled() has long been a problem. For PPC architecture with PHY Revision < 3, a read of the register B43_MMIO_HWENABLED_LO will cause a CPU fault unless b43_status() returns a value of 2 (B43_STAT_STARTED) (BUG 14181). Fixing that results in Bug 14538 in which the driver is unable to reassociate after resuming from hibernation because b43_status() returns 0. The correct fix would be to determine why the status is 0; however, I have not yet found why that happens. The correct value is found for my device, which has PHY revision >= 3. Returning TRUE when the PHY revision < 3 and b43_status() returns 0 fixes the regression for 2.6.32. This patch fixes the problem in Red Hat Bugzilla #538523. Signed-off-by: Larry Finger Tested-by: Christian Casteyde Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43/rfkill.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index ffdce6f3c909..78016ae21c50 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -33,8 +33,14 @@ bool b43_is_hw_radio_enabled(struct b43_wldev *dev) & B43_MMIO_RADIO_HWENABLED_HI_MASK)) return 1; } else { - if (b43_status(dev) >= B43_STAT_STARTED && - b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) + /* To prevent CPU fault on PPC, do not read a register + * unless the interface is started; however, on resume + * for hibernation, this routine is entered early. When + * that happens, unconditionally return TRUE. + */ + if (b43_status(dev) < B43_STAT_STARTED) + return 1; + if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) & B43_MMIO_RADIO_HWENABLED_LO_MASK) return 1; } From fb70ac4b23fc108eb92eef9434e111bbdd7fd922 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 13 Dec 2009 20:21:34 +0100 Subject: [PATCH 256/670] Keys: KEYCTL_SESSION_TO_PARENT needs TIF_NOTIFY_RESUME architecture support commit a00ae4d21b2fa9379914f270ffffd8d3bec55430 upstream. As of commit ee18d64c1f632043a02e6f5ba5e045bb26a5465f ("KEYS: Add a keyctl to install a process's session keyring on its parent [try #6]"), CONFIG_KEYS=y fails to build on architectures that haven't implemented TIF_NOTIFY_RESUME yet: security/keys/keyctl.c: In function 'keyctl_session_to_parent': security/keys/keyctl.c:1312: error: 'TIF_NOTIFY_RESUME' undeclared (first use in this function) security/keys/keyctl.c:1312: error: (Each undeclared identifier is reported only once security/keys/keyctl.c:1312: error: for each function it appears in.) Make KEYCTL_SESSION_TO_PARENT depend on TIF_NOTIFY_RESUME until m68k, and xtensa have implemented it. Signed-off-by: Geert Uytterhoeven Signed-off-by: James Morris Acked-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- security/keys/keyctl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 06ec722897be..1cad4c7b1c33 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1236,6 +1236,7 @@ long keyctl_get_security(key_serial_t keyid, */ long keyctl_session_to_parent(void) { +#ifdef TIF_NOTIFY_RESUME struct task_struct *me, *parent; const struct cred *mycred, *pcred; struct cred *cred, *oldcred; @@ -1326,6 +1327,15 @@ long keyctl_session_to_parent(void) error_keyring: key_ref_put(keyring_r); return ret; + +#else /* !TIF_NOTIFY_RESUME */ + /* + * To be removed when TIF_NOTIFY_RESUME has been implemented on + * m68k/xtensa + */ +#warning TIF_NOTIFY_RESUME not implemented + return -EOPNOTSUPP; +#endif /* !TIF_NOTIFY_RESUME */ } /*****************************************************************************/ From a09adfeb9ea89d22c301749a87480ac98edc2cce Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 25 Nov 2009 13:31:39 +0100 Subject: [PATCH 257/670] sched: Fix balance vs hotplug race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6ad4c18884e864cf4c77f9074d3d1816063f99cd upstream. Since (e761b77: cpu hotplug, sched: Introduce cpu_active_map and redo sched domain managment) we have cpu_active_mask which is suppose to rule scheduler migration and load-balancing, except it never (fully) did. The particular problem being solved here is a crash in try_to_wake_up() where select_task_rq() ends up selecting an offline cpu because select_task_rq_fair() trusts the sched_domain tree to reflect the current state of affairs, similarly select_task_rq_rt() trusts the root_domain. However, the sched_domains are updated from CPU_DEAD, which is after the cpu is taken offline and after stop_machine is done. Therefore it can race perfectly well with code assuming the domains are right. Cure this by building the domains from cpu_active_mask on CPU_DOWN_PREPARE. Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar Cc: Mike Galbraith Cc: Holger Hoffstätte Signed-off-by: Greg Kroah-Hartman --- include/linux/cpumask.h | 2 ++ kernel/cpu.c | 18 +++++++++++++----- kernel/cpuset.c | 16 +++++++++------- kernel/sched.c | 32 +++++++++++++++++--------------- 4 files changed, 41 insertions(+), 27 deletions(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 789cf5f920ce..d77b54733c5b 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -84,6 +84,7 @@ extern const struct cpumask *const cpu_active_mask; #define num_online_cpus() cpumask_weight(cpu_online_mask) #define num_possible_cpus() cpumask_weight(cpu_possible_mask) #define num_present_cpus() cpumask_weight(cpu_present_mask) +#define num_active_cpus() cpumask_weight(cpu_active_mask) #define cpu_online(cpu) cpumask_test_cpu((cpu), cpu_online_mask) #define cpu_possible(cpu) cpumask_test_cpu((cpu), cpu_possible_mask) #define cpu_present(cpu) cpumask_test_cpu((cpu), cpu_present_mask) @@ -92,6 +93,7 @@ extern const struct cpumask *const cpu_active_mask; #define num_online_cpus() 1 #define num_possible_cpus() 1 #define num_present_cpus() 1 +#define num_active_cpus() 1 #define cpu_online(cpu) ((cpu) == 0) #define cpu_possible(cpu) ((cpu) == 0) #define cpu_present(cpu) ((cpu) == 0) diff --git a/kernel/cpu.c b/kernel/cpu.c index 6ba0f1ecb212..b21688640377 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -212,6 +212,8 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls); if (err == NOTIFY_BAD) { + set_cpu_active(cpu, true); + nr_calls--; __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL); @@ -223,11 +225,11 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) /* Ensure that we are not runnable on dying cpu */ cpumask_copy(old_allowed, ¤t->cpus_allowed); - set_cpus_allowed_ptr(current, - cpumask_of(cpumask_any_but(cpu_online_mask, cpu))); + set_cpus_allowed_ptr(current, cpu_active_mask); err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); if (err) { + set_cpu_active(cpu, true); /* CPU didn't die: tell everyone. Can't complain. */ if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, hcpu) == NOTIFY_BAD) @@ -292,9 +294,6 @@ int __ref cpu_down(unsigned int cpu) err = _cpu_down(cpu, 0); - if (cpu_online(cpu)) - set_cpu_active(cpu, true); - out: cpu_maps_update_done(); stop_machine_destroy(); @@ -387,6 +386,15 @@ int disable_nonboot_cpus(void) * with the userspace trying to use the CPU hotplug at the same time */ cpumask_clear(frozen_cpus); + + for_each_online_cpu(cpu) { + if (cpu == first_cpu) + continue; + set_cpu_active(cpu, false); + } + + synchronize_sched(); + printk("Disabling non-boot CPUs ...\n"); for_each_online_cpu(cpu) { if (cpu == first_cpu) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index b5cb469d2545..39e5121a78a6 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -873,7 +873,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, if (retval < 0) return retval; - if (!cpumask_subset(trialcs->cpus_allowed, cpu_online_mask)) + if (!cpumask_subset(trialcs->cpus_allowed, cpu_active_mask)) return -EINVAL; } retval = validate_change(cs, trialcs); @@ -2011,7 +2011,7 @@ static void scan_for_empty_cpusets(struct cpuset *root) } /* Continue past cpusets with all cpus, mems online */ - if (cpumask_subset(cp->cpus_allowed, cpu_online_mask) && + if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) && nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY])) continue; @@ -2020,7 +2020,7 @@ static void scan_for_empty_cpusets(struct cpuset *root) /* Remove offline cpus and mems from this cpuset. */ mutex_lock(&callback_mutex); cpumask_and(cp->cpus_allowed, cp->cpus_allowed, - cpu_online_mask); + cpu_active_mask); nodes_and(cp->mems_allowed, cp->mems_allowed, node_states[N_HIGH_MEMORY]); mutex_unlock(&callback_mutex); @@ -2058,8 +2058,10 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb, switch (phase) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - case CPU_DEAD: - case CPU_DEAD_FROZEN: + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: break; default: @@ -2068,7 +2070,7 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb, cgroup_lock(); mutex_lock(&callback_mutex); - cpumask_copy(top_cpuset.cpus_allowed, cpu_online_mask); + cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask); mutex_unlock(&callback_mutex); scan_for_empty_cpusets(&top_cpuset); ndoms = generate_sched_domains(&doms, &attr); @@ -2115,7 +2117,7 @@ static int cpuset_track_online_nodes(struct notifier_block *self, void __init cpuset_init_smp(void) { - cpumask_copy(top_cpuset.cpus_allowed, cpu_online_mask); + cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask); top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; hotcpu_notifier(cpuset_track_online_cpus, 0); diff --git a/kernel/sched.c b/kernel/sched.c index 279785961eae..04144dbe9f22 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4139,7 +4139,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, unsigned long flags; struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask); - cpumask_copy(cpus, cpu_online_mask); + cpumask_copy(cpus, cpu_active_mask); /* * When power savings policy is enabled for the parent domain, idle @@ -4302,7 +4302,7 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd) int all_pinned = 0; struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask); - cpumask_copy(cpus, cpu_online_mask); + cpumask_copy(cpus, cpu_active_mask); /* * When power savings policy is enabled for the parent domain, idle @@ -4699,7 +4699,7 @@ int select_nohz_load_balancer(int stop_tick) cpumask_set_cpu(cpu, nohz.cpu_mask); /* time for ilb owner also to sleep */ - if (cpumask_weight(nohz.cpu_mask) == num_online_cpus()) { + if (cpumask_weight(nohz.cpu_mask) == num_active_cpus()) { if (atomic_read(&nohz.load_balancer) == cpu) atomic_set(&nohz.load_balancer, -1); return 0; @@ -7075,7 +7075,7 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) int ret = 0; rq = task_rq_lock(p, &flags); - if (!cpumask_intersects(new_mask, cpu_online_mask)) { + if (!cpumask_intersects(new_mask, cpu_active_mask)) { ret = -EINVAL; goto out; } @@ -7097,7 +7097,7 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) if (cpumask_test_cpu(task_cpu(p), new_mask)) goto out; - if (migrate_task(p, cpumask_any_and(cpu_online_mask, new_mask), &req)) { + if (migrate_task(p, cpumask_any_and(cpu_active_mask, new_mask), &req)) { /* Need help from migration thread: drop lock and wait. */ struct task_struct *mt = rq->migration_thread; @@ -7251,19 +7251,19 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) again: /* Look for allowed, online CPU in same node. */ - for_each_cpu_and(dest_cpu, nodemask, cpu_online_mask) + for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask) if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed)) goto move; /* Any allowed, online CPU? */ - dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_online_mask); + dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_active_mask); if (dest_cpu < nr_cpu_ids) goto move; /* No more Mr. Nice Guy. */ if (dest_cpu >= nr_cpu_ids) { cpuset_cpus_allowed_locked(p, &p->cpus_allowed); - dest_cpu = cpumask_any_and(cpu_online_mask, &p->cpus_allowed); + dest_cpu = cpumask_any_and(cpu_active_mask, &p->cpus_allowed); /* * Don't tell them about moving exiting tasks or @@ -7292,7 +7292,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) */ static void migrate_nr_uninterruptible(struct rq *rq_src) { - struct rq *rq_dest = cpu_rq(cpumask_any(cpu_online_mask)); + struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask)); unsigned long flags; local_irq_save(flags); @@ -7546,7 +7546,7 @@ static ctl_table *sd_alloc_ctl_cpu_table(int cpu) static struct ctl_table_header *sd_sysctl_header; static void register_sched_domain_sysctl(void) { - int i, cpu_num = num_online_cpus(); + int i, cpu_num = num_possible_cpus(); struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1); char buf[32]; @@ -7556,7 +7556,7 @@ static void register_sched_domain_sysctl(void) if (entry == NULL) return; - for_each_online_cpu(i) { + for_each_possible_cpu(i) { snprintf(buf, 32, "cpu%d", i); entry->procname = kstrdup(buf, GFP_KERNEL); entry->mode = 0555; @@ -9042,7 +9042,7 @@ void partition_sched_domains(int ndoms_new, struct cpumask *doms_new, if (doms_new == NULL) { ndoms_cur = 0; doms_new = fallback_doms; - cpumask_andnot(&doms_new[0], cpu_online_mask, cpu_isolated_map); + cpumask_andnot(&doms_new[0], cpu_active_mask, cpu_isolated_map); WARN_ON_ONCE(dattr_new); } @@ -9173,8 +9173,10 @@ static int update_sched_domains(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - case CPU_DEAD: - case CPU_DEAD_FROZEN: + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: partition_sched_domains(1, NULL, NULL); return NOTIFY_OK; @@ -9221,7 +9223,7 @@ void __init sched_init_smp(void) #endif get_online_cpus(); mutex_lock(&sched_domains_mutex); - arch_init_sched_domains(cpu_online_mask); + arch_init_sched_domains(cpu_active_mask); cpumask_andnot(non_isolated_cpus, cpu_possible_mask, cpu_isolated_map); if (cpumask_empty(non_isolated_cpus)) cpumask_set_cpu(smp_processor_id(), non_isolated_cpus); From 08ff73341f9d5bde2d5e54bfe4d6a3d2a3f2ee83 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 21 Dec 2009 14:33:52 +1000 Subject: [PATCH 258/670] drm/radeon/kms: fix crtc vblank update for r600 In 2.6.32.2 r600 had no IRQ support, however the patch in 500b758725314ab1b5316eb0caa5b0fa26740e6b to fix vblanks on avivo cards, needs irqs. So check for an R600 card and avoid this path if so. This is a stable only patch for 2.6.32.2 as 2.6.33 has IRQs for r600. Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atombios_crtc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index c6777cbee474..19f93f2b9a12 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -249,13 +249,15 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) if (ASIC_IS_DCE3(rdev)) atombios_enable_crtc_memreq(crtc, 1); atombios_blank_crtc(crtc, 0); - drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); + if (rdev->family < CHIP_R600) + drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); radeon_crtc_load_lut(crtc); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); + if (rdev->family < CHIP_R600) + drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); atombios_blank_crtc(crtc, 1); if (ASIC_IS_DCE3(rdev)) atombios_enable_crtc_memreq(crtc, 0); From 4012cf67b9f1841ad582ca094c230439d98c8a4d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 9 Dec 2009 11:23:42 +0800 Subject: [PATCH 259/670] drm: disable all the possible outputs/crtcs before entering KMS mode commit b16d9acbdb97452d1418420e069acf7381ef10bb upstream. Sometimes we will use a crtc for integerated LVDS, which is different with that assigned by BIOS. If we want to get flicker-free transitions, then we could read out the current state for it and set our current state accordingly. But it is true that if we aren't reading current state out, we do need to turn everything off before modesetting. Otherwise the clocks can get very angry and we get things worse than a flicker at boot. In fact we also do the similar thing in UMS mode. We will disable all the possible outputs/crtcs for the first modesetting. So we disable all the possible outputs/crtcs before entering the KMS mode. Before we configure connector/encoder/crtc, the function of drm_helper_disable_unused_function can disable all the possible outputs/crtcs. Signed-off-by: Zhao Yakui Reviewed-by: Eric Anholt Reviewed-by: Rafal Milecki Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_crtc_helper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index bbfd110a7168..afed886cb0fe 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -1020,6 +1020,9 @@ bool drm_helper_initial_config(struct drm_device *dev) { int count = 0; + /* disable all the possible outputs/crtcs before entering KMS mode */ + drm_helper_disable_unused_functions(dev); + drm_fb_helper_parse_command_line(dev); count = drm_helper_probe_connector_modes(dev, From 1dc51f1054ff6444540c3a3e45aad6657d130562 Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Mon, 7 Dec 2009 12:51:48 +0100 Subject: [PATCH 260/670] S390: dasd: support DIAG access for read-only devices commit 22825ab7693fd29769518a0d25ba43c01a50092a upstream. When a DASD device is used with the DIAG discipline, the DIAG initialization will indicate success or error with a respective return code. So far we have interpreted a return code of 4 as error, but it actually means that the initialization was successful, but the device is read-only. To allow read-only devices to be used with DIAG we need to accept a return code of 4 as success. Re-initialization of the DIAG access is also part of the DIAG error recovery. If we find that the access mode of a device has been changed from writable to read-only while the device was in use, we print an error message. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky Cc: Stephen Powell Signed-off-by: Greg Kroah-Hartman --- drivers/s390/block/dasd_diag.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 4e49b4a6c880..8174ec921769 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -145,6 +145,15 @@ dasd_diag_erp(struct dasd_device *device) mdsk_term_io(device); rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); + if (rc == 4) { + if (!(device->features & DASD_FEATURE_READONLY)) { + dev_warn(&device->cdev->dev, + "The access mode of a DIAG device changed" + " to read-only"); + device->features |= DASD_FEATURE_READONLY; + } + rc = 0; + } if (rc) dev_warn(&device->cdev->dev, "DIAG ERP failed with " "rc=%d\n", rc); @@ -433,16 +442,20 @@ dasd_diag_check_device(struct dasd_device *device) for (sb = 512; sb < bsize; sb = sb << 1) block->s2b_shift++; rc = mdsk_init_io(device, block->bp_block, 0, NULL); - if (rc) { + if (rc && (rc != 4)) { dev_warn(&device->cdev->dev, "DIAG initialization " "failed with rc=%d\n", rc); rc = -EIO; } else { + if (rc == 4) + device->features |= DASD_FEATURE_READONLY; dev_info(&device->cdev->dev, - "New DASD with %ld byte/block, total size %ld KB\n", + "New DASD with %ld byte/block, total size %ld KB%s\n", (unsigned long) block->bp_block, (unsigned long) (block->blocks << - block->s2b_shift) >> 1); + block->s2b_shift) >> 1, + (rc == 4) ? ", read-only device" : ""); + rc = 0; } out_label: free_page((long) label); From af70ddfa0a21d625f1b7ed3389ce30eeed0896c3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Jul 2009 12:27:37 +0200 Subject: [PATCH 261/670] xen: fix is_disconnected_device/exists_disconnected_device commit c6e1971139be1342902873181f3b80a979bfb33b upstream. The logic of is_disconnected_device/exists_disconnected_device is wrong in that they are used to test whether a device is trying to connect (i.e. connecting). For this reason the patch fixes them to not consider a Closing or Closed device to be connecting. At the same time the patch also renames the functions according to what they really do; you could say a closed device is "disconnected" (the old name), but not "connecting" (the new name). This patch is a backport of changeset 909 from the Xenbits tree. Cc: Jeremy Fitzhardinge Signed-off-by: Paolo Bonzini Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xenbus/xenbus_probe.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 3800da7dabfe..19bce3e1b333 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -843,7 +843,7 @@ postcore_initcall(xenbus_probe_init); MODULE_LICENSE("GPL"); -static int is_disconnected_device(struct device *dev, void *data) +static int is_device_connecting(struct device *dev, void *data) { struct xenbus_device *xendev = to_xenbus_device(dev); struct device_driver *drv = data; @@ -861,14 +861,15 @@ static int is_disconnected_device(struct device *dev, void *data) return 0; xendrv = to_xenbus_driver(dev->driver); - return (xendev->state != XenbusStateConnected || - (xendrv->is_ready && !xendrv->is_ready(xendev))); + return (xendev->state < XenbusStateConnected || + (xendev->state == XenbusStateConnected && + xendrv->is_ready && !xendrv->is_ready(xendev))); } -static int exists_disconnected_device(struct device_driver *drv) +static int exists_connecting_device(struct device_driver *drv) { return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, - is_disconnected_device); + is_device_connecting); } static int print_device_status(struct device *dev, void *data) @@ -918,7 +919,7 @@ static void wait_for_devices(struct xenbus_driver *xendrv) if (!ready_to_wait_for_devices || !xen_domain()) return; - while (exists_disconnected_device(drv)) { + while (exists_connecting_device(drv)) { if (time_after(jiffies, timeout)) break; schedule_timeout_interruptible(HZ/10); From 2cfea0096f008796246646f7cb1483f9b298b1d2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Jul 2009 12:27:38 +0200 Subject: [PATCH 262/670] xen: improvement to wait_for_devices() commit f8dc33088febc63286b7a60e6b678de8e064de8e upstream. When printing a warning about a timed-out device, print the current state of both ends of the device connection (i.e., backend as well as frontend). This backports half of changeset 146 from the Xenbits tree. Cc: Jeremy Fitzhardinge Signed-off-by: Paolo Bonzini Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xenbus/xenbus_probe.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 19bce3e1b333..9246a8c4ecf2 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -885,10 +885,13 @@ static int print_device_status(struct device *dev, void *data) /* Information only: is this too noisy? */ printk(KERN_INFO "XENBUS: Device with no driver: %s\n", xendev->nodename); - } else if (xendev->state != XenbusStateConnected) { + } else if (xendev->state < XenbusStateConnected) { + enum xenbus_state rstate = XenbusStateUnknown; + if (xendev->otherend) + rstate = xenbus_read_driver_state(xendev->otherend); printk(KERN_WARNING "XENBUS: Timeout connecting " - "to device: %s (state %d)\n", - xendev->nodename, xendev->state); + "to device: %s (local state %d, remote state %d)\n", + xendev->nodename, xendev->state, rstate); } return 0; From fad0c314dd0f0c3293b202c23ade933ec43e6961 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Jul 2009 12:27:39 +0200 Subject: [PATCH 263/670] xen: wait up to 5 minutes for device connetion commit ae7888012969355a548372e99b066d9e31153b62 upstream. Increases the device timeout from 10s to 5 minutes, giving the user a visual indication during that time in case there are problems. The patch is a backport of changesets 144 and 150 in the Xenbits tree. Cc: Jeremy Fitzhardinge Signed-off-by: Paolo Bonzini Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xenbus/xenbus_probe.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 9246a8c4ecf2..649fcdf114b7 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -901,7 +901,7 @@ static int print_device_status(struct device *dev, void *data) static int ready_to_wait_for_devices; /* - * On a 10 second timeout, wait for all devices currently configured. We need + * On a 5-minute timeout, wait for all devices currently configured. We need * to do this to guarantee that the filesystems and / or network devices * needed for boot are available, before we can allow the boot to proceed. * @@ -916,18 +916,30 @@ static int ready_to_wait_for_devices; */ static void wait_for_devices(struct xenbus_driver *xendrv) { - unsigned long timeout = jiffies + 10*HZ; + unsigned long start = jiffies; struct device_driver *drv = xendrv ? &xendrv->driver : NULL; + unsigned int seconds_waited = 0; if (!ready_to_wait_for_devices || !xen_domain()) return; while (exists_connecting_device(drv)) { - if (time_after(jiffies, timeout)) - break; + if (time_after(jiffies, start + (seconds_waited+5)*HZ)) { + if (!seconds_waited) + printk(KERN_WARNING "XENBUS: Waiting for " + "devices to initialise: "); + seconds_waited += 5; + printk("%us...", 300 - seconds_waited); + if (seconds_waited == 300) + break; + } + schedule_timeout_interruptible(HZ/10); } + if (seconds_waited) + printk("\n"); + bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, print_device_status); } From 3196f989c52765aa202a7917ca381aeafa509a83 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Tue, 22 Dec 2009 21:38:44 +0300 Subject: [PATCH 264/670] orinoco: fix GFP_KERNEL in orinoco_set_key with interrupts disabled commit 5b0691508aa99d309101a49b4b084dc16b3d7019 upstream. orinoco_set_key is called from two places both with interrupts disabled (under orinoco_lock). Use GFP_ATOMIC instead of GFP_KERNEL. Fixes following warning: [ 77.254109] WARNING: at /home/bor/src/linux-git/kernel/lockdep.c:2465 lockdep_trace_alloc+0x9a/0xa0() [ 77.254109] Hardware name: PORTEGE 4000 [ 77.254109] Modules linked in: af_packet irnet ppp_generic slhc ircomm_tty ircomm binfmt_misc dm_mirror dm_region_hash dm_log dm_round_robin dm_multipath dm_mod loop nvram toshiba cryptomgr aead pcompress crypto_blkcipher michael_mic crypto_hash crypto_algapi orinoco_cs orinoco cfg80211 smsc_ircc2 pcmcia irda toshiba_acpi yenta_socket video i2c_ali1535 backlight rsrc_nonstatic ali_agp pcmcia_core psmouse output crc_ccitt i2c_core alim1535_wdt rfkill sg evdev ohci_hcd agpgart usbcore pata_ali libata reiserfs [last unloaded: scsi_wait_scan] [ 77.254109] Pid: 2296, comm: wpa_supplicant Not tainted 2.6.32-1avb #1 [ 77.254109] Call Trace: [ 77.254109] [] warn_slowpath_common+0x6d/0xa0 [ 77.254109] [] ? lockdep_trace_alloc+0x9a/0xa0 [ 77.254109] [] ? lockdep_trace_alloc+0x9a/0xa0 [ 77.254109] [] warn_slowpath_null+0x15/0x20 [ 77.254109] [] lockdep_trace_alloc+0x9a/0xa0 [ 77.254109] [] __kmalloc+0x36/0x130 [ 77.254109] [] ? orinoco_set_key+0x48/0x1c0 [orinoco] [ 77.254109] [] orinoco_set_key+0x48/0x1c0 [orinoco] [ 77.254109] [] orinoco_ioctl_set_encodeext+0x1dc/0x2d0 [orinoco] [ 77.254109] [] ioctl_standard_call+0x207/0x3b0 [ 77.254109] [] ? orinoco_ioctl_set_encodeext+0x0/0x2d0 [orinoco] [ 77.254109] [] ? rtnl_lock+0xf/0x20 [ 77.254109] [] ? rtnl_lock+0xf/0x20 [ 77.254109] [] ? __dev_get_by_name+0x85/0xb0 [ 77.254109] [] wext_handle_ioctl+0x176/0x200 [ 77.254109] [] ? orinoco_ioctl_set_encodeext+0x0/0x2d0 [orinoco] [ 77.254109] [] dev_ioctl+0x6af/0x730 [ 77.254109] [] ? move_addr_to_kernel+0x55/0x60 [ 77.254109] [] ? sys_sendto+0xe9/0x130 [ 77.254109] [] sock_ioctl+0x7e/0x250 [ 77.254109] [] ? sock_ioctl+0x0/0x250 [ 77.254109] [] vfs_ioctl+0x1c/0x70 [ 77.254109] [] do_vfs_ioctl+0x6a/0x590 [ 77.254109] [] ? might_fault+0x90/0xa0 [ 77.254109] [] ? might_fault+0x4a/0xa0 [ 77.254109] [] ? sys_socketcall+0x17e/0x280 [ 77.254109] [] sys_ioctl+0x39/0x60 [ 77.254109] [] sysenter_do_call+0x12/0x32 [ 77.254109] ---[ end trace 95ef563548d21efd ]--- Signed-off-by: Andrey Borzenkov Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/orinoco/wext.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 7698fdd6a3a2..31ca241f7753 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -23,7 +23,7 @@ #define MAX_RID_LEN 1024 /* Helper routine to record keys - * Do not call from interrupt context */ + * It is called under orinoco_lock so it may not sleep */ static int orinoco_set_key(struct orinoco_private *priv, int index, enum orinoco_alg alg, const u8 *key, int key_len, const u8 *seq, int seq_len) @@ -32,14 +32,14 @@ static int orinoco_set_key(struct orinoco_private *priv, int index, kzfree(priv->keys[index].seq); if (key_len) { - priv->keys[index].key = kzalloc(key_len, GFP_KERNEL); + priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC); if (!priv->keys[index].key) goto nomem; } else priv->keys[index].key = NULL; if (seq_len) { - priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL); + priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC); if (!priv->keys[index].seq) goto free_key; } else From 0aebc28083514af318c438fccc8a7ae23b4e1ab8 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 30 Nov 2009 19:47:55 +0100 Subject: [PATCH 265/670] udf: Try harder when looking for VAT inode commit e971b0b9e0dd50d9ceecb67a6a6ab80a80906033 upstream. Some disks do not contain VAT inode in the last recorded block as required by the standard but a few blocks earlier (or the number of recorded blocks is wrong). So look for the VAT inode a bit before the end of the media. Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/udf/super.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 9d1b8c2e6c45..1e4543cbcd27 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1078,21 +1078,39 @@ static int udf_fill_partdesc_info(struct super_block *sb, return 0; } +static void udf_find_vat_block(struct super_block *sb, int p_index, + int type1_index, sector_t start_block) +{ + struct udf_sb_info *sbi = UDF_SB(sb); + struct udf_part_map *map = &sbi->s_partmaps[p_index]; + sector_t vat_block; + struct kernel_lb_addr ino; + + /* + * VAT file entry is in the last recorded block. Some broken disks have + * it a few blocks before so try a bit harder... + */ + ino.partitionReferenceNum = type1_index; + for (vat_block = start_block; + vat_block >= map->s_partition_root && + vat_block >= start_block - 3 && + !sbi->s_vat_inode; vat_block--) { + ino.logicalBlockNum = vat_block - map->s_partition_root; + sbi->s_vat_inode = udf_iget(sb, &ino); + } +} + static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) { struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map = &sbi->s_partmaps[p_index]; - struct kernel_lb_addr ino; struct buffer_head *bh = NULL; struct udf_inode_info *vati; uint32_t pos; struct virtualAllocationTable20 *vat20; sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; - /* VAT file entry is in the last recorded block */ - ino.partitionReferenceNum = type1_index; - ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; - sbi->s_vat_inode = udf_iget(sb, &ino); + udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block); if (!sbi->s_vat_inode && sbi->s_last_block != blocks - 1) { printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" @@ -1100,9 +1118,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) "block of the device (%lu).\n", (unsigned long)sbi->s_last_block, (unsigned long)blocks - 1); - ino.partitionReferenceNum = type1_index; - ino.logicalBlockNum = blocks - 1 - map->s_partition_root; - sbi->s_vat_inode = udf_iget(sb, &ino); + udf_find_vat_block(sb, p_index, type1_index, blocks - 1); } if (!sbi->s_vat_inode) return 1; From f07c88dd6cbcc8086e28759f3686068163d423ae Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Mon, 14 Dec 2009 15:21:12 +0300 Subject: [PATCH 266/670] Add unlocked version of inode_add_bytes() function commit b462707e7ccad058ae151e5c5b06eb5cadcb737f upstream. Quota code requires unlocked version of this function. Off course we can just copy-paste the code, but copy-pasting is always an evil. Signed-off-by: Dmitry Monakhov Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/stat.c | 10 ++++++++-- include/linux/fs.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/stat.c b/fs/stat.c index 075694e31d8b..c4ecd52c5737 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -401,9 +401,9 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, char __user *, filename, } #endif /* __ARCH_WANT_STAT64 */ -void inode_add_bytes(struct inode *inode, loff_t bytes) +/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */ +void __inode_add_bytes(struct inode *inode, loff_t bytes) { - spin_lock(&inode->i_lock); inode->i_blocks += bytes >> 9; bytes &= 511; inode->i_bytes += bytes; @@ -411,6 +411,12 @@ void inode_add_bytes(struct inode *inode, loff_t bytes) inode->i_blocks++; inode->i_bytes -= 512; } +} + +void inode_add_bytes(struct inode *inode, loff_t bytes) +{ + spin_lock(&inode->i_lock); + __inode_add_bytes(inode, bytes); spin_unlock(&inode->i_lock); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 2620a8c63571..98ea20018151 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2314,6 +2314,7 @@ extern const struct inode_operations page_symlink_inode_operations; extern int generic_readlink(struct dentry *, char __user *, int); extern void generic_fillattr(struct inode *, struct kstat *); extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); +void __inode_add_bytes(struct inode *inode, loff_t bytes); void inode_add_bytes(struct inode *inode, loff_t bytes); void inode_sub_bytes(struct inode *inode, loff_t bytes); loff_t inode_get_bytes(struct inode *inode); From bbf245072d81e512cc88535379ae6edb5d08f420 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Mon, 14 Dec 2009 15:21:13 +0300 Subject: [PATCH 267/670] quota: decouple fs reserved space from quota reservation commit fd8fbfc1709822bd94247c5b2ab15a5f5041e103 upstream. Currently inode_reservation is managed by fs itself and this reservation is transfered on dquot_transfer(). This means what inode_reservation must always be in sync with dquot->dq_dqb.dqb_rsvspace. Otherwise dquot_transfer() will result in incorrect quota(WARN_ON in dquot_claim_reserved_space() will be triggered) This is not easy because of complex locking order issues for example http://bugzilla.kernel.org/show_bug.cgi?id=14739 The patch introduce quota reservation field for each fs-inode (fs specific inode is used in order to prevent bloating generic vfs inode). This reservation is managed by quota code internally similar to i_blocks/i_bytes and may not be always in sync with internal fs reservation. Also perform some code rearrangement: - Unify dquot_reserve_space() and dquot_reserve_space() - Unify dquot_release_reserved_space() and dquot_free_space() - Also this patch add missing warning update to release_rsv() dquot_release_reserved_space() must call flush_warnings() as dquot_free_space() does. Signed-off-by: Dmitry Monakhov Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/quota/dquot.c | 219 +++++++++++++++++++++++------------------- include/linux/quota.h | 5 +- 2 files changed, 125 insertions(+), 99 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 39b49c42a7ed..c4d07a803bd0 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -1387,6 +1387,67 @@ void vfs_dq_drop(struct inode *inode) } EXPORT_SYMBOL(vfs_dq_drop); +/* + * inode_reserved_space is managed internally by quota, and protected by + * i_lock similar to i_blocks+i_bytes. + */ +static qsize_t *inode_reserved_space(struct inode * inode) +{ + /* Filesystem must explicitly define it's own method in order to use + * quota reservation interface */ + BUG_ON(!inode->i_sb->dq_op->get_reserved_space); + return inode->i_sb->dq_op->get_reserved_space(inode); +} + +static void inode_add_rsv_space(struct inode *inode, qsize_t number) +{ + spin_lock(&inode->i_lock); + *inode_reserved_space(inode) += number; + spin_unlock(&inode->i_lock); +} + + +static void inode_claim_rsv_space(struct inode *inode, qsize_t number) +{ + spin_lock(&inode->i_lock); + *inode_reserved_space(inode) -= number; + __inode_add_bytes(inode, number); + spin_unlock(&inode->i_lock); +} + +static void inode_sub_rsv_space(struct inode *inode, qsize_t number) +{ + spin_lock(&inode->i_lock); + *inode_reserved_space(inode) -= number; + spin_unlock(&inode->i_lock); +} + +static qsize_t inode_get_rsv_space(struct inode *inode) +{ + qsize_t ret; + spin_lock(&inode->i_lock); + ret = *inode_reserved_space(inode); + spin_unlock(&inode->i_lock); + return ret; +} + +static void inode_incr_space(struct inode *inode, qsize_t number, + int reserve) +{ + if (reserve) + inode_add_rsv_space(inode, number); + else + inode_add_bytes(inode, number); +} + +static void inode_decr_space(struct inode *inode, qsize_t number, int reserve) +{ + if (reserve) + inode_sub_rsv_space(inode, number); + else + inode_sub_bytes(inode, number); +} + /* * Following four functions update i_blocks+i_bytes fields and * quota information (together with appropriate checks) @@ -1405,6 +1466,21 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int cnt, ret = QUOTA_OK; char warntype[MAXQUOTAS]; + /* + * First test before acquiring mutex - solves deadlocks when we + * re-enter the quota code and are already holding the mutex + */ + if (IS_NOQUOTA(inode)) { + inode_incr_space(inode, number, reserve); + goto out; + } + + down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); + if (IS_NOQUOTA(inode)) { + inode_incr_space(inode, number, reserve); + goto out_unlock; + } + for (cnt = 0; cnt < MAXQUOTAS; cnt++) warntype[cnt] = QUOTA_NL_NOWARN; @@ -1415,7 +1491,8 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA) { ret = NO_QUOTA; - goto out_unlock; + spin_unlock(&dq_data_lock); + goto out_flush_warn; } } for (cnt = 0; cnt < MAXQUOTAS; cnt++) { @@ -1426,64 +1503,32 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, else dquot_incr_space(inode->i_dquot[cnt], number); } - if (!reserve) - inode_add_bytes(inode, number); -out_unlock: + inode_incr_space(inode, number, reserve); spin_unlock(&dq_data_lock); + + if (reserve) + goto out_flush_warn; + /* Dirtify all the dquots - this can block when journalling */ + for (cnt = 0; cnt < MAXQUOTAS; cnt++) + if (inode->i_dquot[cnt]) + mark_dquot_dirty(inode->i_dquot[cnt]); +out_flush_warn: flush_warnings(inode->i_dquot, warntype); +out_unlock: + up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); +out: return ret; } int dquot_alloc_space(struct inode *inode, qsize_t number, int warn) { - int cnt, ret = QUOTA_OK; - - /* - * First test before acquiring mutex - solves deadlocks when we - * re-enter the quota code and are already holding the mutex - */ - if (IS_NOQUOTA(inode)) { - inode_add_bytes(inode, number); - goto out; - } - - down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); - if (IS_NOQUOTA(inode)) { - inode_add_bytes(inode, number); - goto out_unlock; - } - - ret = __dquot_alloc_space(inode, number, warn, 0); - if (ret == NO_QUOTA) - goto out_unlock; - - /* Dirtify all the dquots - this can block when journalling */ - for (cnt = 0; cnt < MAXQUOTAS; cnt++) - if (inode->i_dquot[cnt]) - mark_dquot_dirty(inode->i_dquot[cnt]); -out_unlock: - up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); -out: - return ret; + return __dquot_alloc_space(inode, number, warn, 0); } EXPORT_SYMBOL(dquot_alloc_space); int dquot_reserve_space(struct inode *inode, qsize_t number, int warn) { - int ret = QUOTA_OK; - - if (IS_NOQUOTA(inode)) - goto out; - - down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); - if (IS_NOQUOTA(inode)) - goto out_unlock; - - ret = __dquot_alloc_space(inode, number, warn, 1); -out_unlock: - up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); -out: - return ret; + return __dquot_alloc_space(inode, number, warn, 1); } EXPORT_SYMBOL(dquot_reserve_space); @@ -1540,14 +1585,14 @@ int dquot_claim_space(struct inode *inode, qsize_t number) int ret = QUOTA_OK; if (IS_NOQUOTA(inode)) { - inode_add_bytes(inode, number); + inode_claim_rsv_space(inode, number); goto out; } down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); if (IS_NOQUOTA(inode)) { up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); - inode_add_bytes(inode, number); + inode_claim_rsv_space(inode, number); goto out; } @@ -1559,7 +1604,7 @@ int dquot_claim_space(struct inode *inode, qsize_t number) number); } /* Update inode bytes */ - inode_add_bytes(inode, number); + inode_claim_rsv_space(inode, number); spin_unlock(&dq_data_lock); /* Dirtify all the dquots - this can block when journalling */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) @@ -1571,39 +1616,10 @@ int dquot_claim_space(struct inode *inode, qsize_t number) } EXPORT_SYMBOL(dquot_claim_space); -/* - * Release reserved quota space - */ -void dquot_release_reserved_space(struct inode *inode, qsize_t number) -{ - int cnt; - - if (IS_NOQUOTA(inode)) - goto out; - - down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); - if (IS_NOQUOTA(inode)) - goto out_unlock; - - spin_lock(&dq_data_lock); - /* Release reserved dquots */ - for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (inode->i_dquot[cnt]) - dquot_free_reserved_space(inode->i_dquot[cnt], number); - } - spin_unlock(&dq_data_lock); - -out_unlock: - up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); -out: - return; -} -EXPORT_SYMBOL(dquot_release_reserved_space); - /* * This operation can block, but only after everything is updated */ -int dquot_free_space(struct inode *inode, qsize_t number) +int __dquot_free_space(struct inode *inode, qsize_t number, int reserve) { unsigned int cnt; char warntype[MAXQUOTAS]; @@ -1612,7 +1628,7 @@ int dquot_free_space(struct inode *inode, qsize_t number) * re-enter the quota code and are already holding the mutex */ if (IS_NOQUOTA(inode)) { out_sub: - inode_sub_bytes(inode, number); + inode_decr_space(inode, number, reserve); return QUOTA_OK; } @@ -1627,20 +1643,42 @@ int dquot_free_space(struct inode *inode, qsize_t number) if (!inode->i_dquot[cnt]) continue; warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number); - dquot_decr_space(inode->i_dquot[cnt], number); + if (reserve) + dquot_free_reserved_space(inode->i_dquot[cnt], number); + else + dquot_decr_space(inode->i_dquot[cnt], number); } - inode_sub_bytes(inode, number); + inode_decr_space(inode, number, reserve); spin_unlock(&dq_data_lock); + + if (reserve) + goto out_unlock; /* Dirtify all the dquots - this can block when journalling */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) if (inode->i_dquot[cnt]) mark_dquot_dirty(inode->i_dquot[cnt]); +out_unlock: flush_warnings(inode->i_dquot, warntype); up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); return QUOTA_OK; } + +int dquot_free_space(struct inode *inode, qsize_t number) +{ + return __dquot_free_space(inode, number, 0); +} EXPORT_SYMBOL(dquot_free_space); +/* + * Release reserved quota space + */ +void dquot_release_reserved_space(struct inode *inode, qsize_t number) +{ + __dquot_free_space(inode, number, 1); + +} +EXPORT_SYMBOL(dquot_release_reserved_space); + /* * This operation can block, but only after everything is updated */ @@ -1678,19 +1716,6 @@ int dquot_free_inode(const struct inode *inode, qsize_t number) } EXPORT_SYMBOL(dquot_free_inode); -/* - * call back function, get reserved quota space from underlying fs - */ -qsize_t dquot_get_reserved_space(struct inode *inode) -{ - qsize_t reserved_space = 0; - - if (sb_any_quota_active(inode->i_sb) && - inode->i_sb->dq_op->get_reserved_space) - reserved_space = inode->i_sb->dq_op->get_reserved_space(inode); - return reserved_space; -} - /* * Transfer the number of inode and blocks from one diskquota to an other. * @@ -1734,7 +1759,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) } spin_lock(&dq_data_lock); cur_space = inode_get_bytes(inode); - rsv_space = dquot_get_reserved_space(inode); + rsv_space = inode_get_rsv_space(inode); space = cur_space + rsv_space; /* Build the transfer_from list and check the limits */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { diff --git a/include/linux/quota.h b/include/linux/quota.h index 78c48895b12a..8fd8efcb6f2e 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -313,8 +313,9 @@ struct dquot_operations { int (*claim_space) (struct inode *, qsize_t); /* release rsved quota for delayed alloc */ void (*release_rsv) (struct inode *, qsize_t); - /* get reserved quota for delayed alloc */ - qsize_t (*get_reserved_space) (struct inode *); + /* get reserved quota for delayed alloc, value returned is managed by + * quota code only */ + qsize_t *(*get_reserved_space) (struct inode *); }; /* Operations handling requests from userspace */ From dbe5cc0045fafc8fc452fa90dba93ad957494e14 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Mon, 14 Dec 2009 15:21:14 +0300 Subject: [PATCH 268/670] ext4: Convert to generic reserved quota's space management. commit a9e7f4472075fb6937c545af3f6329e9946bbe66 upstream. This patch also fixes write vs chown race condition. Acked-by: "Theodore Ts'o" Signed-off-by: Dmitry Monakhov Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/ext4/ext4.h | 6 +++++- fs/ext4/inode.c | 16 +++++++--------- fs/ext4/super.c | 5 +++++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index bd2a9dd1464c..d0a2afbab009 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -698,6 +698,10 @@ struct ext4_inode_info { __u16 i_extra_isize; spinlock_t i_block_reservation_lock; +#ifdef CONFIG_QUOTA + /* quota space reservation, managed internally by quota code */ + qsize_t i_reserved_quota; +#endif /* completed async DIOs that might need unwritten extents handling */ struct list_head i_aio_dio_complete_list; @@ -1432,7 +1436,7 @@ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); extern int ext4_block_truncate_page(handle_t *handle, struct address_space *mapping, loff_t from); extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); -extern qsize_t ext4_get_reserved_space(struct inode *inode); +extern qsize_t *ext4_get_reserved_space(struct inode *inode); extern int flush_aio_dio_completed_IO(struct inode *inode); /* ioctl.c */ extern long ext4_ioctl(struct file *, unsigned int, unsigned long); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 1dae9a4dbb03..374d38cdb21c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1045,17 +1045,12 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, return err; } -qsize_t ext4_get_reserved_space(struct inode *inode) +#ifdef CONFIG_QUOTA +qsize_t *ext4_get_reserved_space(struct inode *inode) { - unsigned long long total; - - spin_lock(&EXT4_I(inode)->i_block_reservation_lock); - total = EXT4_I(inode)->i_reserved_data_blocks + - EXT4_I(inode)->i_reserved_meta_blocks; - spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); - - return (total << inode->i_blkbits); + return &EXT4_I(inode)->i_reserved_quota; } +#endif /* * Calculate the number of metadata blocks need to reserve * to allocate @blocks for non extent file based file @@ -4850,6 +4845,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; inode->i_size = ext4_isize(raw_inode); ei->i_disksize = inode->i_size; +#ifdef CONFIG_QUOTA + ei->i_reserved_quota = 0; +#endif inode->i_generation = le32_to_cpu(raw_inode->i_generation); ei->i_block_group = iloc.block_group; ei->i_last_alloc_group = ~0; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 9ae521749b90..92943f2ca2ab 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -704,6 +704,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) ei->i_allocated_meta_blocks = 0; ei->i_delalloc_reserved_flag = 0; spin_lock_init(&(ei->i_block_reservation_lock)); +#ifdef CONFIG_QUOTA + ei->i_reserved_quota = 0; +#endif INIT_LIST_HEAD(&ei->i_aio_dio_complete_list); ei->cur_aio_dio = NULL; ei->i_sync_tid = 0; @@ -1001,7 +1004,9 @@ static const struct dquot_operations ext4_quota_operations = { .reserve_space = dquot_reserve_space, .claim_space = dquot_claim_space, .release_rsv = dquot_release_reserved_space, +#ifdef CONFIG_QUOTA .get_reserved_space = ext4_get_reserved_space, +#endif .alloc_inode = dquot_alloc_inode, .free_space = dquot_free_space, .free_inode = dquot_free_inode, From b2dbc4634227483a44732e73801b804915f04969 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Thu, 10 Dec 2009 16:36:27 +0000 Subject: [PATCH 269/670] ext4: fix sleep inside spinlock issue with quota and dealloc (#14739) commit 39bc680a8160bb9d6743f7873b535d553ff61058 upstream. Unlock i_block_reservation_lock before vfs_dq_reserve_block(). This patch fixes http://bugzilla.kernel.org/show_bug.cgi?id=14739 Cc: Theodore Ts'o Signed-off-by: Dmitry Monakhov Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 374d38cdb21c..e233879ebbcb 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1853,19 +1853,17 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks) md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks; total = md_needed + nrblocks; + spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); /* * Make quota reservation here to prevent quota overflow * later. Real quota accounting is done at pages writeout * time. */ - if (vfs_dq_reserve_block(inode, total)) { - spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); + if (vfs_dq_reserve_block(inode, total)) return -EDQUOT; - } if (ext4_claim_free_blocks(sbi, total)) { - spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); vfs_dq_release_reservation_block(inode, total); if (ext4_should_retry_alloc(inode->i_sb, &retries)) { yield(); @@ -1873,10 +1871,11 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks) } return -ENOSPC; } + spin_lock(&EXT4_I(inode)->i_block_reservation_lock); EXT4_I(inode)->i_reserved_data_blocks += nrblocks; - EXT4_I(inode)->i_reserved_meta_blocks = mdblocks; - + EXT4_I(inode)->i_reserved_meta_blocks += md_needed; spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); + return 0; /* success */ } From a89a9e1d729d7f1bc0d18bea800087bdfcfe4957 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 30 Jul 2009 11:10:02 +0200 Subject: [PATCH 270/670] x86, msr: Unify rdmsr_on_cpus/wrmsr_on_cpus commit b8a4754147d61f5359a765a3afd3eb03012aa052 upstream. Since rdmsr_on_cpus and wrmsr_on_cpus are almost identical, unify them into a common __rwmsr_on_cpus helper thus avoiding code duplication. While at it, convert cpumask_t's to const struct cpumask *. Signed-off-by: Borislav Petkov Signed-off-by: H. Peter Anvin Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/msr.h | 4 ++-- arch/x86/lib/msr.c | 46 ++++++++++++++++---------------------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 7e2b6ba962ff..9a00219b331a 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -247,8 +247,8 @@ do { \ #ifdef CONFIG_SMP int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); -void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs); -void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs); +void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); +void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c index 33a1e3ca22d8..41628b104b9e 100644 --- a/arch/x86/lib/msr.c +++ b/arch/x86/lib/msr.c @@ -71,14 +71,9 @@ int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) } EXPORT_SYMBOL(wrmsr_on_cpu); -/* rdmsr on a bunch of CPUs - * - * @mask: which CPUs - * @msr_no: which MSR - * @msrs: array of MSR values - * - */ -void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs) +static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no, + struct msr *msrs, + void (*msr_func) (void *info)) { struct msr_info rv; int this_cpu; @@ -92,11 +87,23 @@ void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs) this_cpu = get_cpu(); if (cpumask_test_cpu(this_cpu, mask)) - __rdmsr_on_cpu(&rv); + msr_func(&rv); - smp_call_function_many(mask, __rdmsr_on_cpu, &rv, 1); + smp_call_function_many(mask, msr_func, &rv, 1); put_cpu(); } + +/* rdmsr on a bunch of CPUs + * + * @mask: which CPUs + * @msr_no: which MSR + * @msrs: array of MSR values + * + */ +void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) +{ + __rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu); +} EXPORT_SYMBOL(rdmsr_on_cpus); /* @@ -107,24 +114,9 @@ EXPORT_SYMBOL(rdmsr_on_cpus); * @msrs: array of MSR values * */ -void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs) +void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) { - struct msr_info rv; - int this_cpu; - - memset(&rv, 0, sizeof(rv)); - - rv.off = cpumask_first(mask); - rv.msrs = msrs; - rv.msr_no = msr_no; - - this_cpu = get_cpu(); - - if (cpumask_test_cpu(this_cpu, mask)) - __wrmsr_on_cpu(&rv); - - smp_call_function_many(mask, __wrmsr_on_cpu, &rv, 1); - put_cpu(); + __rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu); } EXPORT_SYMBOL(wrmsr_on_cpus); From ebd2802865c7ea5f352fd5444c293d013e528922 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 3 Nov 2009 14:56:35 +1030 Subject: [PATCH 271/670] cpumask: use modern cpumask style in drivers/edac/amd64_edac.c commit ba578cb34a71fb08fff14ac0796b934a8c9991e1 upstream. cpumask_t -> struct cpumask, and don't put one on the stack. (Note: this is actually on the stack unless CONFIG_CPUMASK_OFFSTACK=y). Signed-off-by: Rusty Russell Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index a38831c82649..56deaee1eee3 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2625,7 +2625,7 @@ static int amd64_init_csrows(struct mem_ctl_info *mci) static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) { struct amd64_pvt *pvt = mci->pvt_info; - const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id); + const struct cpumask *cpumask = cpumask_of_node(pvt->mc_node_id); int cpu, idx = 0, err = 0; struct msr msrs[cpumask_weight(cpumask)]; u32 value; @@ -2701,7 +2701,7 @@ static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) { - const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id); + const struct cpumask *cpumask = cpumask_of_node(pvt->mc_node_id); int cpu, idx = 0, err = 0; struct msr msrs[cpumask_weight(cpumask)]; u32 value; @@ -2734,7 +2734,7 @@ static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) } /* get all cores on this DCT */ -static void get_cpus_on_this_dct_cpumask(cpumask_t *mask, int nid) +static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, int nid) { int cpu; @@ -2746,25 +2746,30 @@ static void get_cpus_on_this_dct_cpumask(cpumask_t *mask, int nid) /* check MCG_CTL on all the cpus on this node */ static bool amd64_nb_mce_bank_enabled_on_node(int nid) { - cpumask_t mask; + cpumask_var_t mask; struct msr *msrs; int cpu, nbe, idx = 0; bool ret = false; - cpumask_clear(&mask); + if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { + amd64_printk(KERN_WARNING, "%s: error allocating mask\n", + __func__); + return false; + } - get_cpus_on_this_dct_cpumask(&mask, nid); + get_cpus_on_this_dct_cpumask(mask, nid); - msrs = kzalloc(sizeof(struct msr) * cpumask_weight(&mask), GFP_KERNEL); + msrs = kzalloc(sizeof(struct msr) * cpumask_weight(mask), GFP_KERNEL); if (!msrs) { amd64_printk(KERN_WARNING, "%s: error allocating msrs\n", __func__); + free_cpumask_var(mask); return false; } - rdmsr_on_cpus(&mask, MSR_IA32_MCG_CTL, msrs); + rdmsr_on_cpus(mask, MSR_IA32_MCG_CTL, msrs); - for_each_cpu(cpu, &mask) { + for_each_cpu(cpu, mask) { nbe = msrs[idx].l & K8_MSR_MCGCTL_NBE; debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", @@ -2780,6 +2785,7 @@ static bool amd64_nb_mce_bank_enabled_on_node(int nid) out: kfree(msrs); + free_cpumask_var(mask); return ret; } From 26eb2ac67f9296d5b66533e55e9a28a2edd05b48 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 3 Nov 2009 15:29:26 +0100 Subject: [PATCH 272/670] amd64_edac: unify MCGCTL ECC switching commit f6d6ae965760906d79ab29bc38507608c5971549 upstream. Unify almost identical code into one function and remove NUMA-specific usage (specifically cpumask_of_node()) in favor of generic topology methods. Remove unused defines, while at it. Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 254 +++++++++++++++++++++----------------- drivers/edac/amd64_edac.h | 9 +- 2 files changed, 142 insertions(+), 121 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 56deaee1eee3..6ee408ff8479 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2618,121 +2618,6 @@ static int amd64_init_csrows(struct mem_ctl_info *mci) return empty; } -/* - * Only if 'ecc_enable_override' is set AND BIOS had ECC disabled, do "we" - * enable it. - */ -static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) -{ - struct amd64_pvt *pvt = mci->pvt_info; - const struct cpumask *cpumask = cpumask_of_node(pvt->mc_node_id); - int cpu, idx = 0, err = 0; - struct msr msrs[cpumask_weight(cpumask)]; - u32 value; - u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; - - if (!ecc_enable_override) - return; - - memset(msrs, 0, sizeof(msrs)); - - amd64_printk(KERN_WARNING, - "'ecc_enable_override' parameter is active, " - "Enabling AMD ECC hardware now: CAUTION\n"); - - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value); - if (err) - debugf0("Reading K8_NBCTL failed\n"); - - /* turn on UECCn and CECCEn bits */ - pvt->old_nbctl = value & mask; - pvt->nbctl_mcgctl_saved = 1; - - value |= mask; - pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); - - rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); - - for_each_cpu(cpu, cpumask) { - if (msrs[idx].l & K8_MSR_MCGCTL_NBE) - set_bit(idx, &pvt->old_mcgctl); - - msrs[idx].l |= K8_MSR_MCGCTL_NBE; - idx++; - } - wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); - - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); - if (err) - debugf0("Reading K8_NBCFG failed\n"); - - debugf0("NBCFG(1)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, - (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", - (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); - - if (!(value & K8_NBCFG_ECC_ENABLE)) { - amd64_printk(KERN_WARNING, - "This node reports that DRAM ECC is " - "currently Disabled; ENABLING now\n"); - - /* Attempt to turn on DRAM ECC Enable */ - value |= K8_NBCFG_ECC_ENABLE; - pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value); - - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); - if (err) - debugf0("Reading K8_NBCFG failed\n"); - - if (!(value & K8_NBCFG_ECC_ENABLE)) { - amd64_printk(KERN_WARNING, - "Hardware rejects Enabling DRAM ECC checking\n" - "Check memory DIMM configuration\n"); - } else { - amd64_printk(KERN_DEBUG, - "Hardware accepted DRAM ECC Enable\n"); - } - } - debugf0("NBCFG(2)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, - (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", - (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); - - pvt->ctl_error_info.nbcfg = value; -} - -static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) -{ - const struct cpumask *cpumask = cpumask_of_node(pvt->mc_node_id); - int cpu, idx = 0, err = 0; - struct msr msrs[cpumask_weight(cpumask)]; - u32 value; - u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; - - if (!pvt->nbctl_mcgctl_saved) - return; - - memset(msrs, 0, sizeof(msrs)); - - err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value); - if (err) - debugf0("Reading K8_NBCTL failed\n"); - value &= ~mask; - value |= pvt->old_nbctl; - - /* restore the NB Enable MCGCTL bit */ - pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); - - rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); - - for_each_cpu(cpu, cpumask) { - msrs[idx].l &= ~K8_MSR_MCGCTL_NBE; - msrs[idx].l |= - test_bit(idx, &pvt->old_mcgctl) << K8_MSR_MCGCTL_NBE; - idx++; - } - - wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); -} - /* get all cores on this DCT */ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, int nid) { @@ -2789,6 +2674,144 @@ static bool amd64_nb_mce_bank_enabled_on_node(int nid) return ret; } +static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) +{ + cpumask_var_t cmask; + struct msr *msrs = NULL; + int cpu, idx = 0; + + if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) { + amd64_printk(KERN_WARNING, "%s: error allocating mask\n", + __func__); + return false; + } + + get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id); + + msrs = kzalloc(sizeof(struct msr) * cpumask_weight(cmask), GFP_KERNEL); + if (!msrs) { + amd64_printk(KERN_WARNING, "%s: error allocating msrs\n", + __func__); + return -ENOMEM; + } + + rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); + + for_each_cpu(cpu, cmask) { + + if (on) { + if (msrs[idx].l & K8_MSR_MCGCTL_NBE) + pvt->flags.ecc_report = 1; + + msrs[idx].l |= K8_MSR_MCGCTL_NBE; + } else { + /* + * Turn off ECC reporting only when it was off before + */ + if (!pvt->flags.ecc_report) + msrs[idx].l &= ~K8_MSR_MCGCTL_NBE; + } + idx++; + } + wrmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); + + kfree(msrs); + free_cpumask_var(cmask); + + return 0; +} + +/* + * Only if 'ecc_enable_override' is set AND BIOS had ECC disabled, do "we" + * enable it. + */ +static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) +{ + struct amd64_pvt *pvt = mci->pvt_info; + int err = 0; + u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; + + if (!ecc_enable_override) + return; + + amd64_printk(KERN_WARNING, + "'ecc_enable_override' parameter is active, " + "Enabling AMD ECC hardware now: CAUTION\n"); + + err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value); + if (err) + debugf0("Reading K8_NBCTL failed\n"); + + /* turn on UECCn and CECCEn bits */ + pvt->old_nbctl = value & mask; + pvt->nbctl_mcgctl_saved = 1; + + value |= mask; + pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); + + if (amd64_toggle_ecc_err_reporting(pvt, ON)) + amd64_printk(KERN_WARNING, "Error enabling ECC reporting over " + "MCGCTL!\n"); + + err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); + if (err) + debugf0("Reading K8_NBCFG failed\n"); + + debugf0("NBCFG(1)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, + (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", + (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); + + if (!(value & K8_NBCFG_ECC_ENABLE)) { + amd64_printk(KERN_WARNING, + "This node reports that DRAM ECC is " + "currently Disabled; ENABLING now\n"); + + /* Attempt to turn on DRAM ECC Enable */ + value |= K8_NBCFG_ECC_ENABLE; + pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value); + + err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); + if (err) + debugf0("Reading K8_NBCFG failed\n"); + + if (!(value & K8_NBCFG_ECC_ENABLE)) { + amd64_printk(KERN_WARNING, + "Hardware rejects Enabling DRAM ECC checking\n" + "Check memory DIMM configuration\n"); + } else { + amd64_printk(KERN_DEBUG, + "Hardware accepted DRAM ECC Enable\n"); + } + } + debugf0("NBCFG(2)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, + (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", + (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); + + pvt->ctl_error_info.nbcfg = value; +} + +static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) +{ + int err = 0; + u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; + + if (!pvt->nbctl_mcgctl_saved) + return; + + err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value); + if (err) + debugf0("Reading K8_NBCTL failed\n"); + value &= ~mask; + value |= pvt->old_nbctl; + + /* restore the NB Enable MCGCTL bit */ + pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); + + if (amd64_toggle_ecc_err_reporting(pvt, OFF)) + amd64_printk(KERN_WARNING, "Error restoring ECC reporting over " + "MCGCTL!\n"); +} + /* * EDAC requires that the BIOS have ECC enabled before taking over the * processing of ECC errors. This is because the BIOS can properly initialize @@ -2915,7 +2938,6 @@ static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl, pvt->ext_model = boot_cpu_data.x86_model >> 4; pvt->mc_type_index = mc_type_index; pvt->ops = family_ops(mc_type_index); - pvt->old_mcgctl = 0; /* * We have the dram_f2_ctl device as an argument, now go reserve its diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index c6f359a85207..bba6c944ff13 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -147,6 +147,8 @@ #define MAX_CS_COUNT 8 #define DRAM_REG_COUNT 8 +#define ON true +#define OFF false /* * PCI-defined configuration space registers @@ -386,10 +388,7 @@ enum { #define K8_NBCAP_DUAL_NODE BIT(1) #define K8_NBCAP_DCT_DUAL BIT(0) -/* - * MSR Regs - */ -#define K8_MSR_MCGCTL 0x017b +/* MSRs */ #define K8_MSR_MCGCTL_NBE BIT(4) #define K8_MSR_MC4CTL 0x0410 @@ -487,7 +486,6 @@ struct amd64_pvt { /* Save old hw registers' values before we modified them */ u32 nbctl_mcgctl_saved; /* When true, following 2 are valid */ u32 old_nbctl; - unsigned long old_mcgctl; /* per core on this node */ /* MC Type Index value: socket F vs Family 10h */ u32 mc_type_index; @@ -495,6 +493,7 @@ struct amd64_pvt { /* misc settings */ struct flags { unsigned long cf8_extcfg:1; + unsigned long ecc_report:1; } flags; }; From eb21839600f406f76a63e6da241db7f361f7ff52 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 11 Dec 2009 18:14:40 +0100 Subject: [PATCH 273/670] x86, msr: Add support for non-contiguous cpumasks commit 505422517d3f126bb939439e9d15dece94e11d2c upstream. The current rd/wrmsr_on_cpus helpers assume that the supplied cpumasks are contiguous. However, there are machines out there like some K8 multinode Opterons which have a non-contiguous core enumeration on each node (e.g. cores 0,2 on node 0 instead of 0,1), see http://www.gossamer-threads.com/lists/linux/kernel/1160268. This patch fixes out-of-bounds writes (see URL above) by adding per-CPU msr structs which are used on the respective cores. Additionally, two helpers, msrs_{alloc,free}, are provided for use by the callers of the MSR accessors. Cc: H. Peter Anvin Cc: Mauro Carvalho Chehab Cc: Aristeu Rozanski Cc: Randy Dunlap Cc: Doug Thompson Signed-off-by: Borislav Petkov LKML-Reference: <20091211171440.GD31998@aftab> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/msr.h | 3 +++ arch/x86/lib/msr.c | 26 +++++++++++++++++---- drivers/edac/amd64_edac.c | 46 ++++++++++++++------------------------ 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 9a00219b331a..bb30776d42bf 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -244,6 +244,9 @@ do { \ #define write_rdtscp_aux(val) wrmsr(0xc0000103, (val), 0) +struct msr *msrs_alloc(void); +void msrs_free(struct msr *msrs); + #ifdef CONFIG_SMP int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c index 41628b104b9e..872834177937 100644 --- a/arch/x86/lib/msr.c +++ b/arch/x86/lib/msr.c @@ -7,7 +7,6 @@ struct msr_info { u32 msr_no; struct msr reg; struct msr *msrs; - int off; int err; }; @@ -18,7 +17,7 @@ static void __rdmsr_on_cpu(void *info) int this_cpu = raw_smp_processor_id(); if (rv->msrs) - reg = &rv->msrs[this_cpu - rv->off]; + reg = per_cpu_ptr(rv->msrs, this_cpu); else reg = &rv->reg; @@ -32,7 +31,7 @@ static void __wrmsr_on_cpu(void *info) int this_cpu = raw_smp_processor_id(); if (rv->msrs) - reg = &rv->msrs[this_cpu - rv->off]; + reg = per_cpu_ptr(rv->msrs, this_cpu); else reg = &rv->reg; @@ -80,7 +79,6 @@ static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no, memset(&rv, 0, sizeof(rv)); - rv.off = cpumask_first(mask); rv.msrs = msrs; rv.msr_no = msr_no; @@ -120,6 +118,26 @@ void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) } EXPORT_SYMBOL(wrmsr_on_cpus); +struct msr *msrs_alloc(void) +{ + struct msr *msrs = NULL; + + msrs = alloc_percpu(struct msr); + if (!msrs) { + pr_warning("%s: error allocating msrs\n", __func__); + return NULL; + } + + return msrs; +} +EXPORT_SYMBOL(msrs_alloc); + +void msrs_free(struct msr *msrs) +{ + free_percpu(msrs); +} +EXPORT_SYMBOL(msrs_free); + /* These "safe" variants are slower and should be used when the target MSR may not actually exist. */ static void __rdmsr_safe_on_cpu(void *info) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 6ee408ff8479..d2715096217a 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -13,6 +13,8 @@ module_param(report_gart_errors, int, 0644); static int ecc_enable_override; module_param(ecc_enable_override, int, 0644); +static struct msr *msrs; + /* Lookup table for all possible MC control instances */ struct amd64_pvt; static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES]; @@ -2632,8 +2634,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, int nid) static bool amd64_nb_mce_bank_enabled_on_node(int nid) { cpumask_var_t mask; - struct msr *msrs; - int cpu, nbe, idx = 0; + int cpu, nbe; bool ret = false; if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { @@ -2644,32 +2645,22 @@ static bool amd64_nb_mce_bank_enabled_on_node(int nid) get_cpus_on_this_dct_cpumask(mask, nid); - msrs = kzalloc(sizeof(struct msr) * cpumask_weight(mask), GFP_KERNEL); - if (!msrs) { - amd64_printk(KERN_WARNING, "%s: error allocating msrs\n", - __func__); - free_cpumask_var(mask); - return false; - } - rdmsr_on_cpus(mask, MSR_IA32_MCG_CTL, msrs); for_each_cpu(cpu, mask) { - nbe = msrs[idx].l & K8_MSR_MCGCTL_NBE; + struct msr *reg = per_cpu_ptr(msrs, cpu); + nbe = reg->l & K8_MSR_MCGCTL_NBE; debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", - cpu, msrs[idx].q, + cpu, reg->q, (nbe ? "enabled" : "disabled")); if (!nbe) goto out; - - idx++; } ret = true; out: - kfree(msrs); free_cpumask_var(mask); return ret; } @@ -2677,8 +2668,7 @@ static bool amd64_nb_mce_bank_enabled_on_node(int nid) static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) { cpumask_var_t cmask; - struct msr *msrs = NULL; - int cpu, idx = 0; + int cpu; if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) { amd64_printk(KERN_WARNING, "%s: error allocating mask\n", @@ -2688,34 +2678,27 @@ static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id); - msrs = kzalloc(sizeof(struct msr) * cpumask_weight(cmask), GFP_KERNEL); - if (!msrs) { - amd64_printk(KERN_WARNING, "%s: error allocating msrs\n", - __func__); - return -ENOMEM; - } - rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); for_each_cpu(cpu, cmask) { + struct msr *reg = per_cpu_ptr(msrs, cpu); + if (on) { - if (msrs[idx].l & K8_MSR_MCGCTL_NBE) + if (reg->l & K8_MSR_MCGCTL_NBE) pvt->flags.ecc_report = 1; - msrs[idx].l |= K8_MSR_MCGCTL_NBE; + reg->l |= K8_MSR_MCGCTL_NBE; } else { /* * Turn off ECC reporting only when it was off before */ if (!pvt->flags.ecc_report) - msrs[idx].l &= ~K8_MSR_MCGCTL_NBE; + reg->l &= ~K8_MSR_MCGCTL_NBE; } - idx++; } wrmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); - kfree(msrs); free_cpumask_var(cmask); return 0; @@ -3193,6 +3176,8 @@ static int __init amd64_edac_init(void) if (cache_k8_northbridges() < 0) return err; + msrs = msrs_alloc(); + err = pci_register_driver(&amd64_pci_driver); if (err) return err; @@ -3228,6 +3213,9 @@ static void __exit amd64_edac_exit(void) edac_pci_release_generic_ctl(amd64_ctl_pci); pci_unregister_driver(&amd64_pci_driver); + + msrs_free(msrs); + msrs = NULL; } module_init(amd64_edac_init); From 2d9e1f02c8fec8e339eddf6c92e836c18525d328 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 17 Dec 2009 00:16:25 +0100 Subject: [PATCH 274/670] x86, msr: msrs_alloc/free for CONFIG_SMP=n commit 6ede31e03084ee084bcee073ef3d1136f68d0906 upstream. Randy Dunlap reported the following build error: "When CONFIG_SMP=n, CONFIG_X86_MSR=m: ERROR: "msrs_free" [drivers/edac/amd64_edac_mod.ko] undefined! ERROR: "msrs_alloc" [drivers/edac/amd64_edac_mod.ko] undefined!" This is due to the fact that is conditioned on CONFIG_SMP and in the UP case we have only the stubs in the header. Fork off SMP functionality into a new file (msr-smp.c) and build msrs_{alloc,free} unconditionally. Reported-by: Randy Dunlap Cc: H. Peter Anvin Signed-off-by: Borislav Petkov LKML-Reference: <20091216231625.GD27228@liondog.tnic> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/msr.h | 12 +++ arch/x86/lib/Makefile | 4 +- arch/x86/lib/msr-smp.c | 204 +++++++++++++++++++++++++++++++++++ arch/x86/lib/msr.c | 213 ------------------------------------- 4 files changed, 218 insertions(+), 215 deletions(-) create mode 100644 arch/x86/lib/msr-smp.c diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index bb30776d42bf..0e3e728a23f6 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -27,6 +27,18 @@ struct msr { }; }; +struct msr_info { + u32 msr_no; + struct msr reg; + struct msr *msrs; + int err; +}; + +struct msr_regs_info { + u32 *regs; + int err; +}; + static inline unsigned long long native_read_tscp(unsigned int *aux) { unsigned long low, high; diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 85f5db95c60f..c2b6f395a022 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -2,14 +2,14 @@ # Makefile for x86 specific library files. # -obj-$(CONFIG_SMP) := msr.o +obj-$(CONFIG_SMP) += msr-smp.o lib-y := delay.o lib-y += thunk_$(BITS).o lib-y += usercopy_$(BITS).o getuser.o putuser.o lib-y += memcpy_$(BITS).o -obj-y += msr-reg.o msr-reg-export.o +obj-y += msr.o msr-reg.o msr-reg-export.o ifeq ($(CONFIG_X86_32),y) obj-y += atomic64_32.o diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c new file mode 100644 index 000000000000..a6b1b86d2253 --- /dev/null +++ b/arch/x86/lib/msr-smp.c @@ -0,0 +1,204 @@ +#include +#include +#include +#include + +static void __rdmsr_on_cpu(void *info) +{ + struct msr_info *rv = info; + struct msr *reg; + int this_cpu = raw_smp_processor_id(); + + if (rv->msrs) + reg = per_cpu_ptr(rv->msrs, this_cpu); + else + reg = &rv->reg; + + rdmsr(rv->msr_no, reg->l, reg->h); +} + +static void __wrmsr_on_cpu(void *info) +{ + struct msr_info *rv = info; + struct msr *reg; + int this_cpu = raw_smp_processor_id(); + + if (rv->msrs) + reg = per_cpu_ptr(rv->msrs, this_cpu); + else + reg = &rv->reg; + + wrmsr(rv->msr_no, reg->l, reg->h); +} + +int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) +{ + int err; + struct msr_info rv; + + memset(&rv, 0, sizeof(rv)); + + rv.msr_no = msr_no; + err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); + *l = rv.reg.l; + *h = rv.reg.h; + + return err; +} +EXPORT_SYMBOL(rdmsr_on_cpu); + +int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +{ + int err; + struct msr_info rv; + + memset(&rv, 0, sizeof(rv)); + + rv.msr_no = msr_no; + rv.reg.l = l; + rv.reg.h = h; + err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); + + return err; +} +EXPORT_SYMBOL(wrmsr_on_cpu); + +static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no, + struct msr *msrs, + void (*msr_func) (void *info)) +{ + struct msr_info rv; + int this_cpu; + + memset(&rv, 0, sizeof(rv)); + + rv.msrs = msrs; + rv.msr_no = msr_no; + + this_cpu = get_cpu(); + + if (cpumask_test_cpu(this_cpu, mask)) + msr_func(&rv); + + smp_call_function_many(mask, msr_func, &rv, 1); + put_cpu(); +} + +/* rdmsr on a bunch of CPUs + * + * @mask: which CPUs + * @msr_no: which MSR + * @msrs: array of MSR values + * + */ +void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) +{ + __rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu); +} +EXPORT_SYMBOL(rdmsr_on_cpus); + +/* + * wrmsr on a bunch of CPUs + * + * @mask: which CPUs + * @msr_no: which MSR + * @msrs: array of MSR values + * + */ +void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) +{ + __rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu); +} +EXPORT_SYMBOL(wrmsr_on_cpus); + +/* These "safe" variants are slower and should be used when the target MSR + may not actually exist. */ +static void __rdmsr_safe_on_cpu(void *info) +{ + struct msr_info *rv = info; + + rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h); +} + +static void __wrmsr_safe_on_cpu(void *info) +{ + struct msr_info *rv = info; + + rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h); +} + +int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) +{ + int err; + struct msr_info rv; + + memset(&rv, 0, sizeof(rv)); + + rv.msr_no = msr_no; + err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1); + *l = rv.reg.l; + *h = rv.reg.h; + + return err ? err : rv.err; +} +EXPORT_SYMBOL(rdmsr_safe_on_cpu); + +int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +{ + int err; + struct msr_info rv; + + memset(&rv, 0, sizeof(rv)); + + rv.msr_no = msr_no; + rv.reg.l = l; + rv.reg.h = h; + err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1); + + return err ? err : rv.err; +} +EXPORT_SYMBOL(wrmsr_safe_on_cpu); + +/* + * These variants are significantly slower, but allows control over + * the entire 32-bit GPR set. + */ +static void __rdmsr_safe_regs_on_cpu(void *info) +{ + struct msr_regs_info *rv = info; + + rv->err = rdmsr_safe_regs(rv->regs); +} + +static void __wrmsr_safe_regs_on_cpu(void *info) +{ + struct msr_regs_info *rv = info; + + rv->err = wrmsr_safe_regs(rv->regs); +} + +int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs) +{ + int err; + struct msr_regs_info rv; + + rv.regs = regs; + rv.err = -EIO; + err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1); + + return err ? err : rv.err; +} +EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu); + +int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs) +{ + int err; + struct msr_regs_info rv; + + rv.regs = regs; + rv.err = -EIO; + err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1); + + return err ? err : rv.err; +} +EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu); diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c index 872834177937..8f8eebdca7d4 100644 --- a/arch/x86/lib/msr.c +++ b/arch/x86/lib/msr.c @@ -1,123 +1,7 @@ #include #include -#include #include -struct msr_info { - u32 msr_no; - struct msr reg; - struct msr *msrs; - int err; -}; - -static void __rdmsr_on_cpu(void *info) -{ - struct msr_info *rv = info; - struct msr *reg; - int this_cpu = raw_smp_processor_id(); - - if (rv->msrs) - reg = per_cpu_ptr(rv->msrs, this_cpu); - else - reg = &rv->reg; - - rdmsr(rv->msr_no, reg->l, reg->h); -} - -static void __wrmsr_on_cpu(void *info) -{ - struct msr_info *rv = info; - struct msr *reg; - int this_cpu = raw_smp_processor_id(); - - if (rv->msrs) - reg = per_cpu_ptr(rv->msrs, this_cpu); - else - reg = &rv->reg; - - wrmsr(rv->msr_no, reg->l, reg->h); -} - -int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) -{ - int err; - struct msr_info rv; - - memset(&rv, 0, sizeof(rv)); - - rv.msr_no = msr_no; - err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); - *l = rv.reg.l; - *h = rv.reg.h; - - return err; -} -EXPORT_SYMBOL(rdmsr_on_cpu); - -int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) -{ - int err; - struct msr_info rv; - - memset(&rv, 0, sizeof(rv)); - - rv.msr_no = msr_no; - rv.reg.l = l; - rv.reg.h = h; - err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); - - return err; -} -EXPORT_SYMBOL(wrmsr_on_cpu); - -static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no, - struct msr *msrs, - void (*msr_func) (void *info)) -{ - struct msr_info rv; - int this_cpu; - - memset(&rv, 0, sizeof(rv)); - - rv.msrs = msrs; - rv.msr_no = msr_no; - - this_cpu = get_cpu(); - - if (cpumask_test_cpu(this_cpu, mask)) - msr_func(&rv); - - smp_call_function_many(mask, msr_func, &rv, 1); - put_cpu(); -} - -/* rdmsr on a bunch of CPUs - * - * @mask: which CPUs - * @msr_no: which MSR - * @msrs: array of MSR values - * - */ -void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) -{ - __rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu); -} -EXPORT_SYMBOL(rdmsr_on_cpus); - -/* - * wrmsr on a bunch of CPUs - * - * @mask: which CPUs - * @msr_no: which MSR - * @msrs: array of MSR values - * - */ -void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs) -{ - __rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu); -} -EXPORT_SYMBOL(wrmsr_on_cpus); - struct msr *msrs_alloc(void) { struct msr *msrs = NULL; @@ -137,100 +21,3 @@ void msrs_free(struct msr *msrs) free_percpu(msrs); } EXPORT_SYMBOL(msrs_free); - -/* These "safe" variants are slower and should be used when the target MSR - may not actually exist. */ -static void __rdmsr_safe_on_cpu(void *info) -{ - struct msr_info *rv = info; - - rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h); -} - -static void __wrmsr_safe_on_cpu(void *info) -{ - struct msr_info *rv = info; - - rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h); -} - -int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) -{ - int err; - struct msr_info rv; - - memset(&rv, 0, sizeof(rv)); - - rv.msr_no = msr_no; - err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1); - *l = rv.reg.l; - *h = rv.reg.h; - - return err ? err : rv.err; -} -EXPORT_SYMBOL(rdmsr_safe_on_cpu); - -int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) -{ - int err; - struct msr_info rv; - - memset(&rv, 0, sizeof(rv)); - - rv.msr_no = msr_no; - rv.reg.l = l; - rv.reg.h = h; - err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1); - - return err ? err : rv.err; -} -EXPORT_SYMBOL(wrmsr_safe_on_cpu); - -/* - * These variants are significantly slower, but allows control over - * the entire 32-bit GPR set. - */ -struct msr_regs_info { - u32 *regs; - int err; -}; - -static void __rdmsr_safe_regs_on_cpu(void *info) -{ - struct msr_regs_info *rv = info; - - rv->err = rdmsr_safe_regs(rv->regs); -} - -static void __wrmsr_safe_regs_on_cpu(void *info) -{ - struct msr_regs_info *rv = info; - - rv->err = wrmsr_safe_regs(rv->regs); -} - -int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs) -{ - int err; - struct msr_regs_info rv; - - rv.regs = regs; - rv.err = -EIO; - err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1); - - return err ? err : rv.err; -} -EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu); - -int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs) -{ - int err; - struct msr_regs_info rv; - - rv.regs = regs; - rv.err = -EIO; - err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1); - - return err ? err : rv.err; -} -EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu); From 44a529c6b32a9254cacc0d0c6423967883d8ebcd Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 15:15:59 +0100 Subject: [PATCH 275/670] amd64_edac: fix driver instance freeing commit 8f68ed9728193b1f2fb53ba06031b06bd8b3d1b4 upstream. Fix use-after-free errors by pushing all memory-freeing calls to the end of amd64_remove_one_instance(). Reported-by: Darren Jenkins LKML-Reference: <1261370306.11354.52.camel@ICE-BOX> Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index d2715096217a..72d84d0dd97c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3082,16 +3082,15 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) amd64_free_mc_sibling_devices(pvt); - kfree(pvt); - mci->pvt_info = NULL; - - mci_lookup[pvt->mc_node_id] = NULL; - /* unregister from EDAC MCE */ amd_report_gart_errors(false); amd_unregister_ecc_decoder(amd64_decode_bus_error); /* Free the EDAC CORE resources */ + mci->pvt_info = NULL; + mci_lookup[pvt->mc_node_id] = NULL; + + kfree(pvt); edac_mc_free(mci); } From 15383230c0603460f1479610b3dc59e70dc73611 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 18:13:01 +0100 Subject: [PATCH 276/670] amd64_edac: make driver loading more robust commit 56b34b91e22313294154cee0c16e294cf8a45b61 upstream. Currently, the module does not initialize fully when the DIMMs aren't ECC but remains still loaded. Propagate the error when no instance of the driver is properly initialized and prevent further loading. Reorganize and polish error handling in amd64_edac_init() while at it. Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 72d84d0dd97c..22910c648343 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3167,25 +3167,29 @@ static void amd64_setup_pci_device(void) static int __init amd64_edac_init(void) { int nb, err = -ENODEV; + bool load_ok = false; edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n"); opstate_init(); if (cache_k8_northbridges() < 0) - return err; + goto err_ret; msrs = msrs_alloc(); + if (!msrs) + goto err_ret; err = pci_register_driver(&amd64_pci_driver); if (err) - return err; + goto err_pci; /* * At this point, the array 'pvt_lookup[]' contains pointers to alloc'd * amd64_pvt structs. These will be used in the 2nd stage init function * to finish initialization of the MC instances. */ + err = -ENODEV; for (nb = 0; nb < num_k8_northbridges; nb++) { if (!pvt_lookup[nb]) continue; @@ -3193,16 +3197,21 @@ static int __init amd64_edac_init(void) err = amd64_init_2nd_stage(pvt_lookup[nb]); if (err) goto err_2nd_stage; + + load_ok = true; } - amd64_setup_pci_device(); - - return 0; + if (load_ok) { + amd64_setup_pci_device(); + return 0; + } err_2nd_stage: - debugf0("2nd stage failed\n"); pci_unregister_driver(&amd64_pci_driver); - +err_pci: + msrs_free(msrs); + msrs = NULL; +err_ret: return err; } From 9127720087953642a8308b373a76f38916577f0e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 18:55:18 +0100 Subject: [PATCH 277/670] amd64_edac: fix forcing module load/unload commit 43f5e68733cfe8bed3c30b5c14c4993dffb29766 upstream. Clear the override flag after force-loading the module. Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 22910c648343..a0bcfba13d17 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2836,9 +2836,8 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) amd64_printk(KERN_WARNING, "%s", ecc_warning); return -ENODEV; } - } else - /* CLEAR the override, since BIOS controlled it */ ecc_enable_override = 0; + } return 0; } From fc310225dfa4d0ca5e8d1bfe66d49367d3e1d81a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 16 Nov 2009 10:28:09 +0100 Subject: [PATCH 278/670] sched: Sched_rt_periodic_timer vs cpu hotplug commit 047106adcc85e3023da210143a6ab8a55df9e0fc upstream. Heiko reported a case where a timer interrupt managed to reference a root_domain structure that was already freed by a concurrent hot-un-plug operation. Solve this like the regular sched_domain stuff is also synchronized, by adding a synchronize_sched() stmt to the free path, this ensures that a root_domain stays present for any atomic section that could have observed it. Reported-by: Heiko Carstens Signed-off-by: Peter Zijlstra Acked-by: Heiko Carstens Cc: Gregory Haskins Cc: Siddha Suresh B Cc: Martin Schwidefsky LKML-Reference: <1258363873.26714.83.camel@laptop> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/sched.c b/kernel/sched.c index 04144dbe9f22..dd0dccde5df0 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -7925,6 +7925,8 @@ sd_parent_degenerate(struct sched_domain *sd, struct sched_domain *parent) static void free_rootdomain(struct root_domain *rd) { + synchronize_sched(); + cpupri_cleanup(&rd->cpupri); free_cpumask_var(rd->rto_mask); From 743c078e0e10e41b8b10f3c07973068d76fcc866 Mon Sep 17 00:00:00 2001 From: Fang Wenqi Date: Thu, 24 Dec 2009 17:51:42 -0500 Subject: [PATCH 279/670] ext4: Update documentation to correct the inode_readahead_blks option name commit 6d3b82f2d31f22085e5711b28dddcb9fb3d97a25 upstream. Per commit 240799cd, the option name for readahead should be inode_readahead_blks, not inode_readahead. Signed-off-by: Fang Wenqi Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/ext4.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index af6885c3c821..e1def1786e50 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt @@ -196,7 +196,7 @@ nobarrier This also requires an IO stack which can support also be used to enable or disable barriers, for consistency with other ext4 mount options. -inode_readahead=n This tuning parameter controls the maximum +inode_readahead_blks=n This tuning parameter controls the maximum number of inode table blocks that ext4's inode table readahead algorithm will pre-read into the buffer cache. The default value is 32 blocks. From 370b7588553ff0dc89c8b9436a935e2b7fe0207d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 4 Jan 2010 19:26:14 +1030 Subject: [PATCH 280/670] lguest: fix bug in setting guest GDT entry commit 3e27249c84beed1c79d767b350e52ad038db9053 upstream. We kill the guest, but then we blatt random stuff. Reported-by: Dan Carpenter Signed-off-by: Rusty Russell Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/lguest/segments.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c index 951c57b0a7e0..ede46581351a 100644 --- a/drivers/lguest/segments.c +++ b/drivers/lguest/segments.c @@ -179,8 +179,10 @@ void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi) * We assume the Guest has the same number of GDT entries as the * Host, otherwise we'd have to dynamically allocate the Guest GDT. */ - if (num >= ARRAY_SIZE(cpu->arch.gdt)) + if (num >= ARRAY_SIZE(cpu->arch.gdt)) { kill_guest(cpu, "too many gdt entries %i", num); + return; + } /* Set it up, then fix it. */ cpu->arch.gdt[num].a = lo; From b2ea8cb9c8f1937cb80b9beb50548a05bfc37819 Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Mon, 14 Dec 2009 17:59:48 -0800 Subject: [PATCH 281/670] vmscan: do not evict inactive pages when skipping an active list scan commit b39415b2731d7dec5e612d2d12595da82399eedf upstream. In AIM7 runs, recent kernels start swapping out anonymous pages well before they should. This is due to shrink_list falling through to shrink_inactive_list if !inactive_anon_is_low(zone, sc), when all we really wanted to do is pre-age some anonymous pages to give them extra time to be referenced while on the inactive list. The obvious fix is to make sure that shrink_list does not fall through to scanning/reclaiming inactive pages when we called it to scan one of the active lists. This change should be safe because the loop in shrink_zone ensures that we will still shrink the anon and file inactive lists whenever we should. [kosaki.motohiro@jp.fujitsu.com: inactive_file_is_low() should be inactive_anon_is_low()] Reported-by: Larry Woodman Signed-off-by: Rik van Riel Acked-by: Johannes Weiner Cc: Tomasz Chmielewski Signed-off-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Rik Theys Signed-off-by: Greg Kroah-Hartman --- mm/vmscan.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 777af57fd8c8..692807f2228b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1464,20 +1464,26 @@ static int inactive_file_is_low(struct zone *zone, struct scan_control *sc) return low; } +static int inactive_list_is_low(struct zone *zone, struct scan_control *sc, + int file) +{ + if (file) + return inactive_file_is_low(zone, sc); + else + return inactive_anon_is_low(zone, sc); +} + static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan, struct zone *zone, struct scan_control *sc, int priority) { int file = is_file_lru(lru); - if (lru == LRU_ACTIVE_FILE && inactive_file_is_low(zone, sc)) { - shrink_active_list(nr_to_scan, zone, sc, priority, file); + if (is_active_lru(lru)) { + if (inactive_list_is_low(zone, sc, file)) + shrink_active_list(nr_to_scan, zone, sc, priority, file); return 0; } - if (lru == LRU_ACTIVE_ANON && inactive_anon_is_low(zone, sc)) { - shrink_active_list(nr_to_scan, zone, sc, priority, file); - return 0; - } return shrink_inactive_list(nr_to_scan, zone, sc, priority, file); } From 8ac9e802007e99534ec66af850ef7b099df27499 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 30 Dec 2009 23:00:30 +0000 Subject: [PATCH 282/670] ksm: fix mlockfreed to munlocked 2.6.33-rc1 commit 73848b4684e84a84cfd1555af78d41158f31e16b, adjusted to include 31e855ea7173bdb0520f9684580423a9560f66e0's movement of the unlock_page(oldpage), but omit other intervening cleanups. When KSM merges an mlocked page, it has been forgetting to munlock it: that's been left to free_page_mlock(), which reports it in /proc/vmstat as unevictable_pgs_mlockfreed instead of unevictable_pgs_munlocked, which indicates that such pages _might_ be left unevictable for long after they should be evictable. Call munlock_vma_page() to fix that. Signed-off-by: Hugh Dickins Signed-off-by: Greg Kroah-Hartman --- mm/internal.h | 3 ++- mm/ksm.c | 14 +++++++------- mm/mlock.c | 4 ++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/mm/internal.h b/mm/internal.h index 22ec8d2b0fb8..17bc0df273bb 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -107,9 +107,10 @@ static inline int is_mlocked_vma(struct vm_area_struct *vma, struct page *page) } /* - * must be called with vma's mmap_sem held for read, and page locked. + * must be called with vma's mmap_sem held for read or write, and page locked. */ extern void mlock_vma_page(struct page *page); +extern void munlock_vma_page(struct page *page); /* * Clear the page's PageMlocked(). This can be useful in a situation where diff --git a/mm/ksm.c b/mm/ksm.c index 5575f8628fef..e9501f833374 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -34,6 +34,7 @@ #include #include +#include "internal.h" /* * A few notes about the KSM scanning process, @@ -767,15 +768,14 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, * ptes are necessarily already write-protected. But in either * case, we need to lock and check page_count is not raised. */ - if (write_protect_page(vma, oldpage, &orig_pte)) { - unlock_page(oldpage); - goto out_putpage; - } - unlock_page(oldpage); - - if (pages_identical(oldpage, newpage)) + if (write_protect_page(vma, oldpage, &orig_pte) == 0 && + pages_identical(oldpage, newpage)) err = replace_page(vma, oldpage, newpage, orig_pte); + if ((vma->vm_flags & VM_LOCKED) && !err) + munlock_vma_page(oldpage); + + unlock_page(oldpage); out_putpage: put_page(oldpage); put_page(newpage); diff --git a/mm/mlock.c b/mm/mlock.c index bd6f0e466f6c..2e05c97b04f5 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -99,14 +99,14 @@ void mlock_vma_page(struct page *page) * not get another chance to clear PageMlocked. If we successfully * isolate the page and try_to_munlock() detects other VM_LOCKED vmas * mapping the page, it will restore the PageMlocked state, unless the page - * is mapped in a non-linear vma. So, we go ahead and SetPageMlocked(), + * is mapped in a non-linear vma. So, we go ahead and ClearPageMlocked(), * perhaps redundantly. * If we lose the isolation race, and the page is mapped by other VM_LOCKED * vmas, we'll detect this in vmscan--via try_to_munlock() or try_to_unmap() * either of which will restore the PageMlocked state by calling * mlock_vma_page() above, if it can grab the vma's mmap sem. */ -static void munlock_vma_page(struct page *page) +void munlock_vma_page(struct page *page) { BUG_ON(!PageLocked(page)); From 3815270b3107d31c8b7bd69461f0bb3c350ee25c Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 14 Dec 2009 20:33:55 +0100 Subject: [PATCH 283/670] rt2x00: Disable powersaving for rt61pci and rt2800pci. commit 93b6bd26b74efe46b4579592560f9f1cb7b61994 upstream. We've had many reports of rt61pci failures with powersaving enabled. Therefore, as a stop-gap measure, disable powersaving of the rt61pci until we have found a proper solution. Also disable powersaving on rt2800pci as it most probably will show the same problem. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt61pci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b20e3eac9d67..9a6ceb4e28d8 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2537,6 +2537,11 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) char *tx_power; unsigned int i; + /* + * Disable powersaving as default. + */ + rt2x00dev->hw->wiphy->ps_default = false; + /* * Initialize all hw fields. */ From 84d330ec80dc467baf6cb393d9c1ee006d1c024a Mon Sep 17 00:00:00 2001 From: "Serge E. Hallyn" Date: Tue, 29 Dec 2009 14:50:19 -0600 Subject: [PATCH 284/670] generic_permission: MAY_OPEN is not write access commit 7ea6600148c265b1fd53e521022b1d7aec81d974 upstream. generic_permission was refusing CAP_DAC_READ_SEARCH-enabled processes from opening DAC-protected files read-only, because do_filp_open adds MAY_OPEN to the open mask. Ignore MAY_OPEN. After this patch, CAP_DAC_READ_SEARCH is again sufficient to open(fname, O_RDONLY) on a file to which DAC otherwise refuses us read permission. Reported-by: Mike Kazantsev Signed-off-by: Serge E. Hallyn Tested-by: Mike Kazantsev Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/namei.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/namei.c b/fs/namei.c index d11f404667e9..a2b3c28a499d 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -234,6 +234,7 @@ int generic_permission(struct inode *inode, int mask, /* * Searching includes executable on directories, else just read. */ + mask &= MAY_READ | MAY_WRITE | MAY_EXEC; if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) if (capable(CAP_DAC_READ_SEARCH)) return 0; From c3a8e0eaafb438d5a7e6ca55c09b921291fcc1b1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 6 Jan 2010 15:07:45 -0800 Subject: [PATCH 285/670] Linux 2.6.32.3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 23803ce63eee..482dcddf7e5b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = .2 +EXTRAVERSION = .3 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* From 1f51eb3a881359e97dc2c228e55c83fba598e349 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 14 Jan 2010 11:39:39 -0800 Subject: [PATCH 286/670] untangle the do_mremap() mess This backports the following upstream commits all as one patch: 54f5de709984bae0d31d823ff03de755f9dcac54 ecc1a8993751de4e82eb18640d631dae1f626bd6 1a0ef85f84feb13f07b604fcf5b90ef7c2b5c82f f106af4e90eadd76cfc0b5325f659619e08fb762 097eed103862f9c6a97f2e415e21d1134017b135 935874141df839c706cd6cdc438e85eb69d1525e 0ec62d290912bb4b989be7563851bc364ec73b56 c4caa778157dbbf04116f0ac2111e389b5cd7a29 2ea1d13f64efdf49319e86c87d9ba38c30902782 570dcf2c15463842e384eb597a87c1e39bead99b 564b3bffc619dcbdd160de597b0547a7017ea010 0067bd8a55862ac9dd212bd1c4f6f5bff1ca1301 f8b7256096a20436f6d0926747e3ac3d64c81d24 8c7b49b3ecd48923eb64ff57e07a1cdb74782970 9206de95b1ea68357996ec02be5db0638a0de2c1 2c6a10161d0b5fc047b5bd81b03693b9af99fab5 05d72faa6d13c9d857478a5d35c85db9adada685 bb52d6694002b9d632bb355f64daa045c6293a4e e77414e0aad6a1b063ba5e5750c582c75327ea6a aa65607373a4daf2010e8c3867b6317619f3c1a3 Backport done by Greg Kroah-Hartman. Only minor tweaks were needed. Cc: David S. Miller Cc: Hugh Dickins Cc: Paul Mundt Cc: Russell King Cc: Linus Torvalds Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/osf_sys.c | 19 +- arch/arm/include/asm/mman.h | 3 + arch/arm/kernel/calls.S | 2 +- arch/arm/kernel/entry-common.S | 4 +- arch/arm/kernel/sys_arm.c | 55 +---- arch/arm/mm/mmap.c | 3 +- arch/avr32/include/asm/syscalls.h | 4 - arch/avr32/kernel/sys_avr32.c | 31 --- arch/avr32/kernel/syscall-stubs.S | 2 +- arch/blackfin/kernel/sys_bfin.c | 33 --- arch/blackfin/mach-common/entry.S | 2 +- arch/cris/kernel/sys_cris.c | 30 +-- arch/frv/kernel/sys_frv.c | 66 +----- arch/h8300/kernel/sys_h8300.c | 83 +------- arch/h8300/kernel/syscalls.S | 2 +- arch/ia64/ia32/sys_ia32.c | 3 + arch/ia64/kernel/sys_ia64.c | 83 +------- arch/m32r/kernel/sys_m32r.c | 24 --- arch/m32r/kernel/syscall_table.S | 2 +- arch/m68k/kernel/sys_m68k.c | 83 +------- arch/m68knommu/kernel/sys_m68k.c | 38 +--- arch/m68knommu/kernel/syscalltable.S | 2 +- arch/microblaze/kernel/sys_microblaze.c | 38 +--- arch/microblaze/kernel/syscall_table.S | 2 +- arch/mips/kernel/linux32.c | 19 +- arch/mips/kernel/syscall.c | 32 +-- arch/mn10300/include/asm/mman.h | 5 + arch/mn10300/kernel/entry.S | 2 +- arch/mn10300/kernel/sys_mn10300.c | 36 +--- arch/parisc/kernel/sys_parisc.c | 30 +-- arch/powerpc/kernel/syscalls.c | 15 +- arch/s390/kernel/compat_linux.c | 37 +--- arch/s390/kernel/sys_s390.c | 30 +-- arch/score/kernel/sys_score.c | 28 +-- arch/sh/kernel/sys_sh.c | 28 +-- arch/sh/mm/mmap.c | 3 +- arch/sparc/kernel/sys_sparc_32.c | 64 +----- arch/sparc/kernel/sys_sparc_64.c | 50 ++--- arch/sparc/kernel/systbls.h | 1 - arch/sparc/kernel/systbls_32.S | 4 +- arch/sparc/kernel/systbls_64.S | 4 +- arch/um/kernel/syscall.c | 28 +-- arch/um/sys-i386/shared/sysdep/syscalls.h | 4 - arch/x86/ia32/ia32entry.S | 2 +- arch/x86/ia32/sys_ia32.c | 43 +--- arch/x86/include/asm/sys_ia32.h | 3 - arch/x86/include/asm/syscalls.h | 2 - arch/x86/kernel/sys_i386_32.c | 27 +-- arch/x86/kernel/sys_x86_64.c | 17 +- arch/x86/kernel/syscall_table_32.S | 2 +- arch/xtensa/include/asm/syscall.h | 2 - arch/xtensa/include/asm/unistd.h | 2 +- arch/xtensa/kernel/syscall.c | 25 --- include/linux/syscalls.h | 4 + ipc/shm.c | 31 +-- mm/mmap.c | 42 +--- mm/mremap.c | 239 ++++++++++++++-------- mm/util.c | 44 ++++ 58 files changed, 341 insertions(+), 1178 deletions(-) diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 9a3334ae282e..62619f25132f 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -178,25 +178,18 @@ SYSCALL_DEFINE6(osf_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, off) { - struct file *file = NULL; - unsigned long ret = -EBADF; + unsigned long ret = -EINVAL; #if 0 if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED)) printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags); #endif - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); - ret = do_mmap(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); + if ((off + PAGE_ALIGN(len)) < off) + goto out; + if (off & ~PAGE_MASK) + goto out; + ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); out: return ret; } diff --git a/arch/arm/include/asm/mman.h b/arch/arm/include/asm/mman.h index 8eebf89f5ab1..41f99c573b93 100644 --- a/arch/arm/include/asm/mman.h +++ b/arch/arm/include/asm/mman.h @@ -1 +1,4 @@ #include + +#define arch_mmap_check(addr, len, flags) \ + (((flags) & MAP_FIXED && (addr) < FIRST_USER_ADDRESS) ? -EINVAL : 0) diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index fafce1b5c69f..4f07168cf33d 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -172,7 +172,7 @@ /* 160 */ CALL(sys_sched_get_priority_min) CALL(sys_sched_rr_get_interval) CALL(sys_nanosleep) - CALL(sys_arm_mremap) + CALL(sys_mremap) CALL(sys_setresuid16) /* 165 */ CALL(sys_getresuid16) CALL(sys_ni_syscall) /* vm86 */ diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index f0fe95b7085d..2c1db77d7848 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -416,12 +416,12 @@ sys_mmap2: tst r5, #PGOFF_MASK moveq r5, r5, lsr #PAGE_SHIFT - 12 streq r5, [sp, #4] - beq do_mmap2 + beq sys_mmap_pgoff mov r0, #-EINVAL mov pc, lr #else str r5, [sp, #4] - b do_mmap2 + b sys_mmap_pgoff #endif ENDPROC(sys_mmap2) diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 78ecaac65206..ae4027bd01bd 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -28,41 +28,6 @@ #include #include -extern unsigned long do_mremap(unsigned long addr, unsigned long old_len, - unsigned long new_len, unsigned long flags, - unsigned long new_addr); - -/* common code for old and new mmaps */ -inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EINVAL; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - if (flags & MAP_FIXED && addr < FIRST_USER_ADDRESS) - goto out; - - error = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - struct mmap_arg_struct { unsigned long addr; unsigned long len; @@ -84,29 +49,11 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) if (a.offset & ~PAGE_MASK) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return error; } -asmlinkage unsigned long -sys_arm_mremap(unsigned long addr, unsigned long old_len, - unsigned long new_len, unsigned long flags, - unsigned long new_addr) -{ - unsigned long ret = -EINVAL; - - if (flags & MREMAP_FIXED && new_addr < FIRST_USER_ADDRESS) - goto out; - - down_write(¤t->mm->mmap_sem); - ret = do_mremap(addr, old_len, new_len, flags, new_addr); - up_write(¤t->mm->mmap_sem); - -out: - return ret; -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 2b7996401b0f..f5abc51c5a07 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -54,7 +54,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, * We enforce the MAP_FIXED case. */ if (flags & MAP_FIXED) { - if (aliasing && flags & MAP_SHARED && addr & (SHMLBA - 1)) + if (aliasing && flags & MAP_SHARED && + (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)) return -EINVAL; return addr; } diff --git a/arch/avr32/include/asm/syscalls.h b/arch/avr32/include/asm/syscalls.h index 483d666c27c0..66a197266637 100644 --- a/arch/avr32/include/asm/syscalls.h +++ b/arch/avr32/include/asm/syscalls.h @@ -29,10 +29,6 @@ asmlinkage int sys_sigaltstack(const stack_t __user *, stack_t __user *, struct pt_regs *); asmlinkage int sys_rt_sigreturn(struct pt_regs *); -/* kernel/sys_avr32.c */ -asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, off_t); - /* mm/cache.c */ asmlinkage int sys_cacheflush(int, void __user *, size_t); diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c index 5d2daeaf356f..459349b5ed5a 100644 --- a/arch/avr32/kernel/sys_avr32.c +++ b/arch/avr32/kernel/sys_avr32.c @@ -5,39 +5,8 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include -#include -#include -#include #include -#include -#include -#include - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, off_t offset) -{ - int error = -EBADF; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return error; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, offset); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - return error; -} - int kernel_execve(const char *file, char **argv, char **envp) { register long scno asm("r8") = __NR_execve; diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S index f7244cd02fbb..0447a3e2ba64 100644 --- a/arch/avr32/kernel/syscall-stubs.S +++ b/arch/avr32/kernel/syscall-stubs.S @@ -61,7 +61,7 @@ __sys_execve: __sys_mmap2: pushm lr st.w --sp, ARG6 - call sys_mmap2 + call sys_mmap_pgoff sub sp, -4 popm pc diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c index afcef129d4e8..2e7f8e10bf87 100644 --- a/arch/blackfin/kernel/sys_bfin.c +++ b/arch/blackfin/kernel/sys_bfin.c @@ -22,39 +22,6 @@ #include #include -/* common code for old and new mmaps */ -static inline long -do_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - out: - return error; -} - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags) { return sram_alloc_with_lsl(size, flags); diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 94a0375cbdcf..1d8f00ab9ee9 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -1422,7 +1422,7 @@ ENTRY(_sys_call_table) .long _sys_ni_syscall /* streams2 */ .long _sys_vfork /* 190 */ .long _sys_getrlimit - .long _sys_mmap2 + .long _sys_mmap_pgoff .long _sys_truncate64 .long _sys_ftruncate64 .long _sys_stat64 /* 195 */ diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c index 2ad962c7e88e..c2bbb1ac98a9 100644 --- a/arch/cris/kernel/sys_cris.c +++ b/arch/cris/kernel/sys_cris.c @@ -26,31 +26,6 @@ #include #include -/* common code for old and new mmaps */ -static inline long -do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage unsigned long old_mmap(unsigned long __user *args) { unsigned long buffer[6]; @@ -63,7 +38,7 @@ asmlinkage unsigned long old_mmap(unsigned long __user *args) if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */ goto out; - err = do_mmap2(buffer[0], buffer[1], buffer[2], buffer[3], + err = sys_mmap_pgoff(buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5] >> PAGE_SHIFT); out: return err; @@ -73,7 +48,8 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - return do_mmap2(addr, len, prot, flags, fd, pgoff); + /* bug(?): 8Kb pages here */ + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); } /* diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c index 2b6b5289cdcc..1d3d4c9e2521 100644 --- a/arch/frv/kernel/sys_frv.c +++ b/arch/frv/kernel/sys_frv.c @@ -31,9 +31,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - int error = -EBADF; - struct file * file = NULL; - /* As with sparc32, make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE we have.... */ @@ -41,70 +38,11 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, trying to map something we can't */ if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1)) return -EINVAL; - pgoff >>= PAGE_SHIFT - 12; - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; + return sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT - 12)); } -#if 0 /* DAVIDM - do we want this */ -struct mmap_arg_struct64 { - __u32 addr; - __u32 len; - __u32 prot; - __u32 flags; - __u64 offset; /* 64 bits */ - __u32 fd; -}; - -asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) -{ - int error = -EFAULT; - struct file * file = NULL; - struct mmap_arg_struct64 a; - unsigned long pgoff; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - - if ((long)a.offset & ~PAGE_MASK) - return -EINVAL; - - pgoff = a.offset >> PAGE_SHIFT; - if ((a.offset >> PAGE_SHIFT) != pgoff) - return -EINVAL; - - if (!(a.flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(a.fd); - if (!file) - goto out; - } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); -out: - return error; -} -#endif - /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. * diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c index 8cb5d73a0e35..b5969db0ca10 100644 --- a/arch/h8300/kernel/sys_h8300.c +++ b/arch/h8300/kernel/sys_h8300.c @@ -26,39 +26,6 @@ #include #include -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to @@ -87,58 +54,12 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) if (a.offset & ~PAGE_MASK) goto out; - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); out: return error; } -#if 0 /* DAVIDM - do we want this */ -struct mmap_arg_struct64 { - __u32 addr; - __u32 len; - __u32 prot; - __u32 flags; - __u64 offset; /* 64 bits */ - __u32 fd; -}; - -asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) -{ - int error = -EFAULT; - struct file * file = NULL; - struct mmap_arg_struct64 a; - unsigned long pgoff; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - - if ((long)a.offset & ~PAGE_MASK) - return -EINVAL; - - pgoff = a.offset >> PAGE_SHIFT; - if ((a.offset >> PAGE_SHIFT) != pgoff) - return -EINVAL; - - if (!(a.flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(a.fd); - if (!file) - goto out; - } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); -out: - return error; -} -#endif - struct sel_arg_struct { unsigned long n; fd_set *inp, *outp, *exp; diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S index 4eb67faac633..2d69881eda6a 100644 --- a/arch/h8300/kernel/syscalls.S +++ b/arch/h8300/kernel/syscalls.S @@ -206,7 +206,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ .long SYMBOL_NAME(sys_vfork) /* 190 */ .long SYMBOL_NAME(sys_getrlimit) - .long SYMBOL_NAME(sys_mmap2) + .long SYMBOL_NAME(sys_mmap_pgoff) .long SYMBOL_NAME(sys_truncate64) .long SYMBOL_NAME(sys_ftruncate64) .long SYMBOL_NAME(sys_stat64) /* 195 */ diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 625ed8f76fce..e031ee8ecb05 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -858,6 +858,9 @@ ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot prot = get_prot32(prot); + if (flags & MAP_HUGETLB) + return -ENOMEM; + #if PAGE_SHIFT > IA32_PAGE_SHIFT mutex_lock(&ia32_mmap_mutex); { diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index 92ed83f34036..609d50056a6c 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -100,51 +100,7 @@ sys_getpagesize (void) asmlinkage unsigned long ia64_brk (unsigned long brk) { - unsigned long rlim, retval, newbrk, oldbrk; - struct mm_struct *mm = current->mm; - - /* - * Most of this replicates the code in sys_brk() except for an additional safety - * check and the clearing of r8. However, we can't call sys_brk() because we need - * to acquire the mmap_sem before we can do the test... - */ - down_write(&mm->mmap_sem); - - if (brk < mm->end_code) - goto out; - newbrk = PAGE_ALIGN(brk); - oldbrk = PAGE_ALIGN(mm->brk); - if (oldbrk == newbrk) - goto set_brk; - - /* Always allow shrinking brk. */ - if (brk <= mm->brk) { - if (!do_munmap(mm, newbrk, oldbrk-newbrk)) - goto set_brk; - goto out; - } - - /* Check against unimplemented/unmapped addresses: */ - if ((newbrk - oldbrk) > RGN_MAP_LIMIT || REGION_OFFSET(newbrk) > RGN_MAP_LIMIT) - goto out; - - /* Check against rlimit.. */ - rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; - if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim) - goto out; - - /* Check against existing mmap mappings. */ - if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) - goto out; - - /* Ok, looks good - let it rip. */ - if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk) - goto out; -set_brk: - mm->brk = brk; -out: - retval = mm->brk; - up_write(&mm->mmap_sem); + unsigned long retval = sys_brk(brk); force_successful_syscall_return(); return retval; } @@ -185,39 +141,6 @@ int ia64_mmap_check(unsigned long addr, unsigned long len, return 0; } -static inline unsigned long -do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff) -{ - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return -EBADF; - - if (!file->f_op || !file->f_op->mmap) { - addr = -ENODEV; - goto out; - } - } - - /* Careful about overflows.. */ - len = PAGE_ALIGN(len); - if (!len || len > TASK_SIZE) { - addr = -EINVAL; - goto out; - } - - down_write(¤t->mm->mmap_sem); - addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - -out: if (file) - fput(file); - return addr; -} - /* * mmap2() is like mmap() except that the offset is expressed in units * of PAGE_SIZE (instead of bytes). This allows to mmap2() (pieces @@ -226,7 +149,7 @@ out: if (file) asmlinkage unsigned long sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff) { - addr = do_mmap2(addr, len, prot, flags, fd, pgoff); + addr = sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); if (!IS_ERR((void *) addr)) force_successful_syscall_return(); return addr; @@ -238,7 +161,7 @@ sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, lo if (offset_in_page(off) != 0) return -EINVAL; - addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT); + addr = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); if (!IS_ERR((void *) addr)) force_successful_syscall_return(); return addr; diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index 305ac852bbed..d3c865c5a6ba 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -76,30 +76,6 @@ asmlinkage int sys_tas(int __user *addr) return oldval; } -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. * diff --git a/arch/m32r/kernel/syscall_table.S b/arch/m32r/kernel/syscall_table.S index aa3bf4cfab37..60536e271233 100644 --- a/arch/m32r/kernel/syscall_table.S +++ b/arch/m32r/kernel/syscall_table.S @@ -191,7 +191,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 + .long sys_mmap_pgoff .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 7deb402bfc75..218f441de667 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -29,37 +29,16 @@ #include #include -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - return do_mmap2(addr, len, prot, flags, fd, pgoff); + /* + * This is wrong for sun3 - there PAGE_SIZE is 8Kb, + * so we need to shift the argument down by 1; m68k mmap64(3) + * (in libc) expects the last argument of mmap2 in 4Kb units. + */ + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); } /* @@ -90,58 +69,12 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) if (a.offset & ~PAGE_MASK) goto out; - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); out: return error; } -#if 0 -struct mmap_arg_struct64 { - __u32 addr; - __u32 len; - __u32 prot; - __u32 flags; - __u64 offset; /* 64 bits */ - __u32 fd; -}; - -asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) -{ - int error = -EFAULT; - struct file * file = NULL; - struct mmap_arg_struct64 a; - unsigned long pgoff; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - - if ((long)a.offset & ~PAGE_MASK) - return -EINVAL; - - pgoff = a.offset >> PAGE_SHIFT; - if ((a.offset >> PAGE_SHIFT) != pgoff) - return -EINVAL; - - if (!(a.flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(a.fd); - if (!file) - goto out; - } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); -out: - return error; -} -#endif - struct sel_arg_struct { unsigned long n; fd_set __user *inp, *outp, *exp; diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c index efdd090778a3..b67cbc735a9b 100644 --- a/arch/m68knommu/kernel/sys_m68k.c +++ b/arch/m68knommu/kernel/sys_m68k.c @@ -27,39 +27,6 @@ #include #include -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to @@ -88,9 +55,8 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) if (a.offset & ~PAGE_MASK) goto out; - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); out: return error; } diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S index 23535cc415ae..486837efa3d7 100644 --- a/arch/m68knommu/kernel/syscalltable.S +++ b/arch/m68knommu/kernel/syscalltable.S @@ -210,7 +210,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 + .long sys_mmap_pgoff .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 07cabed4b947..9f3c205fb75b 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -62,46 +62,14 @@ asmlinkage long microblaze_execve(char __user *filenamei, char __user *__user *a return error; } -asmlinkage long -sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - struct file *file = NULL; - int ret = -EBADF; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) { - printk(KERN_INFO "no fd in mmap\r\n"); - goto out; - } - } - - down_write(¤t->mm->mmap_sem); - ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); -out: - return ret; -} - asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, off_t pgoff) { - int err = -EINVAL; + if (pgoff & ~PAGE_MASK) + return -EINVAL; - if (pgoff & ~PAGE_MASK) { - printk(KERN_INFO "no pagemask in mmap\r\n"); - goto out; - } - - err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); -out: - return err; + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); } /* diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index ecec19155135..eb50ce5e4e84 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -196,7 +196,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* reserved for streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 /* mmap2 */ + .long sys_mmap_pgoff /* mmap2 */ .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index b77fefaff9da..ea4a74652cf8 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -67,28 +67,13 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, pgoff) { - struct file * file = NULL; unsigned long error; error = -EINVAL; if (pgoff & (~PAGE_MASK >> 12)) goto out; - pgoff >>= PAGE_SHIFT-12; - - if (!(flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(fd); - if (!file) - goto out; - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); - + error = sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT-12)); out: return error; } diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index fe0d79805603..3f7f466190b4 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -93,7 +93,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, * We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && (addr & shm_align_mask)) + if ((flags & MAP_SHARED) && + ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) return -EINVAL; return addr; } @@ -129,31 +130,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, } } -/* common code for old and new mmaps */ -static inline unsigned long -do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, unsigned long pgoff) -{ - unsigned long error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, off_t, offset) @@ -164,7 +140,7 @@ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, if (offset & ~PAGE_MASK) goto out; - result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); out: return result; @@ -177,7 +153,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len, if (pgoff & (~PAGE_MASK >> 12)) return -EINVAL; - return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12)); + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12)); } save_static_function(sys_fork); diff --git a/arch/mn10300/include/asm/mman.h b/arch/mn10300/include/asm/mman.h index 8eebf89f5ab1..db5c53da73ce 100644 --- a/arch/mn10300/include/asm/mman.h +++ b/arch/mn10300/include/asm/mman.h @@ -1 +1,6 @@ #include + +#define MIN_MAP_ADDR PAGE_SIZE /* minimum fixed mmap address */ + +#define arch_mmap_check(addr, len, flags) \ + (((flags) & MAP_FIXED && (addr) < MIN_MAP_ADDR) ? -EINVAL : 0) diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index a94e7ea3faa6..c9ee6c009d79 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S @@ -578,7 +578,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* reserved for streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 + .long sys_mmap_pgoff .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ diff --git a/arch/mn10300/kernel/sys_mn10300.c b/arch/mn10300/kernel/sys_mn10300.c index 8ca5af00334c..17cc6ce04e84 100644 --- a/arch/mn10300/kernel/sys_mn10300.c +++ b/arch/mn10300/kernel/sys_mn10300.c @@ -23,47 +23,13 @@ #include -#define MIN_MAP_ADDR PAGE_SIZE /* minimum fixed mmap address */ - -/* - * memory mapping syscall - */ -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - struct file *file = NULL; - long error = -EINVAL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - if (flags & MAP_FIXED && addr < MIN_MAP_ADDR) - goto out; - - error = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage long old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset) { if (offset & ~PAGE_MASK) return -EINVAL; - return sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); } struct sel_arg_struct { diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 71b31957c8f1..9147391afb03 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -110,37 +110,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, return addr; } -static unsigned long do_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long fd, - unsigned long pgoff) -{ - struct file * file = NULL; - unsigned long error = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file != NULL) - fput(file); -out: - return error; -} - asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE we have. */ - return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12)); + return sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT - 12)); } asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, @@ -148,7 +125,8 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long offset) { if (!(offset & ~PAGE_MASK)) { - return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + return sys_mmap_pgoff(addr, len, prot, flags, fd, + offset >> PAGE_SHIFT); } else { return -EINVAL; } diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index c04832c4a02e..3370e62e43d4 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c @@ -140,7 +140,6 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off, int shift) { - struct file * file = NULL; unsigned long ret = -EINVAL; if (!arch_validate_prot(prot)) @@ -151,20 +150,8 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len, goto out; off >>= shift; } - - ret = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - if (!(file = fget(fd))) - goto out; - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - ret = do_mmap_pgoff(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); + ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off); out: return ret; } diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 0debcec23a39..9c746c01a7a7 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -683,38 +683,6 @@ struct mmap_arg_struct_emu31 { u32 offset; }; -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - struct file * file = NULL; - unsigned long error = -EBADF; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) { - /* Result is out of bounds. */ - do_munmap(current->mm, addr, len); - error = -ENOMEM; - } - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - - asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) { @@ -728,7 +696,8 @@ old32_mmap(struct mmap_arg_struct_emu31 __user *arg) if (a.offset & ~PAGE_MASK) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); out: return error; } @@ -741,7 +710,7 @@ sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) if (copy_from_user(&a, arg, sizeof(a))) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); out: return error; } diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index e9d94f61d500..86a74c9c9e63 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -32,32 +32,6 @@ #include #include "entry.h" -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - long error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux for S/390 isn't able to handle more than 5 @@ -81,7 +55,7 @@ SYSCALL_DEFINE1(mmap2, struct mmap_arg_struct __user *, arg) if (copy_from_user(&a, arg, sizeof(a))) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); out: return error; } @@ -98,7 +72,7 @@ SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct __user *, arg) if (a.offset & ~PAGE_MASK) goto out; - error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return error; } diff --git a/arch/score/kernel/sys_score.c b/arch/score/kernel/sys_score.c index 001249469866..856ed68a58e6 100644 --- a/arch/score/kernel/sys_score.c +++ b/arch/score/kernel/sys_score.c @@ -36,34 +36,16 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - int error = -EBADF; - struct file *file = NULL; - - if (pgoff & (~PAGE_MASK >> 12)) - return -EINVAL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return error; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - - return error; + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); } asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, off_t pgoff) + unsigned long flags, unsigned long fd, off_t offset) { - return sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); + if (unlikely(offset & ~PAGE_MASK)) + return -EINVAL; + return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); } asmlinkage long diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 8aa5d1ceaf14..71399cde03b5 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c @@ -28,37 +28,13 @@ #include #include -static inline long -do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, int fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage int old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, int fd, unsigned long off) { if (off & ~PAGE_MASK) return -EINVAL; - return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT); + return sys_mmap_pgoff(addr, len, prot, flags, fd, off>>PAGE_SHIFT); } asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, @@ -74,7 +50,7 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, pgoff >>= PAGE_SHIFT - 12; - return do_mmap2(addr, len, prot, flags, fd, pgoff); + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); } /* diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c index d2984fa42d3d..afeb710ec5c3 100644 --- a/arch/sh/mm/mmap.c +++ b/arch/sh/mm/mmap.c @@ -54,7 +54,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, /* We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && (addr & shm_align_mask)) + if ((flags & MAP_SHARED) && + ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) return -EINVAL; return addr; } diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 03035c852a43..3a82e65d8db2 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c @@ -45,7 +45,8 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi /* We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1))) + if ((flags & MAP_SHARED) && + ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) return -EINVAL; return addr; } @@ -79,15 +80,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi } } -asmlinkage unsigned long sparc_brk(unsigned long brk) -{ - if(ARCH_SUN4C) { - if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000)) - return current->mm->brk; - } - return sys_brk(brk); -} - /* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. @@ -234,31 +226,6 @@ int sparc_mmap_check(unsigned long addr, unsigned long len) } /* Linux version of mmap */ -static unsigned long do_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long fd, - unsigned long pgoff) -{ - struct file * file = NULL; - unsigned long retval = -EBADF; - - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - len = PAGE_ALIGN(len); - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return retval; -} asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, @@ -266,14 +233,16 @@ asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, { /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE we have. */ - return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12)); + return sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT - 12)); } asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off) { - return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT); + /* no alignment check? */ + return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); } long sparc_remap_file_pages(unsigned long start, unsigned long size, @@ -287,27 +256,6 @@ long sparc_remap_file_pages(unsigned long start, unsigned long size, (pgoff >> (PAGE_SHIFT - 12)), flags); } -extern unsigned long do_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, unsigned long new_addr); - -asmlinkage unsigned long sparc_mremap(unsigned long addr, - unsigned long old_len, unsigned long new_len, - unsigned long flags, unsigned long new_addr) -{ - unsigned long ret = -EINVAL; - - if (unlikely(sparc_mmap_check(addr, old_len))) - goto out; - if (unlikely(sparc_mmap_check(new_addr, new_len))) - goto out; - down_write(¤t->mm->mmap_sem); - ret = do_mremap(addr, old_len, new_len, flags, new_addr); - up_write(¤t->mm->mmap_sem); -out: - return ret; -} - /* we come to here via sys_nis_syscall so it can setup the regs argument */ asmlinkage unsigned long c_sys_nis_syscall (struct pt_regs *regs) diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index e2d102447a43..cfa0e19abe3b 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -317,10 +317,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags) { unsigned long align_goal, addr = -ENOMEM; + unsigned long (*get_area)(struct file *, unsigned long, + unsigned long, unsigned long, unsigned long); + + get_area = current->mm->get_unmapped_area; if (flags & MAP_FIXED) { /* Ok, don't mess with it. */ - return get_unmapped_area(NULL, orig_addr, len, pgoff, flags); + return get_area(NULL, orig_addr, len, pgoff, flags); } flags &= ~MAP_SHARED; @@ -333,7 +337,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u align_goal = (64UL * 1024); do { - addr = get_unmapped_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags); + addr = get_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags); if (!(addr & ~PAGE_MASK)) { addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL); break; @@ -351,7 +355,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u * be obtained. */ if (addr & ~PAGE_MASK) - addr = get_unmapped_area(NULL, orig_addr, len, pgoff, flags); + addr = get_area(NULL, orig_addr, len, pgoff, flags); return addr; } @@ -399,18 +403,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm) } } -SYSCALL_DEFINE1(sparc_brk, unsigned long, brk) -{ - /* People could try to be nasty and use ta 0x6d in 32bit programs */ - if (test_thread_flag(TIF_32BIT) && brk >= STACK_TOP32) - return current->mm->brk; - - if (unlikely(straddles_64bit_va_hole(current->mm->brk, brk))) - return current->mm->brk; - - return sys_brk(brk); -} - /* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. @@ -568,23 +560,13 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, off) { - struct file * file = NULL; - unsigned long retval = -EBADF; + unsigned long retval = -EINVAL; - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - len = PAGE_ALIGN(len); - - down_write(¤t->mm->mmap_sem); - retval = do_mmap(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); + if ((off + PAGE_ALIGN(len)) < off) + goto out; + if (off & ~PAGE_MASK) + goto out; + retval = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); out: return retval; } @@ -614,12 +596,6 @@ SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len, if (test_thread_flag(TIF_32BIT)) goto out; - if (unlikely(new_len >= VA_EXCLUDE_START)) - goto out; - if (unlikely(sparc_mmap_check(addr, old_len))) - goto out; - if (unlikely(sparc_mmap_check(new_addr, new_len))) - goto out; down_write(¤t->mm->mmap_sem); ret = do_mremap(addr, old_len, new_len, flags, new_addr); diff --git a/arch/sparc/kernel/systbls.h b/arch/sparc/kernel/systbls.h index a63c5d2d9849..d2f999ae2b85 100644 --- a/arch/sparc/kernel/systbls.h +++ b/arch/sparc/kernel/systbls.h @@ -9,7 +9,6 @@ struct new_utsname; extern asmlinkage unsigned long sys_getpagesize(void); -extern asmlinkage unsigned long sparc_brk(unsigned long brk); extern asmlinkage long sparc_pipe(struct pt_regs *regs); extern asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 0f1658d37490..14f950afcd67 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -19,7 +19,7 @@ sys_call_table: /*0*/ .long sys_restart_syscall, sys_exit, sys_fork, sys_read, sys_write /*5*/ .long sys_open, sys_close, sys_wait4, sys_creat, sys_link /*10*/ .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod -/*15*/ .long sys_chmod, sys_lchown16, sparc_brk, sys_nis_syscall, sys_lseek +/*15*/ .long sys_chmod, sys_lchown16, sys_brk, sys_nis_syscall, sys_lseek /*20*/ .long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 /*25*/ .long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause /*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice @@ -67,7 +67,7 @@ sys_call_table: /*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler /*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep -/*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl +/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl /*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep /*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 009825f6e73c..f63c871eebb7 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -21,7 +21,7 @@ sys_call_table32: /*0*/ .word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write /*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod -/*15*/ .word sys_chmod, sys_lchown16, sys_sparc_brk, sys32_perfctr, sys32_lseek +/*15*/ .word sys_chmod, sys_lchown16, sys_brk, sys32_perfctr, sys32_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice @@ -96,7 +96,7 @@ sys_call_table: /*0*/ .word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write /*5*/ .word sys_open, sys_close, sys_wait4, sys_creat, sys_link /*10*/ .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod -/*15*/ .word sys_chmod, sys_lchown, sys_sparc_brk, sys_perfctr, sys_lseek +/*15*/ .word sys_chmod, sys_lchown, sys_brk, sys_perfctr, sys_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid /*25*/ .word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall /*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index a4625c7b2bf9..cccab850c27e 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -8,6 +8,7 @@ #include "linux/mm.h" #include "linux/sched.h" #include "linux/utsname.h" +#include "linux/syscalls.h" #include "asm/current.h" #include "asm/mman.h" #include "asm/uaccess.h" @@ -37,31 +38,6 @@ long sys_vfork(void) return ret; } -/* common code for old and new mmaps */ -long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - long error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - out: - return error; -} - long old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset) @@ -70,7 +46,7 @@ long old_mmap(unsigned long addr, unsigned long len, if (offset & ~PAGE_MASK) goto out; - err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + err = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); out: return err; } diff --git a/arch/um/sys-i386/shared/sysdep/syscalls.h b/arch/um/sys-i386/shared/sysdep/syscalls.h index 905698197e35..e7787679e317 100644 --- a/arch/um/sys-i386/shared/sysdep/syscalls.h +++ b/arch/um/sys-i386/shared/sysdep/syscalls.h @@ -20,7 +20,3 @@ extern syscall_handler_t *sys_call_table[]; #define EXECUTE_SYSCALL(syscall, regs) \ ((long (*)(struct syscall_args)) \ (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) - -extern long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff); diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 581b0568fe19..5294d8446732 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -696,7 +696,7 @@ ia32_sys_call_table: .quad quiet_ni_syscall /* streams2 */ .quad stub32_vfork /* 190 */ .quad compat_sys_getrlimit - .quad sys32_mmap2 + .quad sys_mmap_pgoff .quad sys32_truncate64 .quad sys32_ftruncate64 .quad sys32_stat64 /* 195 */ diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index 9f5527198825..016218c353e7 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c @@ -155,9 +155,6 @@ struct mmap_arg_struct { asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; - struct file *file = NULL; - unsigned long retval; - struct mm_struct *mm ; if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; @@ -165,22 +162,8 @@ asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg) if (a.offset & ~PAGE_MASK) return -EINVAL; - if (!(a.flags & MAP_ANONYMOUS)) { - file = fget(a.fd); - if (!file) - return -EBADF; - } - - mm = current->mm; - down_write(&mm->mmap_sem); - retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, + return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset>>PAGE_SHIFT); - if (file) - fput(file); - - up_write(&mm->mmap_sem); - - return retval; } asmlinkage long sys32_mprotect(unsigned long start, size_t len, @@ -539,30 +522,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, return ret; } -asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - struct mm_struct *mm = current->mm; - unsigned long error; - struct file *file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return -EBADF; - } - - down_write(&mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(&mm->mmap_sem); - - if (file) - fput(file); - return error; -} - asmlinkage long sys32_olduname(struct oldold_utsname __user *name) { char *arch = "x86_64"; diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h index 72a6dcd1299b..77c1184bee43 100644 --- a/arch/x86/include/asm/sys_ia32.h +++ b/arch/x86/include/asm/sys_ia32.h @@ -62,9 +62,6 @@ asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32); asmlinkage long sys32_personality(unsigned long); asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); -asmlinkage long sys32_mmap2(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, unsigned long); - struct oldold_utsname; struct old_utsname; asmlinkage long sys32_olduname(struct oldold_utsname __user *); diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index 372b76edd63f..1bb6e395881c 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h @@ -55,8 +55,6 @@ struct sel_arg_struct; struct oldold_utsname; struct old_utsname; -asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, unsigned long); asmlinkage int old_mmap(struct mmap_arg_struct __user *); asmlinkage int old_select(struct sel_arg_struct __user *); asmlinkage int sys_ipc(uint, int, int, int, void __user *, long); diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c index 1884a8d12bfa..dee1ff7cba58 100644 --- a/arch/x86/kernel/sys_i386_32.c +++ b/arch/x86/kernel/sys_i386_32.c @@ -24,31 +24,6 @@ #include -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file *file = NULL; - struct mm_struct *mm = current->mm; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(&mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(&mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux/i386 didn't use to be able to handle more than @@ -77,7 +52,7 @@ asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) if (a.offset & ~PAGE_MASK) goto out; - err = sys_mmap2(a.addr, a.len, a.prot, a.flags, + err = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return err; diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 45e00eb09c3a..8aa2057efd12 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -23,26 +23,11 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, fd, unsigned long, off) { long error; - struct file *file; - error = -EINVAL; if (off & ~PAGE_MASK) goto out; - error = -EBADF; - file = NULL; - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); + error = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); out: return error; } diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S index 0157cd26d7cc..76d70a451285 100644 --- a/arch/x86/kernel/syscall_table_32.S +++ b/arch/x86/kernel/syscall_table_32.S @@ -191,7 +191,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* reserved for streams2 */ .long ptregs_vfork /* 190 */ .long sys_getrlimit - .long sys_mmap2 + .long sys_mmap_pgoff .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index 05cebf8f62b1..4352dbe1186a 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h @@ -13,8 +13,6 @@ struct sigaction; asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*); asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); asmlinkage long xtensa_pipe(int __user *); -asmlinkage long xtensa_mmap2(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, unsigned long); asmlinkage long xtensa_ptrace(long, long, long, long); asmlinkage long xtensa_sigreturn(struct pt_regs*); asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index c092c8fbb2cf..9a5c354d2138 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -189,7 +189,7 @@ __SYSCALL( 79, sys_fremovexattr, 2) /* File Map / Shared Memory Operations */ #define __NR_mmap2 80 -__SYSCALL( 80, xtensa_mmap2, 6) +__SYSCALL( 80, sys_mmap_pgoff, 6) #define __NR_munmap 81 __SYSCALL( 81, sys_munmap, 2) #define __NR_mprotect 82 diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index ac15ecbdf919..1e67bab775c1 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c @@ -57,31 +57,6 @@ asmlinkage long xtensa_pipe(int __user *userfds) return error; } - -asmlinkage long xtensa_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) { unsigned long ret; diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index a990ace1a838..93515c6190a7 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -879,4 +879,8 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[]); asmlinkage long sys_perf_event_open( struct perf_event_attr __user *attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags); + +asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff); #endif diff --git a/ipc/shm.c b/ipc/shm.c index 464694e0aa4a..11bec626c228 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -290,28 +290,28 @@ static unsigned long shm_get_unmapped_area(struct file *file, unsigned long flags) { struct shm_file_data *sfd = shm_file_data(file); - return get_unmapped_area(sfd->file, addr, len, pgoff, flags); -} - -int is_file_shm_hugepages(struct file *file) -{ - int ret = 0; - - if (file->f_op == &shm_file_operations) { - struct shm_file_data *sfd; - sfd = shm_file_data(file); - ret = is_file_hugepages(sfd->file); - } - return ret; + return sfd->file->f_op->get_unmapped_area(sfd->file, addr, len, + pgoff, flags); } static const struct file_operations shm_file_operations = { .mmap = shm_mmap, .fsync = shm_fsync, .release = shm_release, +}; + +static const struct file_operations shm_file_operations_huge = { + .mmap = shm_mmap, + .fsync = shm_fsync, + .release = shm_release, .get_unmapped_area = shm_get_unmapped_area, }; +int is_file_shm_hugepages(struct file *file) +{ + return file->f_op == &shm_file_operations_huge; +} + static const struct vm_operations_struct shm_vm_ops = { .open = shm_open, /* callback for a new vm-area open */ .close = shm_close, /* callback for when the vm-area is released */ @@ -889,7 +889,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) if (!sfd) goto out_put_dentry; - file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); + file = alloc_file(path.mnt, path.dentry, f_mode, + is_file_hugepages(shp->shm_file) ? + &shm_file_operations_huge : + &shm_file_operations); if (!file) goto out_free; ima_counts_get(file); diff --git a/mm/mmap.c b/mm/mmap.c index 73f5e4b64010..ae197468b352 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -932,13 +932,9 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, if (!(flags & MAP_FIXED)) addr = round_hint_to_min(addr); - error = arch_mmap_check(addr, len, flags); - if (error) - return error; - /* Careful about overflows.. */ len = PAGE_ALIGN(len); - if (!len || len > TASK_SIZE) + if (!len) return -ENOMEM; /* offset overflow? */ @@ -949,24 +945,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, if (mm->map_count > sysctl_max_map_count) return -ENOMEM; - if (flags & MAP_HUGETLB) { - struct user_struct *user = NULL; - if (file) - return -EINVAL; - - /* - * VM_NORESERVE is used because the reservations will be - * taken when vm_ops->mmap() is called - * A dummy user value is used because we are not locking - * memory so no accounting is necessary - */ - len = ALIGN(len, huge_page_size(&default_hstate)); - file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, - &user, HUGETLB_ANONHUGE_INODE); - if (IS_ERR(file)) - return PTR_ERR(file); - } - /* Obtain the address to map to. we verify (or select) it and ensure * that it represents a valid section of the address space. */ @@ -1459,6 +1437,14 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + unsigned long error = arch_mmap_check(addr, len, flags); + if (error) + return error; + + /* Careful about overflows.. */ + if (len > TASK_SIZE) + return -ENOMEM; + get_area = current->mm->get_unmapped_area; if (file && file->f_op && file->f_op->get_unmapped_area) get_area = file->f_op->get_unmapped_area; @@ -2003,20 +1989,14 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if (!len) return addr; - if ((addr + len) > TASK_SIZE || (addr + len) < addr) - return -EINVAL; - - if (is_hugepage_only_range(mm, addr, len)) - return -EINVAL; - error = security_file_mmap(NULL, 0, 0, 0, addr, 1); if (error) return error; flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; - error = arch_mmap_check(addr, len, flags); - if (error) + error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED); + if (error & ~PAGE_MASK) return error; /* diff --git a/mm/mremap.c b/mm/mremap.c index 97bff2547719..845190898d59 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -261,6 +261,137 @@ static unsigned long move_vma(struct vm_area_struct *vma, return new_addr; } +static struct vm_area_struct *vma_to_resize(unsigned long addr, + unsigned long old_len, unsigned long new_len, unsigned long *p) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma = find_vma(mm, addr); + + if (!vma || vma->vm_start > addr) + goto Efault; + + if (is_vm_hugetlb_page(vma)) + goto Einval; + + /* We can't remap across vm area boundaries */ + if (old_len > vma->vm_end - addr) + goto Efault; + + if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) { + if (new_len > old_len) + goto Efault; + } + + if (vma->vm_flags & VM_LOCKED) { + unsigned long locked, lock_limit; + locked = mm->locked_vm << PAGE_SHIFT; + lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; + locked += new_len - old_len; + if (locked > lock_limit && !capable(CAP_IPC_LOCK)) + goto Eagain; + } + + if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) + goto Enomem; + + if (vma->vm_flags & VM_ACCOUNT) { + unsigned long charged = (new_len - old_len) >> PAGE_SHIFT; + if (security_vm_enough_memory(charged)) + goto Efault; + *p = charged; + } + + return vma; + +Efault: /* very odd choice for most of the cases, but... */ + return ERR_PTR(-EFAULT); +Einval: + return ERR_PTR(-EINVAL); +Enomem: + return ERR_PTR(-ENOMEM); +Eagain: + return ERR_PTR(-EAGAIN); +} + +static unsigned long mremap_to(unsigned long addr, + unsigned long old_len, unsigned long new_addr, + unsigned long new_len) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long ret = -EINVAL; + unsigned long charged = 0; + unsigned long map_flags; + + if (new_addr & ~PAGE_MASK) + goto out; + + if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len) + goto out; + + /* Check if the location we're moving into overlaps the + * old location at all, and fail if it does. + */ + if ((new_addr <= addr) && (new_addr+new_len) > addr) + goto out; + + if ((addr <= new_addr) && (addr+old_len) > new_addr) + goto out; + + ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); + if (ret) + goto out; + + ret = do_munmap(mm, new_addr, new_len); + if (ret) + goto out; + + if (old_len >= new_len) { + ret = do_munmap(mm, addr+new_len, old_len - new_len); + if (ret && old_len != new_len) + goto out; + old_len = new_len; + } + + vma = vma_to_resize(addr, old_len, new_len, &charged); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto out; + } + + map_flags = MAP_FIXED; + if (vma->vm_flags & VM_MAYSHARE) + map_flags |= MAP_SHARED; + + ret = get_unmapped_area(vma->vm_file, new_addr, new_len, vma->vm_pgoff + + ((addr - vma->vm_start) >> PAGE_SHIFT), + map_flags); + if (ret & ~PAGE_MASK) + goto out1; + + ret = move_vma(vma, addr, old_len, new_len, new_addr); + if (!(ret & ~PAGE_MASK)) + goto out; +out1: + vm_unacct_memory(charged); + +out: + return ret; +} + +static int vma_expandable(struct vm_area_struct *vma, unsigned long delta) +{ + unsigned long end = vma->vm_end + delta; + if (end < vma->vm_end) /* overflow */ + return 0; + if (vma->vm_next && vma->vm_next->vm_start < end) /* intersection */ + return 0; + if (get_unmapped_area(NULL, vma->vm_start, end - vma->vm_start, + 0, MAP_FIXED) & ~PAGE_MASK) + return 0; + return 1; +} + /* * Expand (or shrink) an existing mapping, potentially moving it at the * same time (controlled by the MREMAP_MAYMOVE flag and available VM space) @@ -294,32 +425,10 @@ unsigned long do_mremap(unsigned long addr, if (!new_len) goto out; - /* new_addr is only valid if MREMAP_FIXED is specified */ if (flags & MREMAP_FIXED) { - if (new_addr & ~PAGE_MASK) - goto out; - if (!(flags & MREMAP_MAYMOVE)) - goto out; - - if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len) - goto out; - - /* Check if the location we're moving into overlaps the - * old location at all, and fail if it does. - */ - if ((new_addr <= addr) && (new_addr+new_len) > addr) - goto out; - - if ((addr <= new_addr) && (addr+old_len) > new_addr) - goto out; - - ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); - if (ret) - goto out; - - ret = do_munmap(mm, new_addr, new_len); - if (ret) - goto out; + if (flags & MREMAP_MAYMOVE) + ret = mremap_to(addr, old_len, new_addr, new_len); + goto out; } /* @@ -332,60 +441,23 @@ unsigned long do_mremap(unsigned long addr, if (ret && old_len != new_len) goto out; ret = addr; - if (!(flags & MREMAP_FIXED) || (new_addr == addr)) - goto out; - old_len = new_len; + goto out; } /* - * Ok, we need to grow.. or relocate. + * Ok, we need to grow.. */ - ret = -EFAULT; - vma = find_vma(mm, addr); - if (!vma || vma->vm_start > addr) + vma = vma_to_resize(addr, old_len, new_len, &charged); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); goto out; - if (is_vm_hugetlb_page(vma)) { - ret = -EINVAL; - goto out; - } - /* We can't remap across vm area boundaries */ - if (old_len > vma->vm_end - addr) - goto out; - if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) { - if (new_len > old_len) - goto out; - } - if (vma->vm_flags & VM_LOCKED) { - unsigned long locked, lock_limit; - locked = mm->locked_vm << PAGE_SHIFT; - lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; - locked += new_len - old_len; - ret = -EAGAIN; - if (locked > lock_limit && !capable(CAP_IPC_LOCK)) - goto out; - } - if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) { - ret = -ENOMEM; - goto out; - } - - if (vma->vm_flags & VM_ACCOUNT) { - charged = (new_len - old_len) >> PAGE_SHIFT; - if (security_vm_enough_memory(charged)) - goto out_nc; } /* old_len exactly to the end of the area.. - * And we're not relocating the area. */ - if (old_len == vma->vm_end - addr && - !((flags & MREMAP_FIXED) && (addr != new_addr)) && - (old_len != new_len || !(flags & MREMAP_MAYMOVE))) { - unsigned long max_addr = TASK_SIZE; - if (vma->vm_next) - max_addr = vma->vm_next->vm_start; + if (old_len == vma->vm_end - addr) { /* can we just expand the current mapping? */ - if (max_addr - addr >= new_len) { + if (vma_expandable(vma, new_len - old_len)) { int pages = (new_len - old_len) >> PAGE_SHIFT; vma_adjust(vma, vma->vm_start, @@ -409,28 +481,27 @@ unsigned long do_mremap(unsigned long addr, */ ret = -ENOMEM; if (flags & MREMAP_MAYMOVE) { - if (!(flags & MREMAP_FIXED)) { - unsigned long map_flags = 0; - if (vma->vm_flags & VM_MAYSHARE) - map_flags |= MAP_SHARED; + unsigned long map_flags = 0; + if (vma->vm_flags & VM_MAYSHARE) + map_flags |= MAP_SHARED; - new_addr = get_unmapped_area(vma->vm_file, 0, new_len, - vma->vm_pgoff, map_flags); - if (new_addr & ~PAGE_MASK) { - ret = new_addr; - goto out; - } - - ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); - if (ret) - goto out; + new_addr = get_unmapped_area(vma->vm_file, 0, new_len, + vma->vm_pgoff + + ((addr - vma->vm_start) >> PAGE_SHIFT), + map_flags); + if (new_addr & ~PAGE_MASK) { + ret = new_addr; + goto out; } + + ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); + if (ret) + goto out; ret = move_vma(vma, addr, old_len, new_len, new_addr); } out: if (ret & ~PAGE_MASK) vm_unacct_memory(charged); -out_nc: return ret; } diff --git a/mm/util.c b/mm/util.c index 7c35ad95f927..b377ce430803 100644 --- a/mm/util.c +++ b/mm/util.c @@ -4,6 +4,10 @@ #include #include #include +#include +#include +#include +#include #include #define CREATE_TRACE_POINTS @@ -268,6 +272,46 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start, } EXPORT_SYMBOL_GPL(get_user_pages_fast); +SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, + unsigned long, prot, unsigned long, flags, + unsigned long, fd, unsigned long, pgoff) +{ + struct file * file = NULL; + unsigned long retval = -EBADF; + + if (!(flags & MAP_ANONYMOUS)) { + if (unlikely(flags & MAP_HUGETLB)) + return -EINVAL; + file = fget(fd); + if (!file) + goto out; + } else if (flags & MAP_HUGETLB) { + struct user_struct *user = NULL; + /* + * VM_NORESERVE is used because the reservations will be + * taken when vm_ops->mmap() is called + * A dummy user value is used because we are not locking + * memory so no accounting is necessary + */ + len = ALIGN(len, huge_page_size(&default_hstate)); + file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, + &user, HUGETLB_ANONHUGE_INODE); + if (IS_ERR(file)) + return PTR_ERR(file); + } + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + + down_write(¤t->mm->mmap_sem); + retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up_write(¤t->mm->mmap_sem); + + if (file) + fput(file); +out: + return retval; +} + /* Tracepoints definitions. */ EXPORT_TRACEPOINT_SYMBOL(kmalloc); EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc); From e4dd8ca5be771aa706b0797b3284328bb595bfa1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 16 Dec 2009 08:23:37 -0800 Subject: [PATCH 287/670] fasync: split 'fasync_helper()' into separate add/remove functions commit 53281b6d34d44308372d16acb7fb5327609f68b6 upstream. Yes, the add and remove cases do share the same basic loop and the locking, but the compiler can inline and then CSE some of the end result anyway. And splitting it up makes the code way easier to follow, and makes it clearer exactly what the semantics are. In particular, we must make sure that the FASYNC flag in file->f_flags exactly matches the state of "is this file on any fasync list", since not only is that flag visible to user space (F_GETFL), but we also use that flag to check whether we need to remove any fasync entries on file close. We got that wrong for the case of a mixed use of file locking (which tries to remove any fasync entries for file leases) and fasync. Splitting the function up also makes it possible to do some future optimizations without making the function even messier. In particular, since the FASYNC flag has to match the state of "is this on a list", we can do the following future optimizations: - on remove, we don't even need to get the locks and traverse the list if FASYNC isn't set, since we can know a priori that there is no point (this is effectively the same optimization that we already do in __fput() wrt removing fasync on file close) - on add, we can use the FASYNC flag to decide whether we are changing an existing entry or need to allocate a new one. but this is just the cleanup + fix for the FASYNC flag. Acked-by: Al Viro Tested-by: Tavis Ormandy Cc: Jeff Dike Cc: Matt Mackall Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/fcntl.c | 110 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 40 deletions(-) diff --git a/fs/fcntl.c b/fs/fcntl.c index 2cf93ec40a67..97e01dc0d95f 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -618,60 +618,90 @@ static DEFINE_RWLOCK(fasync_lock); static struct kmem_cache *fasync_cache __read_mostly; /* - * fasync_helper() is used by almost all character device drivers - * to set up the fasync queue. It returns negative on error, 0 if it did - * no changes and positive if it added/deleted the entry. + * Remove a fasync entry. If successfully removed, return + * positive and clear the FASYNC flag. If no entry exists, + * do nothing and return 0. + * + * NOTE! It is very important that the FASYNC flag always + * match the state "is the filp on a fasync list". + * + * We always take the 'filp->f_lock', in since fasync_lock + * needs to be irq-safe. */ -int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) +static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp) { struct fasync_struct *fa, **fp; - struct fasync_struct *new = NULL; int result = 0; - if (on) { - new = kmem_cache_alloc(fasync_cache, GFP_KERNEL); - if (!new) - return -ENOMEM; - } - - /* - * We need to take f_lock first since it's not an IRQ-safe - * lock. - */ spin_lock(&filp->f_lock); write_lock_irq(&fasync_lock); for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { - if (fa->fa_file == filp) { - if(on) { - fa->fa_fd = fd; - kmem_cache_free(fasync_cache, new); - } else { - *fp = fa->fa_next; - kmem_cache_free(fasync_cache, fa); - result = 1; - } - goto out; - } - } - - if (on) { - new->magic = FASYNC_MAGIC; - new->fa_file = filp; - new->fa_fd = fd; - new->fa_next = *fapp; - *fapp = new; - result = 1; - } -out: - if (on) - filp->f_flags |= FASYNC; - else + if (fa->fa_file != filp) + continue; + *fp = fa->fa_next; + kmem_cache_free(fasync_cache, fa); filp->f_flags &= ~FASYNC; + result = 1; + break; + } write_unlock_irq(&fasync_lock); spin_unlock(&filp->f_lock); return result; } +/* + * Add a fasync entry. Return negative on error, positive if + * added, and zero if did nothing but change an existing one. + * + * NOTE! It is very important that the FASYNC flag always + * match the state "is the filp on a fasync list". + */ +static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp) +{ + struct fasync_struct *new, *fa, **fp; + int result = 0; + + new = kmem_cache_alloc(fasync_cache, GFP_KERNEL); + if (!new) + return -ENOMEM; + + spin_lock(&filp->f_lock); + write_lock_irq(&fasync_lock); + for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { + if (fa->fa_file != filp) + continue; + fa->fa_fd = fd; + kmem_cache_free(fasync_cache, new); + goto out; + } + + new->magic = FASYNC_MAGIC; + new->fa_file = filp; + new->fa_fd = fd; + new->fa_next = *fapp; + *fapp = new; + result = 1; + filp->f_flags |= FASYNC; + +out: + write_unlock_irq(&fasync_lock); + spin_unlock(&filp->f_lock); + return result; +} + +/* + * fasync_helper() is used by almost all character device drivers + * to set up the fasync queue, and for regular files by the file + * lease code. It returns negative on error, 0 if it did no changes + * and positive if it added/deleted the entry. + */ +int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) +{ + if (!on) + return fasync_remove_entry(filp, fapp); + return fasync_add_entry(fd, filp, fapp); +} + EXPORT_SYMBOL(fasync_helper); void __kill_fasync(struct fasync_struct *fa, int sig, int band) From efd38f42843399cd8da8a5b63b04c8917f8d83a7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 24 Dec 2009 01:13:51 +0100 Subject: [PATCH 288/670] ASoC: fix params_rate() macro use in several codecs commit b3172f222ab5afdc91ea058bd11c42cf169728f3 upstream. Sevelar ASoC codec drivers wrongly assume, that the params_rate() macro returns one of SNDRV_PCM_RATE_* defines instead of the actual numerical sampling rate. Fix them. Signed-off-by: Guennadi Liakhovetski Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8510.c | 14 +++++++------- sound/soc/codecs/wm8940.c | 14 +++++++------- sound/soc/codecs/wm8974.c | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 060d5d06ba95..8db62e252ed0 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -425,23 +425,23 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, /* filter coefficient */ switch (params_rate(params)) { - case SNDRV_PCM_RATE_8000: + case 8000: adn |= 0x5 << 1; break; - case SNDRV_PCM_RATE_11025: + case 11025: adn |= 0x4 << 1; break; - case SNDRV_PCM_RATE_16000: + case 16000: adn |= 0x3 << 1; break; - case SNDRV_PCM_RATE_22050: + case 22050: adn |= 0x2 << 1; break; - case SNDRV_PCM_RATE_32000: + case 32000: adn |= 0x1 << 1; break; - case SNDRV_PCM_RATE_44100: - case SNDRV_PCM_RATE_48000: + case 44100: + case 48000: break; } diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 1ef2454c5205..63bc2ae736a1 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -379,23 +379,23 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, iface |= (1 << 9); switch (params_rate(params)) { - case SNDRV_PCM_RATE_8000: + case 8000: addcntrl |= (0x5 << 1); break; - case SNDRV_PCM_RATE_11025: + case 11025: addcntrl |= (0x4 << 1); break; - case SNDRV_PCM_RATE_16000: + case 16000: addcntrl |= (0x3 << 1); break; - case SNDRV_PCM_RATE_22050: + case 22050: addcntrl |= (0x2 << 1); break; - case SNDRV_PCM_RATE_32000: + case 32000: addcntrl |= (0x1 << 1); break; - case SNDRV_PCM_RATE_44100: - case SNDRV_PCM_RATE_48000: + case 44100: + case 48000: break; } ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl); diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index b0bd1c0ac1d0..0dbf6fe1878a 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -480,23 +480,23 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, /* filter coefficient */ switch (params_rate(params)) { - case SNDRV_PCM_RATE_8000: + case 8000: adn |= 0x5 << 1; break; - case SNDRV_PCM_RATE_11025: + case 11025: adn |= 0x4 << 1; break; - case SNDRV_PCM_RATE_16000: + case 16000: adn |= 0x3 << 1; break; - case SNDRV_PCM_RATE_22050: + case 22050: adn |= 0x2 << 1; break; - case SNDRV_PCM_RATE_32000: + case 32000: adn |= 0x1 << 1; break; - case SNDRV_PCM_RATE_44100: - case SNDRV_PCM_RATE_48000: + case 44100: + case 48000: break; } From 8dfabfcf7b0c03f33f7cb945772027060de70b61 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 19 Dec 2009 14:43:01 +0000 Subject: [PATCH 289/670] modules: Skip empty sections when exporting section notes commit 10b465aaf9536ee5a16652fa0700740183d48ec9 upstream. Commit 35dead4 "modules: don't export section names of empty sections via sysfs" changed the set of sections that have attributes, but did not change the iteration over these attributes in add_notes_attrs(). This can lead to add_notes_attrs() creating attributes with the wrong names or with null name pointers. Introduce a sect_empty() function and use it in both add_sect_attrs() and add_notes_attrs(). Reported-by: Martin Michlmayr Signed-off-by: Ben Hutchings Tested-by: Martin Michlmayr Signed-off-by: Rusty Russell Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/module.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index 5842a71cf052..37caef0197ef 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1146,6 +1146,12 @@ static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, * J. Corbet */ #if defined(CONFIG_KALLSYMS) && defined(CONFIG_SYSFS) + +static inline bool sect_empty(const Elf_Shdr *sect) +{ + return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; +} + struct module_sect_attr { struct module_attribute mattr; @@ -1187,8 +1193,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, /* Count loaded sections and allocate structures */ for (i = 0; i < nsect; i++) - if (sechdrs[i].sh_flags & SHF_ALLOC - && sechdrs[i].sh_size) + if (!sect_empty(&sechdrs[i])) nloaded++; size[0] = ALIGN(sizeof(*sect_attrs) + nloaded * sizeof(sect_attrs->attrs[0]), @@ -1206,9 +1211,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, sattr = §_attrs->attrs[0]; gattr = §_attrs->grp.attrs[0]; for (i = 0; i < nsect; i++) { - if (! (sechdrs[i].sh_flags & SHF_ALLOC)) - continue; - if (!sechdrs[i].sh_size) + if (sect_empty(&sechdrs[i])) continue; sattr->address = sechdrs[i].sh_addr; sattr->name = kstrdup(secstrings + sechdrs[i].sh_name, @@ -1292,7 +1295,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, /* Count notes sections and allocate structures. */ notes = 0; for (i = 0; i < nsect; i++) - if ((sechdrs[i].sh_flags & SHF_ALLOC) && + if (!sect_empty(&sechdrs[i]) && (sechdrs[i].sh_type == SHT_NOTE)) ++notes; @@ -1308,7 +1311,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, notes_attrs->notes = notes; nattr = ¬es_attrs->attrs[0]; for (loaded = i = 0; i < nsect; ++i) { - if (!(sechdrs[i].sh_flags & SHF_ALLOC)) + if (sect_empty(&sechdrs[i])) continue; if (sechdrs[i].sh_type == SHT_NOTE) { nattr->attr.name = mod->sect_attrs->attrs[loaded].name; From 24488113f0ee3d3fdb64734cb2364cbe2ca1ba33 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Sun, 27 Dec 2009 17:01:42 +0200 Subject: [PATCH 290/670] exofs: simple_write_end does not mark_inode_dirty commit efd124b999fb4d426b30675f1684521af0872789 upstream. exofs uses simple_write_end() for it's .write_end handler. But it is not enough because simple_write_end() does not call mark_inode_dirty() when it extends i_size. So even if we do call mark_inode_dirty at beginning of write out, with a very long IO and a saturated system we might get the .write_inode() called while still extend-writing to file and miss out on the last i_size updates. So override .write_end, call simple_write_end(), and afterwords if i_size was changed call mark_inode_dirty(). It stands to logic that since simple_write_end() was the one extending i_size it should also call mark_inode_dirty(). But it looks like all users of simple_write_end() are memory-bound pseudo filesystems, who could careless about mark_inode_dirty(). I might submit a warning-comment patch to simple_write_end() in future. Signed-off-by: Boaz Harrosh Signed-off-by: Greg Kroah-Hartman --- fs/exofs/inode.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 6c10f7476699..6f7df0f7d282 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -731,13 +731,28 @@ static int exofs_write_begin_export(struct file *file, fsdata); } +static int exofs_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *page, void *fsdata) +{ + struct inode *inode = mapping->host; + /* According to comment in simple_write_end i_mutex is held */ + loff_t i_size = inode->i_size; + int ret; + + ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata); + if (i_size != inode->i_size) + mark_inode_dirty(inode); + return ret; +} + const struct address_space_operations exofs_aops = { .readpage = exofs_readpage, .readpages = exofs_readpages, .writepage = exofs_writepage, .writepages = exofs_writepages, .write_begin = exofs_write_begin_export, - .write_end = simple_write_end, + .write_end = exofs_write_end, }; /****************************************************************************** From b7e5f77916291b3c80fdf34dd2a649d8d10138e8 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 5 Jan 2010 12:48:49 +1030 Subject: [PATCH 291/670] Revert "x86: Side-step lguest problem by only building cmpxchg8b_emu for pre-Pentium" commit db677ffa5f5a4f15b9dad4d132b3477b80766d82 upstream. This reverts commit ae1b22f6e46c03cede7cea234d0bf2253b4261cf. As Linus said in 982d007a6ee: "There was something really messy about cmpxchg8b and clone CPU's, so if you enable it on other CPUs later, do it carefully." This breaks lguest for those configs, but we can fix that by emulating if we have to. Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=14884 Signed-off-by: Rusty Russell Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/Kconfig.cpu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 2649840d888f..f2824fb8c79c 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -400,7 +400,7 @@ config X86_TSC config X86_CMPXCHG64 def_bool y - depends on !M386 && !M486 + depends on X86_PAE || X86_64 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM # this should be set for all -march=.. options where the compiler # generates cmov. From 3aafc557edb43aa82d9a5651f071d9dae7a2638b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 25 Dec 2009 17:44:45 +0100 Subject: [PATCH 292/670] nfsd: make sure data is on disk before calling ->fsync commit 7211a4e859ad070b28545c06e0a6cb60b3b8aa31 upstream. nfsd is not using vfs_fsync, so I missed it when changing the calling convention during the 2.6.32 window. This patch fixes it to not only start the data writeout, but also wait for it to complete before calling into ->fsync. Signed-off-by: Christoph Hellwig Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/vfs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index a293f0273263..570dd1c103d5 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -774,12 +774,9 @@ static inline int nfsd_dosync(struct file *filp, struct dentry *dp, int (*fsync) (struct file *, struct dentry *, int); int err; - err = filemap_fdatawrite(inode->i_mapping); + err = filemap_write_and_wait(inode->i_mapping); if (err == 0 && fop && (fsync = fop->fsync)) err = fsync(filp, dp, 0); - if (err == 0) - err = filemap_fdatawait(inode->i_mapping); - return err; } From eb0b93d6e280e51b1056be57ea92bb6ebec01ad4 Mon Sep 17 00:00:00 2001 From: Xiaotian Feng Date: Thu, 31 Dec 2009 10:52:36 +0800 Subject: [PATCH 293/670] sunrpc: fix peername failed on closed listener commit b292cf9ce70d221c3f04ff62db5ab13d9a249ca8 upstream. There're some warnings of "nfsd: peername failed (err 107)!" socket error -107 means Transport endpoint is not connected. This warning message was outputed by svc_tcp_accept() [net/sunrpc/svcsock.c], when kernel_getpeername returns -107. This means socket might be CLOSED. And svc_tcp_accept was called by svc_recv() [net/sunrpc/svc_xprt.c] if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { newxpt = xprt->xpt_ops->xpo_accept(xprt); So this might happen when xprt->xpt_flags has both XPT_LISTENER and XPT_CLOSE. Let's take a look at commit b0401d72, this commit has moved the close processing after do recvfrom method, but this commit also introduces this warnings, if the xpt_flags has both XPT_LISTENER and XPT_CLOSED, we should close it, not accpet then close. Signed-off-by: Xiaotian Feng Cc: J. Bruce Fields Cc: Neil Brown Cc: Trond Myklebust Cc: David S. Miller Cc: Nikola Ciprich Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/svc_xprt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index df124f78ee48..0266ccada52a 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -711,7 +711,8 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) spin_unlock_bh(&pool->sp_lock); len = 0; - if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { + if (test_bit(XPT_LISTENER, &xprt->xpt_flags) && + !test_bit(XPT_CLOSE, &xprt->xpt_flags)) { struct svc_xprt *newxpt; newxpt = xprt->xpt_ops->xpo_accept(xprt); if (newxpt) { From e64b13f62782f5e495c085e1c06e48224545617f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 18 Dec 2009 16:28:05 -0500 Subject: [PATCH 294/670] SUNRPC: Fix up an error return value in gss_import_sec_context_kerberos() commit 14ace024b1e16d2bb9445c8387494fbbd820a738 upstream. If the context allocation fails, the function currently returns a random error code, since the variable 'p' still points to a valid memory location. Ensure that it returns ENOMEM... Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/auth_gss/gss_krb5_mech.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index ef45eba22485..2deb0ed72ff4 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -131,8 +131,10 @@ gss_import_sec_context_kerberos(const void *p, struct krb5_ctx *ctx; int tmp; - if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS))) + if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS))) { + p = ERR_PTR(-ENOMEM); goto out_err; + } p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate)); if (IS_ERR(p)) From 8ffe94786b66c4ea4298c5ab770de2e96993c9e3 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 18 Dec 2009 16:28:12 -0500 Subject: [PATCH 295/670] SUNRPC: Fix the return value in gss_import_sec_context() commit b891e4a05ef6beac85465295a032431577c66b16 upstream. If the context allocation fails, it will return GSS_S_FAILURE, which is neither a valid error code, nor is it even negative. Return ENOMEM instead... Reported-by: Jeff Layton Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/auth_gss/gss_mech_switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index 6efbb0cd3c7c..76e4c6f4ac3c 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c @@ -252,7 +252,7 @@ gss_import_sec_context(const void *input_token, size_t bufsize, struct gss_ctx **ctx_id) { if (!(*ctx_id = kzalloc(sizeof(**ctx_id), GFP_KERNEL))) - return GSS_S_FAILURE; + return -ENOMEM; (*ctx_id)->mech_type = gss_mech_get(mech); return mech->gm_ops From 8064af147be22c82fa805c6af0695c7dc52bb9c5 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 18 Dec 2009 16:28:20 -0500 Subject: [PATCH 296/670] sunrpc: on successful gss error pipe write, don't return error commit 486bad2e40e938cd68fd853b7a9fa3115a9d3a4a upstream. When handling the gssd downcall, the kernel should distinguish between a successful downcall that contains an error code and a failed downcall (i.e. where the parsing failed or some other sort of problem occurred). In the former case, gss_pipe_downcall should be returning the number of bytes written to the pipe instead of an error. In the event of other errors, we generally want the initiating task to retry the upcall so we set msg.errno to -EAGAIN. An unexpected error code here is a bug however, so BUG() in that case. Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/auth_gss/auth_gss.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 129d75ea25d2..9c5a19d9dbce 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -644,7 +644,22 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); if (IS_ERR(p)) { err = PTR_ERR(p); - gss_msg->msg.errno = (err == -EAGAIN) ? -EAGAIN : -EACCES; + switch (err) { + case -EACCES: + gss_msg->msg.errno = err; + err = mlen; + break; + case -EFAULT: + case -ENOMEM: + case -EINVAL: + case -ENOSYS: + gss_msg->msg.errno = -EAGAIN; + break; + default: + printk(KERN_CRIT "%s: bad return from " + "gss_fill_context: %ld\n", __func__, err); + BUG(); + } goto err_release_msg; } gss_msg->ctx = gss_get_ctx(ctx); From d3e4d5f8ccd3dfb33d9f2907b5290509766352ea Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 11 Dec 2009 09:26:11 +0800 Subject: [PATCH 297/670] drm/i915: Update LVDS connector status when receiving ACPI LID event commit a2565377a5c31e25c77c7cabaf6752abe9a2d83a upstream. Dirk reports that nothing is displayed on LVDS when using ubuntu 9.1 after close/reopen the LID. And I also reproduce this issue on another laptop. After some tests and debug, it seems that it is related with that the LVDS status is not updated in time in course of suspend/resume. Now the LID state is used to check whether the LVDS is connected or disconnected. And when the LID is closed, it means that the LVDS is disconnected. When it is reopened, it means that the LVDS is connected. At the same time on some distributions the LID event is also used to put the system into suspend state. When the LID is closed, the system will enter the suspend state. When the LID is reopened, the system will be resumed. In such case when the LID is closed, user-space script will receive the LID notification event and detect the LVDS as disconnected. Then the system will enter the suspended state. When the LID is reopened, the system will be resumed. As the LVDS status is not updated in course of resume, it will cause that the LVDS connector is marked as unused and disabled. After the resume is finished,user-space script will try to configure the display mode for LVDS. But unfortunately as the LVDS status is not updated in time and it is still marked as disconnected, the LVDS and its corresponding CRTC will be disabled again in the function of drm_helper_disable_unused_functions after changing mode for LVDS. So we had better check and update the status of LVDS connector after receiving the LID notication event. Then after the system is resumed from suspended state, we can set the display mode for LVDS correctly. Signed-off-by: Zhao Yakui Reported-by: Dirk Hohndel Reviewed-by: Jesse Barnes Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_lvds.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ecbafd036858..791fded1378d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -546,6 +546,7 @@ typedef struct drm_i915_private { struct timer_list idle_timer; bool busy; u16 orig_clock; + struct drm_connector *int_lvds_connector; } drm_i915_private_t; /** driver private structure attached to each drm_gem_object */ diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 05598ae10c4b..0e0e4b47a7d0 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -679,7 +679,14 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, struct drm_i915_private *dev_priv = container_of(nb, struct drm_i915_private, lid_notifier); struct drm_device *dev = dev_priv->dev; + struct drm_connector *connector = dev_priv->int_lvds_connector; + /* + * check and update the status of LVDS connector after receiving + * the LID nofication event. + */ + if (connector) + connector->status = connector->funcs->detect(connector); if (!acpi_lid_open()) { dev_priv->modeset_on_lid = 1; return NOTIFY_OK; @@ -1085,6 +1092,8 @@ void intel_lvds_init(struct drm_device *dev) DRM_DEBUG("lid notifier registration failed\n"); dev_priv->lid_notifier.notifier_call = NULL; } + /* keep the LVDS connector */ + dev_priv->int_lvds_connector = connector; drm_sysfs_connector_add(connector); return; From d241962850065fe0aabfbe947028a5e5f14ffb45 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 15 Dec 2009 17:50:00 +0100 Subject: [PATCH 298/670] drm/i915: fix order of fence release wrt flushing commit 96b47b65594fe2365f73aede060cb5203561fed3 upstream. i915_gem_object_unbind had the ordering wrong. The other user, i915_gem_object_put_fence_reg already has the correct ordering. Results was usually corrupted pixmaps, especially garbled font glyphs after a suspend/resume (because this evicts everything). I'm still waiting for the feedback from the bug-reporters, but because this obviously fixes a bug (at least for me) I'm already submitting it. Bugzilla: http://bugs.freedesktop.org/show_bug.cgi?id=25406 Signed-off-by: Daniel Vetter Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5ddbd38201b0..2e10b9a0db69 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2010,9 +2010,6 @@ i915_gem_object_unbind(struct drm_gem_object *obj) /* blow away mappings if mapped through GTT */ i915_gem_release_mmap(obj); - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) - i915_gem_clear_fence_reg(obj); - /* Move the object to the CPU domain to ensure that * any possible CPU writes while it's not in the GTT * are flushed when we go to remap it. This will @@ -2028,6 +2025,10 @@ i915_gem_object_unbind(struct drm_gem_object *obj) BUG_ON(obj_priv->active); + /* release the fence reg _after_ flushing */ + if (obj_priv->fence_reg != I915_FENCE_REG_NONE) + i915_gem_clear_fence_reg(obj); + if (obj_priv->agp_mem != NULL) { drm_unbind_agp(obj_priv->agp_mem); drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); From c6939598243bc2dbaece589a8dadb547d9083098 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Jan 2010 18:57:57 +0000 Subject: [PATCH 299/670] drm/i915: Permit pinning whilst the device is 'suspended' commit e3d8affb0d2d95f2da61e30ce86b33177feb91e8 upstream. As pinning (allocating and binding GTT memory) does not actually invoke GPU commands, it is safe, and indeed is attempted, during resumption from suspension: [drm:intel_init_clock_gating] *ERROR* failed to pin power context: -16 Signed-off-by: Chris Wilson Reported-by: Hugh Dickins Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_gem.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2e10b9a0db69..3d75c67fa78c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2571,9 +2571,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) bool retry_alloc = false; int ret; - if (dev_priv->mm.suspended) - return -EBUSY; - if (obj_priv->madv != I915_MADV_WILLNEED) { DRM_ERROR("Attempting to bind a purgeable object\n"); return -EINVAL; From de040919d2c6a9a6a905b629810d2139c0d5f370 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 5 Jan 2010 11:25:05 +0800 Subject: [PATCH 300/670] drm: remove address mask param for drm_pci_alloc() commit e6be8d9d17bd44061116f601fe2609b3ace7aa69 upstream. drm_pci_alloc() has input of address mask for setting pci dma mask on the device, which should be properly setup by drm driver. And leave it as a param for drm_pci_alloc() would cause confusion or mistake would corrupt the correct dma mask setting, as seen on intel hw which set wrong dma mask for hw status page. So remove it from drm_pci_alloc() function. Signed-off-by: Zhenyu Wang Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/ati_pcigart.c | 10 ++++++++-- drivers/gpu/drm/drm_bufs.c | 4 ++-- drivers/gpu/drm/drm_pci.c | 8 +------- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- include/drm/drmP.h | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/ati_pcigart.c b/drivers/gpu/drm/ati_pcigart.c index 628eae3e9b83..a1fce68e3bbe 100644 --- a/drivers/gpu/drm/ati_pcigart.c +++ b/drivers/gpu/drm/ati_pcigart.c @@ -39,8 +39,7 @@ static int drm_ati_alloc_pcigart_table(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) { gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size, - PAGE_SIZE, - gart_info->table_mask); + PAGE_SIZE); if (gart_info->table_handle == NULL) return -ENOMEM; @@ -112,6 +111,13 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); + if (pci_set_dma_mask(dev->pdev, gart_info->table_mask)) { + DRM_ERROR("fail to set dma mask to 0x%Lx\n", + gart_info->table_mask); + ret = 1; + goto done; + } + ret = drm_ati_alloc_pcigart_table(dev, gart_info); if (ret) { DRM_ERROR("cannot allocate PCI GART page!\n"); diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 3d09e304f6f4..8417cc4c43f1 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -326,7 +326,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, * As we're limiting the address to 2^32-1 (or less), * casting it down to 32 bits is no problem, but we * need to point to a 64bit variable first. */ - dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL); + dmah = drm_pci_alloc(dev, map->size, map->size); if (!dmah) { kfree(map); return -ENOMEM; @@ -885,7 +885,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) while (entry->buf_count < count) { - dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful); + dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000); if (!dmah) { /* Set count correctly so we free the proper amount. */ diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 577094fb1995..e68ebf92fa2a 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -47,8 +47,7 @@ /** * \brief Allocate a PCI consistent memory block, for DMA. */ -drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align, - dma_addr_t maxaddr) +drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align) { drm_dma_handle_t *dmah; #if 1 @@ -63,11 +62,6 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali if (align > size) return NULL; - if (pci_set_dma_mask(dev->pdev, maxaddr) != 0) { - DRM_ERROR("Setting pci dma mask failed\n"); - return NULL; - } - dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL); if (!dmah) return NULL; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index e5b138be45fa..4a553adfa4f6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -123,7 +123,7 @@ static int i915_init_phys_hws(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; /* Program Hardware Status Page */ dev_priv->status_page_dmah = - drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); + drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE); if (!dev_priv->status_page_dmah) { DRM_ERROR("Can not allocate hardware status page\n"); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 3d75c67fa78c..df2c625b1fa0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4637,7 +4637,7 @@ int i915_gem_init_phys_object(struct drm_device *dev, phys_obj->id = id; - phys_obj->handle = drm_pci_alloc(dev, size, 0, 0xffffffff); + phys_obj->handle = drm_pci_alloc(dev, size, 0); if (!phys_obj->handle) { ret = -ENOMEM; goto kfree_obj; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 9d3d684103f6..7ad3faa5dde7 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1402,7 +1402,7 @@ extern int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info * gart_info); extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size, - size_t align, dma_addr_t maxaddr); + size_t align); extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah); extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah); From cba0270924c7a6be1f30abd854ebdb3e0df6fb81 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 4 Jan 2010 16:29:30 +0800 Subject: [PATCH 301/670] drm/i915: Enable/disable the dithering for LVDS based on VBT setting commit 898822ce9561ab9b58a7eb60580a162a83dadecd upstream. Enable/disable the dithering for LVDS based on VBT setting. On the 965/g4x platform the dithering flag is defined in LVDS register. And on the ironlake the dithering flag is defined in pipeconf register. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1687edf68795..54e5907723d7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -968,6 +968,8 @@ #define LVDS_PORT_EN (1 << 31) /* Selects pipe B for LVDS data. Must be set on pre-965. */ #define LVDS_PIPEB_SELECT (1 << 30) +/* LVDS dithering flag on 965/g4x platform */ +#define LVDS_ENABLE_DITHER (1 << 25) /* Enable border for unscaled (or aspect-scaled) display */ #define LVDS_BORDER_ENABLE (1 << 15) /* @@ -1737,6 +1739,8 @@ /* Display & cursor control */ +/* dithering flag on Ironlake */ +#define PIPE_ENABLE_DITHER (1 << 4) /* Pipe A */ #define PIPEADSL 0x70000 #define PIPEACONF 0x70008 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f1de53b2f49b..2e7e521ac4da 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3104,7 +3104,20 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, * appropriately here, but we need to look more thoroughly into how * panels behave in the two modes. */ - + /* set the dithering flag */ + if (IS_I965G(dev)) { + if (dev_priv->lvds_dither) { + if (IS_IGDNG(dev)) + pipeconf |= PIPE_ENABLE_DITHER; + else + lvds |= LVDS_ENABLE_DITHER; + } else { + if (IS_IGDNG(dev)) + pipeconf &= ~PIPE_ENABLE_DITHER; + else + lvds &= ~LVDS_ENABLE_DITHER; + } + } I915_WRITE(lvds_reg, lvds); I915_READ(lvds_reg); } From c04fd308e3d6148c3c8bcba688c668569759b29c Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 4 Jan 2010 16:29:31 +0800 Subject: [PATCH 302/670] drm/i915: Make the BPC in FDI rx/transcoder be consistent with that in pipeconf on Ironlake commit 8faf3b317471179c02db339aa80955a2e88c036d upstream. Make the BPC in FDI rx/transcoder be consistent with that in pipeconf on Ironlake. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2e7e521ac4da..d02016dc77dc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1473,6 +1473,10 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B; u32 temp; int tries = 5, j, n; + u32 pipe_bpc; + + temp = I915_READ(pipeconf_reg); + pipe_bpc = temp & PIPE_BPC_MASK; /* XXX: When our outputs are all unaware of DPMS modes other than off * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. @@ -1504,6 +1508,12 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ temp = I915_READ(fdi_rx_reg); + /* + * make the BPC in FDI Rx be consistent with that in + * pipeconf reg. + */ + temp &= ~(0x7 << 16); + temp |= (pipe_bpc << 11); I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE | FDI_SEL_PCDCLK | FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */ @@ -1644,6 +1654,12 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) /* enable PCH transcoder */ temp = I915_READ(transconf_reg); + /* + * make the BPC in transcoder be consistent with + * that in pipeconf reg. + */ + temp &= ~PIPE_BPC_MASK; + temp |= pipe_bpc; I915_WRITE(transconf_reg, temp | TRANS_ENABLE); I915_READ(transconf_reg); @@ -1722,6 +1738,9 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(fdi_tx_reg); temp = I915_READ(fdi_rx_reg); + /* BPC in FDI rx is consistent with that in pipeconf */ + temp &= ~(0x07 << 16); + temp |= (pipe_bpc << 11); I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE); I915_READ(fdi_rx_reg); @@ -1765,7 +1784,12 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) } } } - + temp = I915_READ(transconf_reg); + /* BPC in transcoder is consistent with that in pipeconf */ + temp &= ~PIPE_BPC_MASK; + temp |= pipe_bpc; + I915_WRITE(transconf_reg, temp); + I915_READ(transconf_reg); udelay(100); /* disable PCH DPLL */ From c7e8c269f5d886064af13e7d3eff1324cd78248c Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 4 Jan 2010 16:29:32 +0800 Subject: [PATCH 303/670] drm/i915: Select the correct BPC for LVDS on Ironlake commit e5a95eb778690bc864eb330202d2c1b974caaeb4 upstream. Select the correct BPC for LVDS on Ironlake. If it is 18-bit LVDS panel, the BPC will be 6. When it is 24-bit LVDS panel, the BPC will 8. At the same time the BPC will be 8 when the output device is CRT/HDMI/DP. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d02016dc77dc..406b53271c69 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2901,6 +2901,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* determine panel color depth */ temp = I915_READ(pipeconf_reg); + temp &= ~PIPE_BPC_MASK; + if (is_lvds) { + int lvds_reg = I915_READ(PCH_LVDS); + /* the BPC will be 6 if it is 18-bit LVDS panel */ + if ((lvds_reg & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) + temp |= PIPE_8BPC; + else + temp |= PIPE_6BPC; + } else + temp |= PIPE_8BPC; + I915_WRITE(pipeconf_reg, temp); + I915_READ(pipeconf_reg); switch (temp & PIPE_BPC_MASK) { case PIPE_8BPC: From 0c51b5c49b554e7da4c929e1ee877d9e47ba1eec Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Nov 2009 14:08:52 -0800 Subject: [PATCH 304/670] drm/i915: fix unused var commit 29bd0ae25f8cb96b63560c2cbccec77b425e1603 upstream. drivers/gpu/drm/i915/i915_dma.c: In function 'i915_driver_load': drivers/gpu/drm/i915/i915_dma.c:1114: warning: 'll_base' may be used uninitialized in this function Partly this is because gcc isn't smart enough. But `ll_base' does get used uninitialised in the DRM_DEBUG() call. Cc: Jesse Barnes Cc: Eric Anholt Cc: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 4a553adfa4f6..bc2db7d16d18 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1111,7 +1111,8 @@ static void i915_setup_compression(struct drm_device *dev, int size) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_mm_node *compressed_fb, *compressed_llb; - unsigned long cfb_base, ll_base; + unsigned long cfb_base; + unsigned long ll_base = 0; /* Leave 1M for line length buffer & misc. */ compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0); From fdc08951c6708ecab22102ab404322c4d9de5221 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Fri, 8 Jan 2010 14:43:11 -0800 Subject: [PATCH 305/670] rtc_cmos: convert shutdown to new pnp_driver->shutdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 004731b2c7c658d36bee167cb1e1a399c2cbccc9 upstream. commit abd6633c67925f90775bb74755f9c547e30f1f20 ("pnp: add a shutdown method to pnp drivers") adds shutdown method to bus driver blindly. With it, driver->shutdown is no longer valid. Use pnp_driver->shutdown instead. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=14889 Signed-off-by: OGAWA Hirofumi Reported-by: Malte Schröder Cc: "Rafael J. Wysocki" Cc: Bjorn Helgaas Cc: David Hardeman Cc: Dmitry Torokhov Cc: Alessandro Zummo Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-cmos.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index f7a4701bf863..473e5f25e3dd 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -1099,9 +1099,9 @@ static int cmos_pnp_resume(struct pnp_dev *pnp) #define cmos_pnp_resume NULL #endif -static void cmos_pnp_shutdown(struct device *pdev) +static void cmos_pnp_shutdown(struct pnp_dev *pnp) { - if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev)) + if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev)) return; cmos_do_shutdown(); @@ -1120,15 +1120,12 @@ static struct pnp_driver cmos_pnp_driver = { .id_table = rtc_ids, .probe = cmos_pnp_probe, .remove = __exit_p(cmos_pnp_remove), + .shutdown = cmos_pnp_shutdown, /* flag ensures resume() gets called, and stops syslog spam */ .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, .suspend = cmos_pnp_suspend, .resume = cmos_pnp_resume, - .driver = { - .name = (char *)driver_name, - .shutdown = cmos_pnp_shutdown, - } }; #endif /* CONFIG_PNP */ From 6abb6ac30148ca47ff66c917ecd83df975daccbf Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 8 Jan 2010 14:43:08 -0800 Subject: [PATCH 306/670] drivers/cpuidle/governors/menu.c: fix undefined reference to `__udivdi3' commit 5787536edf18e33d06e2bf038bfd0910f4def213 upstream. menu: use proper 64 bit math The new menu governor is incorrectly doing a 64 bit divide. Compile tested only Signed-off-by: Stephen Hemminger Cc: Arjan van de Ven Cc: Len Brown Cc: Venkatesh Pallipadi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/cpuidle/governors/menu.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 68104434ebb5..73655aeb3a60 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -18,6 +18,7 @@ #include #include #include +#include #define BUCKETS 12 #define RESOLUTION 1024 @@ -169,6 +170,12 @@ static DEFINE_PER_CPU(struct menu_device, menu_devices); static void menu_update(struct cpuidle_device *dev); +/* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */ +static u64 div_round64(u64 dividend, u32 divisor) +{ + return div_u64(dividend + (divisor / 2), divisor); +} + /** * menu_select - selects the next idle state to enter * @dev: the CPU @@ -209,9 +216,8 @@ static int menu_select(struct cpuidle_device *dev) data->correction_factor[data->bucket] = RESOLUTION * DECAY; /* Make sure to round up for half microseconds */ - data->predicted_us = DIV_ROUND_CLOSEST( - data->expected_us * data->correction_factor[data->bucket], - RESOLUTION * DECAY); + data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket], + RESOLUTION * DECAY); /* * We want to default to C1 (hlt), not to busy polling From 21f7654aa8eac2e3c47097497aee440c222bd9ed Mon Sep 17 00:00:00 2001 From: Dave Anderson Date: Fri, 8 Jan 2010 14:42:50 -0800 Subject: [PATCH 307/670] cgroups: fix 2.6.32 regression causing BUG_ON() in cgroup_diput() commit bd4f490a079730aadfaf9a728303ea0135c01945 upstream. The LTP cgroup test suite generates a "kernel BUG at kernel/cgroup.c:790!" here in cgroup_diput(): /* * if we're getting rid of the cgroup, refcount should ensure * that there are no pidlists left. */ BUG_ON(!list_empty(&cgrp->pidlists)); The cgroup pidlist rework in 2.6.32 generates the BUG_ON, which is caused when pidlist_array_load() calls cgroup_pidlist_find(): (1) if a matching cgroup_pidlist is found, it down_write's the mutex of the pre-existing cgroup_pidlist, and increments its use_count. (2) if no matching cgroup_pidlist is found, then a new one is allocated, it down_write's its mutex, and the use_count is set to 0. (3) the matching, or new, cgroup_pidlist gets returned back to pidlist_array_load(), which increments its use_count -- regardless whether new or pre-existing -- and up_write's the mutex. So if a matching list is ever encountered by cgroup_pidlist_find() during the life of a cgroup directory, it results in an inflated use_count value, preventing it from ever getting released by cgroup_release_pid_array(). Then if the directory is subsequently removed, cgroup_diput() hits the BUG_ON() when it finds that the directory's cgroup is still populated with a pidlist. The patch simply removes the use_count increment when a matching pidlist is found by cgroup_pidlist_find(), because it gets bumped by the calling pidlist_array_load() function while still protected by the list's mutex. Signed-off-by: Dave Anderson Reviewed-by: Li Zefan Acked-by: Ben Blum Cc: Paul Menage Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 0249f4be9b5c..1fbcc748044a 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2468,7 +2468,6 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp, /* make sure l doesn't vanish out from under us */ down_write(&l->mutex); mutex_unlock(&cgrp->pidlist_mutex); - l->use_count++; return l; } } From f21efc5709f5e0285389a10ede7e3cef54977029 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 8 Jan 2010 14:42:47 -0800 Subject: [PATCH 308/670] lib/rational.c needs module.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7ee3aebe31d2cb22c84e1c8f48182947b13a3607 upstream. lib/rational.c:62: warning: data definition has no type or storage class lib/rational.c:62: warning: type defaults to 'int' in declaration of 'EXPORT_SYMBOL' lib/rational.c:62: warning: parameter names (without types) in function declaration Signed-off-by: Sascha Hauer Signed-off-by: Uwe Kleine-König Acked-by: WANG Cong Cc: Oskar Schirmer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/rational.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/rational.c b/lib/rational.c index b3c099b5478e..3ed247b80662 100644 --- a/lib/rational.c +++ b/lib/rational.c @@ -7,6 +7,7 @@ */ #include +#include /* * calculate best rational approximation for a given fraction From ecac13f4da35b215152e8dab78470662e1b9685d Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Fri, 8 Jan 2010 14:42:36 -0800 Subject: [PATCH 309/670] dma-debug: allow DMA_BIDIRECTIONAL mappings to be synced with DMA_FROM_DEVICE and commit 42d53b4ff7d61487d18274ebdf1f70c1aef6f122 upstream. There is no need to perform full BIDIR sync (copying the buffers in case of swiotlb and similar schemes) if we know that the owner (CPU or device) hasn't altered the data. Addresses the false-positive reported at http://bugzilla.kernel.org/show_bug.cgi?id=14169 Signed-off-by: Krzysztof Halasa Cc: David Miller Cc: Joerg Roedel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/dma-debug.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 5a77c7cfb59e..084e879d42cc 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -913,6 +913,9 @@ static void check_sync(struct device *dev, ref->size); } + if (entry->direction == DMA_BIDIRECTIONAL) + goto out; + if (ref->direction != entry->direction) { err_printk(dev, entry, "DMA-API: device driver syncs " "DMA memory with different direction " @@ -923,9 +926,6 @@ static void check_sync(struct device *dev, dir2name[ref->direction]); } - if (entry->direction == DMA_BIDIRECTIONAL) - goto out; - if (to_cpu && !(entry->direction == DMA_FROM_DEVICE) && !(ref->direction == DMA_TO_DEVICE)) err_printk(dev, entry, "DMA-API: device driver syncs " @@ -948,7 +948,6 @@ static void check_sync(struct device *dev, out: put_hash_bucket(bucket, &flags); - } void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, From 0696a3b5e0bb2b214b4b8293ce214f3a2e113bda Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 8 Jan 2010 14:42:52 -0800 Subject: [PATCH 310/670] kernel/signal.c: fix kernel information leak with print-fatal-signals=1 commit b45c6e76bc2c72f6426c14bed64fdcbc9bf37cb0 upstream. When print-fatal-signals is enabled it's possible to dump any memory reachable by the kernel to the log by simply jumping to that address from user space. Or crash the system if there's some hardware with read side effects. The fatal signals handler will dump 16 bytes at the execution address, which is fully controlled by ring 3. In addition when something jumps to a unmapped address there will be up to 16 additional useless page faults, which might be potentially slow (and at least is not very efficient) Fortunately this option is off by default and only there on i386. But fix it by checking for kernel addresses and also stopping when there's a page fault. Signed-off-by: Andi Kleen Cc: Ingo Molnar Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/signal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/signal.c b/kernel/signal.c index 6705320784fd..4d0658dda0e5 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -939,7 +939,8 @@ static void print_fatal_signal(struct pt_regs *regs, int signr) for (i = 0; i < 16; i++) { unsigned char insn; - __get_user(insn, (unsigned char *)(regs->ip + i)); + if (get_user(insn, (unsigned char *)(regs->ip + i))) + break; printk("%02x ", insn); } } From 0798abf9dc8157145d7136f751b6a16aaac1b1e8 Mon Sep 17 00:00:00 2001 From: Anna Lemehova Date: Fri, 8 Jan 2010 14:42:58 -0800 Subject: [PATCH 311/670] mmc_block: add dev_t initialization check commit 7d92df692994472cab6045bbd9d0e2c4afa4365f upstream. When a card is removed before mmc_blk_probe() has called add_disk(), then the minor field is uninitialized and has value 0. This caused mmc_blk_put() to always release devidx 0 even if 0 was still in use. Then the next mmc_blk_probe() used the first free idx of 0, which oopses in sysfs, since it is used by another card. Signed-off-by: Anna Lemehova Signed-off-by: Adrian Hunter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/card/block.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 85f0e8cd875b..5988573bb843 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -85,7 +85,12 @@ static void mmc_blk_put(struct mmc_blk_data *md) mutex_lock(&open_lock); md->usage--; if (md->usage == 0) { + int devmaj = MAJOR(disk_devt(md->disk)); int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT; + + if (!devmaj) + devidx = md->disk->first_minor >> MMC_SHIFT; + __clear_bit(devidx, dev_use); put_disk(md->disk); From 0c74f45acfacc220adfa9e035ffeb3d5e8f9f0d8 Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Fri, 8 Jan 2010 14:42:59 -0800 Subject: [PATCH 312/670] mmc_block: fix probe error cleanup bug commit 0a74ff29b8dd8b748f8856352f9a9b5c6cc362cc upstream. If mmc_blk_set_blksize() fails mmc_blk_probe() the request queue and its thread have been set up and they need to be shut down properly before putting the disk. Signed-off-by: Jarkko Lavinen Signed-off-by: Adrian Hunter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/card/block.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 5988573bb843..ee879117017f 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -618,6 +618,7 @@ static int mmc_blk_probe(struct mmc_card *card) return 0; out: + mmc_cleanup_queue(&md->queue); mmc_blk_put(md); return err; From e0abcea649db45223c7df49df5db04dc1aa3a271 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 8 Jan 2010 14:43:00 -0800 Subject: [PATCH 313/670] mmc_block: fix queue cleanup commit 5fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740 upstream. The main bug was that 'blk_cleanup_queue()' was called while the block device could still be in use, for example, because the card was removed while files were still open. In addition, to be sure that 'mmc_request()' will get called for all new requests (so it can error them out), the queue is emptied during cleanup. This is done after the worker thread is stopped to avoid racing with it. Finally, it is not a device error for this to be happening, so quiet the (sometimes very many) error messages. Signed-off-by: Adrian Hunter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/card/block.c | 2 ++ drivers/mmc/card/queue.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index ee879117017f..1f552c6e7579 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -91,6 +91,8 @@ static void mmc_blk_put(struct mmc_blk_data *md) if (!devmaj) devidx = md->disk->first_minor >> MMC_SHIFT; + blk_cleanup_queue(md->queue.queue); + __clear_bit(devidx, dev_use); put_disk(md->disk); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 49e582356c65..c5a7a855f4b1 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -90,9 +90,10 @@ static void mmc_request(struct request_queue *q) struct request *req; if (!mq) { - printk(KERN_ERR "MMC: killing requests for dead queue\n"); - while ((req = blk_fetch_request(q)) != NULL) + while ((req = blk_fetch_request(q)) != NULL) { + req->cmd_flags |= REQ_QUIET; __blk_end_request_all(req, -EIO); + } return; } @@ -223,17 +224,18 @@ void mmc_cleanup_queue(struct mmc_queue *mq) struct request_queue *q = mq->queue; unsigned long flags; - /* Mark that we should start throwing out stragglers */ - spin_lock_irqsave(q->queue_lock, flags); - q->queuedata = NULL; - spin_unlock_irqrestore(q->queue_lock, flags); - /* Make sure the queue isn't suspended, as that will deadlock */ mmc_queue_resume(mq); /* Then terminate our worker thread */ kthread_stop(mq->thread); + /* Empty the queue */ + spin_lock_irqsave(q->queue_lock, flags); + q->queuedata = NULL; + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + if (mq->bounce_sg) kfree(mq->bounce_sg); mq->bounce_sg = NULL; @@ -245,8 +247,6 @@ void mmc_cleanup_queue(struct mmc_queue *mq) kfree(mq->bounce_buf); mq->bounce_buf = NULL; - blk_cleanup_queue(mq->queue); - mq->card = NULL; } EXPORT_SYMBOL(mmc_cleanup_queue); From 5bb4e8409e9d28cc7cf6900fd68840604480caf4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 12 Jan 2010 14:00:11 +0100 Subject: [PATCH 314/670] ALSA: hda - Fix ALC861-VD capture source mixer commit 9c0afc861a7228f718cb6a79fa7f9d46bf9ff300 upstream. The capture source or input source mixer element wasn't created properly for ALC861-VD codec due to the wrong NID passed to alc_auto_create_input_ctls(). References: Novell bnc#568305 http://bugzilla.novell.com/show_bug.cgi?id=568305 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e40d31f1b098..a4cb18341d12 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -15323,7 +15323,7 @@ static struct alc_config_preset alc861vd_presets[] = { static int alc861vd_auto_create_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { - return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0); + return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x22, 0); } From 0385cc0cdb6ed37d433dcf1f2e3f4451326c7c07 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Sat, 9 Jan 2010 01:22:29 -0500 Subject: [PATCH 315/670] ALSA: ac97: Add Dell Dimension 2400 to Headphone/Line Jack Sense blacklist commit af9a75dd1a1f8a9aa406466cc8bb16208120488a upstream. This model needs both 'Headphone Jack Sense' and 'Line Jack Sense' muted for audible playback, so just add it to the ad1981 jack sense blacklist. Tested-by: Pete Signed-off-by: Daniel T Chen Signed-off-by: Jaroslav Kysela Signed-off-by: Greg Kroah-Hartman --- sound/pci/ac97/ac97_patch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 7337abdbe4e3..67ca4403c1c6 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1870,6 +1870,7 @@ static unsigned int ad1981_jacks_blacklist[] = { 0x10140554, /* Thinkpad T42p/R50p */ 0x10140567, /* Thinkpad T43p 2668-G7U */ 0x10140581, /* Thinkpad X41-2527 */ + 0x10280160, /* Dell Dimension 2400 */ 0x104380b0, /* Asus A7V8X-MX */ 0x11790241, /* Toshiba Satellite A-15 S127 */ 0x144dc01a, /* Samsung NP-X20C004/SEG */ From cf99848730bff6df4f473daa089966372c131147 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Sun, 27 Dec 2009 15:48:40 -0500 Subject: [PATCH 316/670] ALSA: atiixp: Specify codec for Foxconn RC4107MA-RS2 commit dfb12eeb0f04b37e5eb3858864d074af4ecd2ac7 upstream. BugLink: https://bugs.launchpad.net/ubuntu/+bug/498863 This mainboard needs ac97_codec=0. Tested-by: Apoorv Parle Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/atiixp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index d6752dff2a44..42b4fbbd8e2b 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -297,6 +297,7 @@ static struct pci_device_id snd_atiixp_ids[] = { MODULE_DEVICE_TABLE(pci, snd_atiixp_ids); static struct snd_pci_quirk atiixp_quirks[] __devinitdata = { + SND_PCI_QUIRK(0x105b, 0x0c81, "Foxconn RC4107MA-RS2", 0), SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0), { } /* terminator */ }; From 954c8ef2187e4fd5d870ff0d2d909deebf69f90e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 7 Jan 2010 16:29:20 +0000 Subject: [PATCH 317/670] ASoC: Fix WM8350 DSP mode B configuration commit 5ee518ecbcb5934e284ea51a19a939c891f5f7ea upstream. We need to set the LRCLK inversion bit to select DSP mode. Signed-off-by: Mark Brown Acked-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8350.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 593d5b9c9f03..2089fe7d1ba6 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -925,7 +925,7 @@ static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) iface |= 0x3 << 8; break; case SND_SOC_DAIFMT_DSP_B: - iface |= 0x3 << 8; /* lg not sure which mode */ + iface |= 0x3 << 8 | WM8350_AIF_LRCLK_INV; break; default: return -EINVAL; From 635b4f931d32118a7bda1b6b7622883bc7e0dcab Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 8 Jan 2010 17:31:24 +0100 Subject: [PATCH 318/670] netfilter: ebtables: enforce CAP_NET_ADMIN commit dce766af541f6605fa9889892c0280bab31c66ab upstream. normal users are currently allowed to set/modify ebtables rules. Restrict it to processes with CAP_NET_ADMIN. Note that this cannot be reproduced with unmodified ebtables binary because it uses SOCK_RAW. Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- net/bridge/netfilter/ebtables.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index bd1c65425d4f..0b7f262cd148 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1406,6 +1406,9 @@ static int do_ebt_set_ctl(struct sock *sk, { int ret; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + switch(cmd) { case EBT_SO_SET_ENTRIES: ret = do_replace(sock_net(sk), user, len); @@ -1425,6 +1428,9 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) struct ebt_replace tmp; struct ebt_table *t; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&tmp, user, sizeof(tmp))) return -EFAULT; From 545b02070bb58430c8ce96369bdbbe15e4aef1f7 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 7 Jan 2010 18:33:18 +0100 Subject: [PATCH 319/670] netfilter: nf_ct_ftp: fix out of bounds read in update_nl_seq() commit aaff23a95aea5f000895f50d90e91f1e2f727002 upstream. As noticed by Dan Carpenter , update_nl_seq() currently contains an out of bounds read of the seq_aft_nl array when looking for the oldest sequence number position. Fix it to only compare valid positions. Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_ftp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 5509dd1f14cf..7dfd469c0cf8 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -323,24 +323,24 @@ static void update_nl_seq(struct nf_conn *ct, u32 nl_seq, struct nf_ct_ftp_master *info, int dir, struct sk_buff *skb) { - unsigned int i, oldest = NUM_SEQ_TO_REMEMBER; + unsigned int i, oldest; /* Look for oldest: if we find exact match, we're done. */ for (i = 0; i < info->seq_aft_nl_num[dir]; i++) { if (info->seq_aft_nl[dir][i] == nl_seq) return; - - if (oldest == info->seq_aft_nl_num[dir] || - before(info->seq_aft_nl[dir][i], - info->seq_aft_nl[dir][oldest])) - oldest = i; } if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) { info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq; - } else if (oldest != NUM_SEQ_TO_REMEMBER && - after(nl_seq, info->seq_aft_nl[dir][oldest])) { - info->seq_aft_nl[dir][oldest] = nl_seq; + } else { + if (before(info->seq_aft_nl[dir][0], info->seq_aft_nl[dir][1])) + oldest = 0; + else + oldest = 1; + + if (after(nl_seq, info->seq_aft_nl[dir][oldest])) + info->seq_aft_nl[dir][oldest] = nl_seq; } } From 4052fbfb24712ee7bb31c4c813d551712d7a4e4e Mon Sep 17 00:00:00 2001 From: Yong Wang Date: Sun, 10 Jan 2010 20:52:34 +0100 Subject: [PATCH 320/670] hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs commit 1fe63ab47a617ee95f562eaa7ddbbc59981ff8c6 upstream. The max junction temperature of Atom N450/D410/D510 CPUs is 100 degrees Celsius. Since these CPUs are always coupled with Intel NM10 chipset in one package, the best way to verify whether an Atom CPU is N450/D410/D510 is to check the host bridge device. Signed-off-by: Yong Wang Acked-by: Huaxu Wan Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/coretemp.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 700e93adeb33..c1f7ea024581 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -374,7 +374,7 @@ config SENSORS_GL520SM config SENSORS_CORETEMP tristate "Intel Core/Core2/Atom temperature sensor" - depends on X86 && EXPERIMENTAL + depends on X86 && PCI && EXPERIMENTAL help If you say yes here you get support for the temperature sensor inside your CPU. Most of the family 6 CPUs diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index caef39cda8c8..2d7bceeed0bc 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,7 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * int usemsr_ee = 1; int err; u32 eax, edx; + struct pci_dev *host_bridge; /* Early chips have no MSR for TjMax */ @@ -168,11 +170,21 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * usemsr_ee = 0; } - /* Atoms seems to have TjMax at 90C */ + /* Atom CPUs */ if (c->x86_model == 0x1c) { usemsr_ee = 0; - tjmax = 90000; + + host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); + + if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL + && (host_bridge->device == 0xa000 /* NM10 based nettop */ + || host_bridge->device == 0xa010)) /* NM10 based netbook */ + tjmax = 100000; + else + tjmax = 90000; + + pci_dev_put(host_bridge); } if ((c->x86_model > 0xe) && (usemsr_ee)) { From a61dcb0c6ac2aac895a17b37dcbe57b249a3d826 Mon Sep 17 00:00:00 2001 From: Roger Blofeld Date: Sun, 10 Jan 2010 20:52:32 +0100 Subject: [PATCH 321/670] hwmon: (adt7462) Fix pin 28 monitoring commit bb595c923bc51dff9cdd112de18deb57ac7945d2 upstream. The ADT7462_PIN28_VOLT value is a 4-bit field, so the corresponding shift must be 4. Signed-off-by: Roger Blofeld Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/adt7462.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index 1852f27bac51..262c133048ce 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -97,7 +97,7 @@ I2C_CLIENT_INSMOD_1(adt7462); #define ADT7462_PIN24_SHIFT 6 #define ADT7462_PIN26_VOLT_INPUT 0x08 #define ADT7462_PIN25_VOLT_INPUT 0x20 -#define ADT7462_PIN28_SHIFT 6 /* cfg3 */ +#define ADT7462_PIN28_SHIFT 4 /* cfg3 */ #define ADT7462_PIN28_VOLT 0x5 #define ADT7462_REG_ALARM1 0xB8 From 38c4d8d579c4e752e03edcdd2e96a49787d71a3a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 6 Jan 2010 18:03:36 +0100 Subject: [PATCH 322/670] quota: Fix dquot_transfer for filesystems different from ext4 commit 05b5d898235401c489c68e1f3bc5706a29ad5713 upstream. Commit fd8fbfc1 modified the way we find amount of reserved space belonging to an inode. The amount of reserved space is checked from dquot_transfer and thus inode_reserved_space gets called even for filesystems that don't provide get_reserved_space callback which results in a BUG. Fix the problem by checking get_reserved_space callback and return 0 if the filesystem does not provide it. CC: Dmitry Monakhov Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/quota/dquot.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index c4d07a803bd0..253498739978 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -1425,6 +1425,9 @@ static void inode_sub_rsv_space(struct inode *inode, qsize_t number) static qsize_t inode_get_rsv_space(struct inode *inode) { qsize_t ret; + + if (!inode->i_sb->dq_op->get_reserved_space) + return 0; spin_lock(&inode->i_lock); ret = *inode_reserved_space(inode); spin_unlock(&inode->i_lock); From a111c28a5d47bc15ed6b644a0b7c69d748c1bdb2 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 17 Dec 2009 13:57:09 +0000 Subject: [PATCH 323/670] xen: fix hang on suspend. commit c5cae661d6cf808b6984762f763261adf35f3eb7 upstream. In 65f63384 "xen: improve error handling in do_suspend" I said: - xs_suspend()/xs_resume() and dpm_suspend_noirq()/dpm_resume_noirq() were not nested in the obvious way. and changed the ordering of the calls as so: BEFORE AFTER xs_suspend dpm_suspend_noirq dpm_suspend_noirq xs_suspend *SUSPEND* *SUSPEND* dpm_resume_noirq dpm_resume_noirq xs_resume xs_resume Clearly this is not an improvement and I was talking rubbish. In particular the new ordering is susceptible to a hang if a xenstore write is in progress at the point at which the suspend kicks in. When the suspend process calls xs_suspend it tries to take the request_mutex but if a write is in progress it could be looping in xenbus_xs.c:read_reply() waiting for something to arrive on &xs_state.reply_list while holding the request_mutex (taken in the caller of read_reply). However if we have done dpm_suspend_noirq before xs_suspend then we won't get any more xenstore interrupts and process_msg() will never be woken up to add anything to the reply_list. Fix this by calling xs_suspend before dpm_suspend_noirq. If dpm_suspend_noirq fails then make sure we go through the xs_suspend_cancel() code path. Signed-off-by: Ian Campbell Acked-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman --- drivers/xen/manage.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index c4997930afc7..5d42d55e299b 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -102,15 +102,15 @@ static void do_suspend(void) goto out_thaw; } + printk(KERN_DEBUG "suspending xenstore...\n"); + xs_suspend(); + err = dpm_suspend_noirq(PMSG_SUSPEND); if (err) { printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); goto out_resume; } - printk(KERN_DEBUG "suspending xenstore...\n"); - xs_suspend(); - err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); dpm_resume_noirq(PMSG_RESUME); @@ -120,13 +120,13 @@ static void do_suspend(void) cancelled = 1; } +out_resume: if (!cancelled) { xen_arch_resume(); xs_resume(); } else xs_suspend_cancel(); -out_resume: dpm_resume_end(PMSG_RESUME); /* Make sure timer events get retriggered on all CPUs */ From fc95845f174a07d4200a30681067d22c9e34723c Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 8 Jan 2010 10:04:30 -0800 Subject: [PATCH 324/670] iwlwifi: fix iwl_queue_used bug when read_ptr == write_ptr commit c8106d7625a58ee4387cb2efe3e82320ad44b467 upstream. When txq read_ptr equals to write_ptr, iwl_queue_used should always return false. Because there is no used TFD in this case. This is a complementary fix to the fix already included in commit "iwl3945: fix panic in iwl3945 driver". Both fixes are needed to address the panic below. This problem was discussed on linux-wireless in http://thread.gmane.org/gmane.linux.kernel.wireless.general/43568 <1>[ 7290.414172] IP: [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.414205] PGD 0 <1>[ 7290.414214] Thread overran stack, or stack corrupted <0>[ 7290.414229] Oops: 0002 [#1] PREEMPT SMP <0>[ 7290.414246] last sysfs file: /sys/devices/platform/coretemp.1/temp1_input <4>[ 7290.414265] CPU 0 <4>[ 7290.414274] Modules linked in: af_packet nfsd usb_storage usb_libusual cpufreq_powersave exportfs cpufreq_conservative iwl3945 nfs cpufreq_userspace snd_hda_codec_realtek acpi_cpufreq uvcvideo lockd iwlcore snd_hda_intel joydev coretemp nfs_acl videodev snd_hda_codec mac80211 v4l1_compat snd_hwdep sbp2 v4l2_compat_ioctl32 uhci_hcd psmouse auth_rpcgss ohci1394 cfg80211 ehci_hcd video ieee1394 snd_pcm serio_raw battery ac nvidia(P) usbcore output sunrpc evdev lirc_ene0100 snd_page_alloc rfkill tg3 libphy fuse lzo lzo_decompress lzo_compress <6>[ 7290.414486] Pid: 0, comm: swapper Tainted: P 2.6.32-rc8-wl #213 Aspire 5720 <6>[ 7290.414507] RIP: 0010:[] [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <6>[ 7290.414541] RSP: 0018:ffff880002203d60 EFLAGS: 00010246 <6>[ 7290.414557] RAX: 000000000000004f RBX: ffff880064c11600 RCX: 0000000000000013 <6>[ 7290.414576] RDX: ffffffffa0ddcf20 RSI: ffff8800512b7008 RDI: 0000000000000038 <6>[ 7290.414596] RBP: ffff880002203dd0 R08: 0000000000000000 R09: 0000000000000100 <6>[ 7290.414616] R10: 0000000000000001 R11: 0000000000000000 R12: 00000000000000a0 <6>[ 7290.414635] R13: 0000000000000002 R14: 0000000000000013 R15: 0000000000020201 <6>[ 7290.414655] FS: 0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000 <6>[ 7290.414677] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b <6>[ 7290.414693] CR2: 0000000000000041 CR3: 0000000001001000 CR4: 00000000000006f0 <6>[ 7290.414712] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 <6>[ 7290.414732] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 <4>[ 7290.414752] Process swapper (pid: 0, threadinfo ffffffff81524000, task ffffffff81528b60) <0>[ 7290.414772] Stack: <4>[ 7290.414780] ffff880002203da0 0000000000000046 0000000000000000 0000000000000046 <4>[ 7290.414804] <0> 0000000000000282 0000000000000282 0000000000000282 ffff880064c12010 <4>[ 7290.414830] <0> ffff880002203db0 ffff880064c11600 ffff880064c12e50 ffff8800512b7000 <0>[ 7290.414858] Call Trace: <0>[ 7290.414867] <4>[ 7290.414884] [] iwl3945_irq_tasklet+0x657/0x1740 [iwl3945] <4>[ 7290.414910] [] ? _spin_unlock+0x30/0x60 <4>[ 7290.414931] [] tasklet_action+0x101/0x110 <4>[ 7290.414950] [] __do_softirq+0xc0/0x160 <4>[ 7290.414968] [] call_softirq+0x1c/0x30 <4>[ 7290.414986] [] do_softirq+0x75/0xb0 <4>[ 7290.415003] [] irq_exit+0x95/0xa0 <4>[ 7290.415020] [] do_IRQ+0x77/0xf0 <4>[ 7290.415038] [] ret_from_intr+0x0/0xf <0>[ 7290.415052] <4>[ 7290.415067] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415087] [] ? acpi_idle_enter_bm+0x27a/0x2a5 <4>[ 7290.415107] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415130] [] ? cpuidle_idle_call+0x93/0xf0 <4>[ 7290.415149] [] ? cpu_idle+0xa7/0x110 <4>[ 7290.415168] [] ? rest_init+0x75/0x80 <4>[ 7290.415187] [] ? start_kernel+0x3a7/0x3b3 <4>[ 7290.415206] [] ? x86_64_start_reservations+0x125/0x129 <4>[ 7290.415227] [] ? x86_64_start_kernel+0xe4/0xeb <0>[ 7290.415243] Code: 00 41 39 ce 0f 8d e8 01 00 00 48 8b 47 40 48 63 d2 48 69 d2 98 00 00 00 4c 8b 04 02 48 c7 c2 20 cf dd a0 49 8d 78 38 49 8d 40 4f 47 09 00 c6 47 0c 00 c6 47 0f 00 c6 47 12 00 c6 47 15 00 49 <1>[ 7290.415382] RIP [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.415410] RSP <0>[ 7290.415421] CR2: 0000000000000041 <4>[ 7290.415436] ---[ end trace ec46807277caa515 ]--- <0>[ 7290.415450] Kernel panic - not syncing: Fatal exception in interrupt <4>[ 7290.415468] Pid: 0, comm: swapper Tainted: P D 2.6.32-rc8-wl #213 <4>[ 7290.415486] Call Trace: <4>[ 7290.415495] [] panic+0x7d/0x13a <4>[ 7290.415519] [] oops_end+0xda/0xe0 <4>[ 7290.415538] [] no_context+0xea/0x250 <4>[ 7290.415557] [] ? select_task_rq_fair+0x511/0x780 <4>[ 7290.415578] [] __bad_area_nosemaphore+0x125/0x1e0 <4>[ 7290.415597] [] ? __enqueue_entity+0x7c/0x80 <4>[ 7290.415616] [] ? enqueue_task_fair+0x111/0x150 <4>[ 7290.415636] [] bad_area_nosemaphore+0xe/0x10 <4>[ 7290.415656] [] do_page_fault+0x26a/0x320 <4>[ 7290.415674] [] page_fault+0x1f/0x30 <4>[ 7290.415697] [] ? iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.415723] [] iwl3945_irq_tasklet+0x657/0x1740 [iwl3945] <4>[ 7290.415746] [] ? _spin_unlock+0x30/0x60 <4>[ 7290.415764] [] tasklet_action+0x101/0x110 <4>[ 7290.415783] [] __do_softirq+0xc0/0x160 <4>[ 7290.415801] [] call_softirq+0x1c/0x30 <4>[ 7290.415818] [] do_softirq+0x75/0xb0 <4>[ 7290.415835] [] irq_exit+0x95/0xa0 <4>[ 7290.415852] [] do_IRQ+0x77/0xf0 <4>[ 7290.415869] [] ret_from_intr+0x0/0xf <4>[ 7290.415883] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415911] [] ? acpi_idle_enter_bm+0x27a/0x2a5 <4>[ 7290.415931] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415952] [] ? cpuidle_idle_call+0x93/0xf0 <4>[ 7290.415971] [] ? cpu_idle+0xa7/0x110 <4>[ 7290.415989] [] ? rest_init+0x75/0x80 <4>[ 7290.416007] [] ? start_kernel+0x3a7/0x3b3 <4>[ 7290.416026] [] ? x86_64_start_reservations+0x125/0x129 <4>[ 7290.416047] [] ? x86_64_start_kernel+0xe4/0xeb Reported-by: Maxim Levitsky Tested-by: Maxim Levitsky Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c2d9b7a5ef64..cea2ee25722c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -703,7 +703,7 @@ extern void iwl_txq_ctx_stop(struct iwl_priv *priv); extern int iwl_queue_space(const struct iwl_queue *q); static inline int iwl_queue_used(const struct iwl_queue *q, int i) { - return q->write_ptr > q->read_ptr ? + return q->write_ptr >= q->read_ptr ? (i >= q->read_ptr && i < q->write_ptr) : !(i < q->read_ptr && i >= q->write_ptr); } From e6efac7b7c4ce45d40f5e07d3105e07704e95673 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 4 Jan 2010 10:40:39 -0500 Subject: [PATCH 325/670] ath5k: Fix eeprom checksum check for custom sized eeproms commit 359207c687cc8f4f9845c8dadd0d6dabad44e584 upstream. Commit 8bf3d79bc401ca417ccf9fc076d3295d1a71dbf5 enabled EEPROM checksum checks to avoid bogus bug reports but failed to address updating the code to consider devices with custom EEPROM sizes. Devices with custom sized EEPROMs have the upper limit size stuffed in the EEPROM. Use this as the upper limit instead of the static default size. In case of a checksum error also provide back the max size and whether or not this was the default size or a custom one. If the EEPROM is busted we add a failsafe check to ensure we don't loop forever or try to read bogus areas of hardware. This closes bug 14874 http://bugzilla.kernel.org/show_bug.cgi?id=14874 Cc: David Quan Cc: Stephen Beahm Reported-by: Joshua Covington Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath5k/eeprom.c | 32 ++++++++++++++++++++++--- drivers/net/wireless/ath/ath5k/eeprom.h | 8 +++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 791885262602..9a96550006ad 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -97,7 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; int ret; u16 val; - u32 cksum, offset; + u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; /* * Read values from EEPROM and store them in the capability structure @@ -116,12 +116,38 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) * Validate the checksum of the EEPROM date. There are some * devices with invalid EEPROMs. */ - for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { + AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val); + if (val) { + eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) << + AR5K_EEPROM_SIZE_ENDLOC_SHIFT; + AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val); + eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE; + + /* + * Fail safe check to prevent stupid loops due + * to busted EEPROMs. XXX: This value is likely too + * big still, waiting on a better value. + */ + if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) { + ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: " + "%d (0x%04x) max expected: %d (0x%04x)\n", + eep_max, eep_max, + 3 * AR5K_EEPROM_INFO_MAX, + 3 * AR5K_EEPROM_INFO_MAX); + return -EIO; + } + } + + for (cksum = 0, offset = 0; offset < eep_max; offset++) { AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); cksum ^= val; } if (cksum != AR5K_EEPROM_INFO_CKSUM) { - ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); + ATH5K_ERR(ah->ah_sc, "Invalid EEPROM " + "checksum: 0x%04x eep_max: 0x%04x (%s)\n", + cksum, eep_max, + eep_max == AR5K_EEPROM_INFO_MAX ? + "default size" : "custom size"); return -EIO; } diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 0123f3521a0b..473a483bb9c3 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -37,6 +37,14 @@ #define AR5K_EEPROM_RFKILL_POLARITY_S 1 #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ + +/* FLASH(EEPROM) Defines for AR531X chips */ +#define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */ +#define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */ +#define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0 +#define AR5K_EEPROM_SIZE_UPPER_SHIFT 4 +#define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12 + #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) From 724ad42667b42b363bbef867d1c31850b599fecc Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 4 Jan 2010 11:37:39 -0500 Subject: [PATCH 326/670] cfg80211: fix syntax error on user regulatory hints commit e12822e1d3fface0d9e1095c5177e10141bd6bd6 upstream. This fixes a syntax error when setting up the user regulatory hint. This change yields the same exact binary object though so it ends up just being a syntax typo fix, fortunately. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f256dfffbf46..efd24a7aa8f0 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1714,7 +1714,7 @@ int regulatory_hint_user(const char *alpha2) request->wiphy_idx = WIPHY_IDX_STALE; request->alpha2[0] = alpha2[0]; request->alpha2[1] = alpha2[1]; - request->initiator = NL80211_REGDOM_SET_BY_USER, + request->initiator = NL80211_REGDOM_SET_BY_USER; queue_regulatory_request(request); From 0ea5505e18a1cb8eebf3384f825840897894ceda Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 3 Jan 2010 11:19:35 +0200 Subject: [PATCH 327/670] iwl: off by one bug commit 8a9ac160e844c7ce8074f6aa531feefb4acdee7c upstream. tid is used as an array offset. agg = &priv->stations[sta_id].tid[tid].agg; iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); It should be limitted to MAX_TID_COUNT - 1; struct iwl_tid_data tid[MAX_TID_COUNT]; regards, dan carpenter Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index f4e2e84e1296..99331edd9d75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2087,7 +2087,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, struct ieee80211_tx_info *info; struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->u.status); - int tid = MAX_TID_COUNT; + int tid = MAX_TID_COUNT - 1; int sta_id; int freed; u8 *qc = NULL; From 9b13cca3a8623088d95d9897d29370b4e0b9c213 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 7 Jan 2010 20:23:53 +0100 Subject: [PATCH 328/670] mac80211: add missing sanity checks for action frames commit d79074488083ec0d7ecd15352192dc1631f25643 upstream. Various missing sanity checks caused rejected action frames to be interpreted as channel switch announcements, which can cause a client mode interface to switch away from its operating channel, thereby losing connectivity. This patch ensures that only spectrum management action frames are processed by the CSA handling function and prevents rejected action frames from getting processed by the MLME code. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mlme.c | 4 +++- net/mac80211/rx.c | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f13d181c0644..6cae2954963d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1953,7 +1953,9 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); break; case IEEE80211_STYPE_ACTION: - /* XXX: differentiate, can only happen for CSA now! */ + if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) + break; + ieee80211_sta_process_chanswitch(sdata, &mgmt->u.action.u.chan_switch.sw_elem, ifmgd->associated); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 4e14754373a4..674d8c258266 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1808,6 +1808,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; default: + /* do not process rejected action frames */ + if (mgmt->u.action.category & 0x80) + return RX_DROP_MONITOR; + return RX_CONTINUE; } From b9945e752afed38518d7041ae00dea25f6272a34 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 Dec 2009 11:11:13 -0800 Subject: [PATCH 329/670] drm/i915: remove render reclock support commit cda9d05c499093c67b4a376a15009923acc2127a upstream. This code generally fails to adjust the render clock, and when it does, it conflicts with some other register settings and can cause problems. So remove this code altogether. I'm reworking it now to do the right thing, but the only bit it will share is the VBT check for whether reclocking is supported, so I'm leaving that bit. Reverts most of 652c393a3368af84359da37c45afc35a91144960 ("add dynamic clock frequency control"), though for many the regressions showed up in the later 181a5336d6cc836f05507410d66988c483ad0154 ("Fix render reclock availability detection"). Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 127 --------------------------- 1 file changed, 127 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 406b53271c69..121b92e0eec7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3737,125 +3737,6 @@ static void intel_gpu_idle_timer(unsigned long arg) queue_work(dev_priv->wq, &dev_priv->idle_work); } -void intel_increase_renderclock(struct drm_device *dev, bool schedule) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - if (IS_IGDNG(dev)) - return; - - if (!dev_priv->render_reclock_avail) { - DRM_DEBUG("not reclocking render clock\n"); - return; - } - - /* Restore render clock frequency to original value */ - if (IS_G4X(dev) || IS_I9XX(dev)) - pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock); - else if (IS_I85X(dev)) - pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock); - DRM_DEBUG("increasing render clock frequency\n"); - - /* Schedule downclock */ - if (schedule) - mod_timer(&dev_priv->idle_timer, jiffies + - msecs_to_jiffies(GPU_IDLE_TIMEOUT)); -} - -void intel_decrease_renderclock(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - if (IS_IGDNG(dev)) - return; - - if (!dev_priv->render_reclock_avail) { - DRM_DEBUG("not reclocking render clock\n"); - return; - } - - if (IS_G4X(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK; - gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I965G(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~I965_GC_RENDER_CLOCK_MASK; - gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I945G(dev) || IS_I945GM(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~I945_GC_RENDER_CLOCK_MASK; - gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I915G(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~I915_GC_RENDER_CLOCK_MASK; - gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I85X(dev)) { - u16 hpllcc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, HPLLCC, &hpllcc); - - /* Up to maximum... */ - hpllcc &= ~GC_CLOCK_CONTROL_MASK; - hpllcc |= GC_CLOCK_133_200; - - pci_write_config_word(dev->pdev, HPLLCC, hpllcc); - } - DRM_DEBUG("decreasing render clock frequency\n"); -} - -/* Note that no increase function is needed for this - increase_renderclock() - * will also rewrite these bits - */ -void intel_decrease_displayclock(struct drm_device *dev) -{ - if (IS_IGDNG(dev)) - return; - - if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) || - IS_I915GM(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~0xf0; - gcfgc |= 0x80; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } -} - #define CRTC_IDLE_TIMEOUT 1000 /* ms */ static void intel_crtc_idle_timer(unsigned long arg) @@ -3969,12 +3850,6 @@ static void intel_idle_update(struct work_struct *work) mutex_lock(&dev->struct_mutex); - /* GPU isn't processing, downclock it. */ - if (!dev_priv->busy) { - intel_decrease_renderclock(dev); - intel_decrease_displayclock(dev); - } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { /* Skip inactive CRTCs */ if (!crtc->fb) @@ -4009,7 +3884,6 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) return; dev_priv->busy = true; - intel_increase_renderclock(dev, true); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (!crtc->fb) @@ -4514,7 +4388,6 @@ void intel_modeset_cleanup(struct drm_device *dev) del_timer_sync(&intel_crtc->idle_timer); } - intel_increase_renderclock(dev, false); del_timer_sync(&dev_priv->idle_timer); mutex_unlock(&dev->struct_mutex); From 904e3733fd1c50e81f4726f56759343207874a95 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 18 Dec 2009 11:36:49 +0100 Subject: [PATCH 330/670] libertas: Remove carrier signaling from the scan code commit 659c8e5243caf14564155ad8421404f044dd8031 upstream. There is no reason to signal a carrier off when doing a 802.11 scan. Cc: Holger Schurig Signed-off-by: Samuel Ortiz Acked-by: Dan Williams Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/libertas/scan.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 6c95af3023cc..06d66a171396 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -399,11 +399,8 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan) chan_count = lbs_scan_create_channel_list(priv, chan_list); netif_stop_queue(priv->dev); - netif_carrier_off(priv->dev); - if (priv->mesh_dev) { + if (priv->mesh_dev) netif_stop_queue(priv->mesh_dev); - netif_carrier_off(priv->mesh_dev); - } /* Prepare to continue an interrupted scan */ lbs_deb_scan("chan_count %d, scan_channel %d\n", @@ -467,16 +464,13 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan) priv->scan_channel = 0; out: - if (priv->connect_status == LBS_CONNECTED) { - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - } - if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) { - netif_carrier_on(priv->mesh_dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->mesh_dev); - } + if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) + netif_wake_queue(priv->dev); + + if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) && + !priv->tx_pending_len) + netif_wake_queue(priv->mesh_dev); + kfree(chan_list); lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); From 71c77079a7b5c22e01eba239f93ce38bd6126725 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 8 Jan 2010 00:40:42 -0500 Subject: [PATCH 331/670] kernel/sysctl.c: fix stable merge error in NOMMU mmap_min_addr Stable commit 0399123f3dcce1a515d021107ec0fb4413ca3efa didn't match the original upstream commit. The CONFIG_MMU check was added much too early in the list disabling a lot of proc entries in the process. Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- kernel/sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index dd84be9ac6e4..b8bd058c5cd2 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1200,7 +1200,6 @@ static struct ctl_table vm_table[] = { .extra2 = (void *)&hugetlb_infinity, }, #endif -#ifdef CONFIG_MMU { .ctl_name = VM_LOWMEM_RESERVE_RATIO, .procname = "lowmem_reserve_ratio", @@ -1346,6 +1345,7 @@ static struct ctl_table vm_table[] = { .strategy = &sysctl_jiffies, }, #endif +#ifdef CONFIG_MMU { .ctl_name = CTL_UNNUMBERED, .procname = "mmap_min_addr", From d3b1e3bff1a2ed3a145634775588f1019bc76f5c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 14 Jan 2010 20:51:53 +0100 Subject: [PATCH 332/670] mac80211: fix skb buffering issue (and fixes to that) This is a backport of the mainline patches cf0277e714a0db302a8f80e1b85fd61c32cf00b3 045cfb71a3901005bf6dcedae98cecb3360a0bfc b49bb574e44226b332c28439999d196ddec2f643 Here is the description of the first of those patches (the other two just fixed bugs added by that patch): Since I removed the master netdev, we've been keeping internal queues only, and even before that we never told the networking stack above the virtual interfaces about congestion. This means that packets are queued in mac80211 and the upper layers never know, possibly leading to memory exhaustion and other problems. This patch makes all interfaces multiqueue and uses ndo_select_queue to put the packets into queues per AC. Additionally, when the driver stops a queue, we now stop all corresponding queues for the virtual interfaces as well. The injection case will use VO by default for non-data frames, and BE for data frames, but downgrade any data frames according to ACM. It needs to be fleshed out in the future to allow chosing the queue/AC in radiotap. Signed-off-by: Johannes Berg Cc: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/iface.c | 40 +++++++++++++++++++- net/mac80211/rx.c | 4 +- net/mac80211/tx.c | 5 ++- net/mac80211/util.c | 12 ++++++ net/mac80211/wme.c | 87 +++++++++++++++++++++++++++++++------------- net/mac80211/wme.h | 8 +++- 6 files changed, 125 insertions(+), 31 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b8295cbd7e8f..079c500a7de5 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -15,12 +15,14 @@ #include #include #include +#include #include "ieee80211_i.h" #include "sta_info.h" #include "debugfs_netdev.h" #include "mesh.h" #include "led.h" #include "driver-ops.h" +#include "wme.h" /** * DOC: Interface list locking @@ -642,6 +644,12 @@ static void ieee80211_teardown_sdata(struct net_device *dev) WARN_ON(flushed); } +static u16 ieee80211_netdev_select_queue(struct net_device *dev, + struct sk_buff *skb) +{ + return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); +} + static const struct net_device_ops ieee80211_dataif_ops = { .ndo_open = ieee80211_open, .ndo_stop = ieee80211_stop, @@ -650,8 +658,35 @@ static const struct net_device_ops ieee80211_dataif_ops = { .ndo_set_multicast_list = ieee80211_set_multicast_list, .ndo_change_mtu = ieee80211_change_mtu, .ndo_set_mac_address = eth_mac_addr, + .ndo_select_queue = ieee80211_netdev_select_queue, }; +static u16 ieee80211_monitor_select_queue(struct net_device *dev, + struct sk_buff *skb) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; + struct ieee80211_hdr *hdr; + struct ieee80211_radiotap_header *rtap = (void *)skb->data; + + if (local->hw.queues < 4) + return 0; + + if (skb->len < 4 || + skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */) + return 0; /* doesn't matter, frame will be dropped */ + + hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); + + if (!ieee80211_is_data(hdr->frame_control)) { + skb->priority = 7; + return ieee802_1d_to_ac[skb->priority]; + } + + skb->priority = 0; + return ieee80211_downgrade_queue(local, skb); +} + static const struct net_device_ops ieee80211_monitorif_ops = { .ndo_open = ieee80211_open, .ndo_stop = ieee80211_stop, @@ -660,6 +695,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = { .ndo_set_multicast_list = ieee80211_set_multicast_list, .ndo_change_mtu = ieee80211_change_mtu, .ndo_set_mac_address = eth_mac_addr, + .ndo_select_queue = ieee80211_monitor_select_queue, }; static void ieee80211_if_setup(struct net_device *dev) @@ -768,8 +804,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, ASSERT_RTNL(); - ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, - name, ieee80211_if_setup); + ndev = alloc_netdev_mq(sizeof(*sdata) + local->hw.vif_data_size, + name, ieee80211_if_setup, local->hw.queues); if (!ndev) return -ENOMEM; dev_net_set(ndev, wiphy_net(local->hw.wiphy)); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 674d8c258266..16c6cdc6e8af 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1548,7 +1548,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) memset(info, 0, sizeof(*info)); info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; info->control.vif = &rx->sdata->vif; - ieee80211_select_queue(local, fwd_skb); + skb_set_queue_mapping(skb, + ieee80211_select_queue(rx->sdata, fwd_skb)); + ieee80211_set_qos_hdr(local, skb); if (is_multicast_ether_addr(fwd_hdr->addr1)) IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, fwded_mcast); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d39819745abf..441f68e3f379 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1482,7 +1482,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, return; } - ieee80211_select_queue(local, skb); + ieee80211_set_qos_hdr(local, skb); ieee80211_tx(sdata, skb, false); dev_put(sdata->dev); } @@ -2226,6 +2226,9 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, if (!encrypt) info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + /* send all internal mgmt frames on VO */ + skb_set_queue_mapping(skb, 0); + /* * The other path calling ieee80211_xmit is from the tasklet, * and while we can handle concurrent transmissions locking diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 51e0bd278e66..553cffe9ab37 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -269,6 +269,7 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason) { struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; if (WARN_ON(queue >= hw->queues)) return; @@ -281,6 +282,11 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, if (!skb_queue_empty(&local->pending[queue])) tasklet_schedule(&local->tx_pending_tasklet); + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) + netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); + rcu_read_unlock(); } void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, @@ -305,11 +311,17 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason) { struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; if (WARN_ON(queue >= hw->queues)) return; __set_bit(reason, &local->queue_stop_reasons[queue]); + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) + netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue)); + rcu_read_unlock(); } void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index b19b7696f3a2..6d32ebf1ea37 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -44,22 +44,62 @@ static int wme_downgrade_ac(struct sk_buff *skb) } -/* Indicate which queue to use. */ -static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) +/* Indicate which queue to use. */ +u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_local *local = sdata->local; + struct sta_info *sta = NULL; + u32 sta_flags = 0; + const u8 *ra = NULL; + bool qos = false; - if (!ieee80211_is_data(hdr->frame_control)) { - /* management frames go on AC_VO queue, but are sent - * without QoS control fields */ - return 0; + if (local->hw.queues < 4 || skb->len < 6) { + skb->priority = 0; /* required for correct WPA/11i MIC */ + return min_t(u16, local->hw.queues - 1, + ieee802_1d_to_ac[skb->priority]); } - if (0 /* injected */) { - /* use AC from radiotap */ + rcu_read_lock(); + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_AP: + ra = skb->data; + break; + case NL80211_IFTYPE_WDS: + ra = sdata->u.wds.remote_addr; + break; +#ifdef CONFIG_MAC80211_MESH + case NL80211_IFTYPE_MESH_POINT: + /* + * XXX: This is clearly broken ... but already was before, + * because ieee80211_fill_mesh_addresses() would clear A1 + * except for multicast addresses. + */ + break; +#endif + case NL80211_IFTYPE_STATION: + ra = sdata->u.mgd.bssid; + break; + case NL80211_IFTYPE_ADHOC: + ra = skb->data; + break; + default: + break; } - if (!ieee80211_is_data_qos(hdr->frame_control)) { + if (!sta && ra && !is_multicast_ether_addr(ra)) { + sta = sta_info_get(local, ra); + if (sta) + sta_flags = get_sta_flags(sta); + } + + if (sta_flags & WLAN_STA_WME) + qos = true; + + rcu_read_unlock(); + + if (!qos) { skb->priority = 0; /* required for correct WPA/11i MIC */ return ieee802_1d_to_ac[skb->priority]; } @@ -68,6 +108,12 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) * data frame has */ skb->priority = cfg80211_classify8021d(skb); + return ieee80211_downgrade_queue(local, skb); +} + +u16 ieee80211_downgrade_queue(struct ieee80211_local *local, + struct sk_buff *skb) +{ /* in case we are a client verify acm is not set for this ac */ while (unlikely(local->wmm_acm & BIT(skb->priority))) { if (wme_downgrade_ac(skb)) { @@ -85,24 +131,17 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) return ieee802_1d_to_ac[skb->priority]; } -void ieee80211_select_queue(struct ieee80211_local *local, struct sk_buff *skb) +void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 queue; - u8 tid; + struct ieee80211_hdr *hdr = (void *)skb->data; - queue = classify80211(local, skb); - if (unlikely(queue >= local->hw.queues)) - queue = local->hw.queues - 1; - - /* - * Now we know the 1d priority, fill in the QoS header if - * there is one (and we haven't done this before). - */ + /* Fill in the QoS header if there is one. */ if (ieee80211_is_data_qos(hdr->frame_control)) { u8 *p = ieee80211_get_qos_ctl(hdr); - u8 ack_policy = 0; + u8 ack_policy = 0, tid; + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; + if (unlikely(local->wifi_wme_noack_test)) ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK << QOS_CONTROL_ACK_POLICY_SHIFT; @@ -110,6 +149,4 @@ void ieee80211_select_queue(struct ieee80211_local *local, struct sk_buff *skb) *p++ = ack_policy | tid; *p = 0; } - - skb_set_queue_mapping(skb, queue); } diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index d4fd87ca5118..6053b1c9feee 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h @@ -20,7 +20,11 @@ extern const int ieee802_1d_to_ac[8]; -void ieee80211_select_queue(struct ieee80211_local *local, - struct sk_buff *skb); +u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb); +void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb); +u16 ieee80211_downgrade_queue(struct ieee80211_local *local, + struct sk_buff *skb); + #endif /* _WME_H */ From dffaea5bd7145629d54ba57a49366bbd8157ddef Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 19 Dec 2009 15:59:45 +0000 Subject: [PATCH 333/670] fix braindamage in audit_tree.c untag_chunk() commit 6f5d51148921c242680a7a1d9913384a30ab3cbe upstream. ... aka "Al had badly fscked up when writing that thing and nobody noticed until Eric had fixed leaks that used to mask the breakage". The function essentially creates a copy of old array sans one element and replaces the references to elements of original (they are on cyclic lists) with those to corresponding elements of new one. After that the old one is fair game for freeing. First of all, there's a dumb braino: when we get to list_replace_init we use indices for wrong arrays - position in new one with the old array and vice versa. Another bug is more subtle - termination condition is wrong if the element to be excluded happens to be the last one. We shouldn't go until we fill the new array, we should go until we'd finished the old one. Otherwise the element we are trying to kill will remain on the cyclic lists... That crap used to be masked by several leaks, so it was not quite trivial to hit. Eric had fixed some of those leaks a while ago and the shit had hit the fan... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/audit_tree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 2451dc6f3282..b36aa9651ba2 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -277,7 +277,7 @@ static void untag_chunk(struct node *p) owner->root = NULL; } - for (i = j = 0; i < size; i++, j++) { + for (i = j = 0; j <= size; i++, j++) { struct audit_tree *s; if (&chunk->owners[j] == p) { list_del_init(&p->list); @@ -290,7 +290,7 @@ static void untag_chunk(struct node *p) if (!s) /* result of earlier fallback */ continue; get_tree(s); - list_replace_init(&chunk->owners[i].list, &new->owners[j].list); + list_replace_init(&chunk->owners[j].list, &new->owners[i].list); } list_replace_rcu(&chunk->hash, &new->hash); From 9ef9a7c717299c9c57cba7a246462bf1c342118a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 19 Dec 2009 16:03:30 +0000 Subject: [PATCH 334/670] fix more leaks in audit_tree.c tag_chunk() commit b4c30aad39805902cf5b855aa8a8b22d728ad057 upstream. Several leaks in audit_tree didn't get caught by commit 318b6d3d7ddbcad3d6867e630711b8a705d873d7, including the leak on normal exit in case of multiple rules refering to the same chunk. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- kernel/audit_tree.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index b36aa9651ba2..4b05bd9479db 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -373,15 +373,17 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) for (n = 0; n < old->count; n++) { if (old->owners[n].owner == tree) { spin_unlock(&hash_lock); - put_inotify_watch(watch); + put_inotify_watch(&old->watch); return 0; } } spin_unlock(&hash_lock); chunk = alloc_chunk(old->count + 1); - if (!chunk) + if (!chunk) { + put_inotify_watch(&old->watch); return -ENOMEM; + } mutex_lock(&inode->inotify_mutex); if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) { @@ -425,7 +427,8 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&hash_lock); inotify_evict_watch(&old->watch); mutex_unlock(&inode->inotify_mutex); - put_inotify_watch(&old->watch); + put_inotify_watch(&old->watch); /* pair to inotify_find_watch */ + put_inotify_watch(&old->watch); /* and kill it */ return 0; } From 54f1b39ce06aaf023db558ce4cc73f1d550d0d53 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 15 Dec 2009 16:28:32 -0600 Subject: [PATCH 335/670] module: handle ppc64 relocating kcrctabs when CONFIG_RELOCATABLE=y commit d4703aefdbc8f9f347f6dcefcddd791294314eb7 upstream. powerpc applies relocations to the kcrctab. They're absolute symbols, but it's not completely unreasonable: other archs may too, but the relocation is often 0. http://lists.ozlabs.org/pipermail/linuxppc-dev/2009-November/077972.html Inspired-by: Neil Horman Signed-off-by: Rusty Russell Tested-by: Neil Horman Acked-by: Paul Mackerras Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/module.h | 5 +++++ arch/powerpc/kernel/vmlinux.lds.S | 3 +++ kernel/module.c | 28 +++++++++++++++++++++------- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index 08454880a2c0..0192a4ee2bc2 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h @@ -87,5 +87,10 @@ struct exception_table_entry; void sort_ex_table(struct exception_table_entry *start, struct exception_table_entry *finish); +#ifdef CONFIG_MODVERSIONS +#define ARCH_RELOCATES_KCRCTAB + +extern const unsigned long reloc_start[]; +#endif #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MODULE_H */ diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 27735a7ac12b..dcd01c82e701 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -38,6 +38,9 @@ jiffies = jiffies_64 + 4; #endif SECTIONS { + . = 0; + reloc_start = .; + . = KERNELBASE; /* diff --git a/kernel/module.c b/kernel/module.c index 37caef0197ef..dfa33e8ee2a9 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1030,11 +1030,23 @@ static int try_to_force_load(struct module *mod, const char *reason) } #ifdef CONFIG_MODVERSIONS +/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */ +static unsigned long maybe_relocated(unsigned long crc, + const struct module *crc_owner) +{ +#ifdef ARCH_RELOCATES_KCRCTAB + if (crc_owner == NULL) + return crc - (unsigned long)reloc_start; +#endif + return crc; +} + static int check_version(Elf_Shdr *sechdrs, unsigned int versindex, const char *symname, struct module *mod, - const unsigned long *crc) + const unsigned long *crc, + const struct module *crc_owner) { unsigned int i, num_versions; struct modversion_info *versions; @@ -1055,10 +1067,10 @@ static int check_version(Elf_Shdr *sechdrs, if (strcmp(versions[i].name, symname) != 0) continue; - if (versions[i].crc == *crc) + if (versions[i].crc == maybe_relocated(*crc, crc_owner)) return 1; DEBUGP("Found checksum %lX vs module %lX\n", - *crc, versions[i].crc); + maybe_relocated(*crc, crc_owner), versions[i].crc); goto bad_version; } @@ -1081,7 +1093,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL, &crc, true, false)) BUG(); - return check_version(sechdrs, versindex, "module_layout", mod, crc); + return check_version(sechdrs, versindex, "module_layout", mod, crc, + NULL); } /* First part is kernel version, which we ignore if module has crcs. */ @@ -1099,7 +1112,8 @@ static inline int check_version(Elf_Shdr *sechdrs, unsigned int versindex, const char *symname, struct module *mod, - const unsigned long *crc) + const unsigned long *crc, + const struct module *crc_owner) { return 1; } @@ -1134,8 +1148,8 @@ static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, /* use_module can fail due to OOM, or module initialization or unloading */ if (sym) { - if (!check_version(sechdrs, versindex, name, mod, crc) || - !use_module(mod, owner)) + if (!check_version(sechdrs, versindex, name, mod, crc, owner) + || !use_module(mod, owner)) sym = NULL; } return sym; From 5deb72edb39542650c73e3fa7bf4a4a3ef14cc63 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 13 Jan 2010 17:27:37 -0800 Subject: [PATCH 336/670] ipv6: skb_dst() can be NULL in ipv6_hop_jumbo(). commit 2570a4f5428bcdb1077622342181755741e7fa60 upstream. This fixes CERT-FI FICORA #341748 Discovered by Olli Jarva and Tuomo Untinen from the CROSS project at Codenomicon Ltd. Just like in CVE-2007-4567, we can't rely upon skb_dst() being non-NULL at this point. We fixed that in commit e76b2b2567b83448c2ee85a896433b96150c92e6 ("[IPV6]: Do no rely on skb->dst before it is assigned.") However commit 483a47d2fe794328d29950fe00ce26dd405d9437 ("ipv6: added net argument to IP6_INC_STATS_BH") put a new version of the same bug into this function. Complicating analysis further, this bug can only trigger when network namespaces are enabled in the build. When namespaces are turned off, the dev_net() does not evaluate it's argument, so the dereference would not occur. So, for a long time, namespaces couldn't be turned on unless SYSFS was disabled. Therefore, this code has largely been disabled except by people turning it on explicitly for namespace development. With help from Eugene Teo Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/exthdrs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index df159fffe4bc..4bac362b1335 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -559,6 +559,11 @@ static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : __in6_dev_get(skb->dev); } +static inline struct net *ipv6_skb_net(struct sk_buff *skb) +{ + return skb_dst(skb) ? dev_net(skb_dst(skb)->dev) : dev_net(skb->dev); +} + /* Router Alert as of RFC 2711 */ static int ipv6_hop_ra(struct sk_buff *skb, int optoff) @@ -580,8 +585,8 @@ static int ipv6_hop_ra(struct sk_buff *skb, int optoff) static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) { const unsigned char *nh = skb_network_header(skb); + struct net *net = ipv6_skb_net(skb); u32 pkt_len; - struct net *net = dev_net(skb_dst(skb)->dev); if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", From 5877960869333e42ebeb733e8d9d5630ff96d350 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 2 Dec 2009 11:00:05 +0000 Subject: [PATCH 337/670] agp/intel-agp: Clear entire GTT on startup commit fc61901373987ad61851ed001fe971f3ee8d96a3 upstream. Some BIOSes fail to initialise the GTT, which will cause DMA faults when the IOMMU is enabled. We need to clear the whole thing to point at the scratch page, not just the part that Linux is going to use. Signed-off-by: David Woodhouse [anholt: Note that this may also help with stability in the presence of driver bugs, by not drawing to memory we don't own] Signed-off-by: Eric Anholt Cc: Zhenyu Wang Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/intel-agp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 3cb56a049e24..4dcfef05045a 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -178,6 +178,7 @@ static struct _intel_private { * popup and for the GTT. */ int gtt_entries; /* i830+ */ + int gtt_total_size; union { void __iomem *i9xx_flush_page; void *i8xx_flush_page; @@ -1153,7 +1154,7 @@ static int intel_i915_configure(void) readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ if (agp_bridge->driver->needs_scratch_page) { - for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) { + for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) { writel(agp_bridge->scratch_page, intel_private.gtt+i); } readl(intel_private.gtt+i-1); /* PCI Posting. */ @@ -1308,6 +1309,8 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) if (!intel_private.gtt) return -ENOMEM; + intel_private.gtt_total_size = gtt_map_size / 4; + temp &= 0xfff80000; intel_private.registers = ioremap(temp, 128 * 4096); @@ -1395,6 +1398,8 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) if (!intel_private.gtt) return -ENOMEM; + intel_private.gtt_total_size = gtt_size / 4; + intel_private.registers = ioremap(temp, 128 * 4096); if (!intel_private.registers) { iounmap(intel_private.gtt); From 3df76730b1e135164451de3192fcf5e1166eb944 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 18 Jan 2010 10:23:35 -0800 Subject: [PATCH 338/670] Linux 2.6.32.4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 482dcddf7e5b..6d13598f153f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = .3 +EXTRAVERSION = .4 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* From cec3ad600c2395d2d018332dadea9b2fe33e6169 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 15 Jan 2010 12:12:24 -0500 Subject: [PATCH 339/670] inotify: do not reuse watch descriptors commit 9e572cc9877ee6c43af60778f6b8d5ba0692d935 upstream. Since commit 7e790dd5fc937bc8d2400c30a05e32a9e9eef276 ("inotify: fix error paths in inotify_update_watch") inotify changed the manor in which it gave watch descriptors back to userspace. Previous to this commit inotify acted like the following: inotify_add_watch(X, Y, Z) = 1 inotify_rm_watch(X, 1); inotify_add_watch(X, Y, Z) = 2 but after this patch inotify would return watch descriptors like so: inotify_add_watch(X, Y, Z) = 1 inotify_rm_watch(X, 1); inotify_add_watch(X, Y, Z) = 1 which I saw as equivalent to opening an fd where open(file) = 1; close(1); open(file) = 1; seemed perfectly reasonable. The issue is that quite a bit of userspace apparently relies on the behavior in which watch descriptors will not be quickly reused. KDE relies on it, I know some selinux packages rely on it, and I have heard complaints from other random sources such as debian bug 558981. Although the man page implies what we do is ok, we broke userspace so this patch almost reverts us to the old behavior. It is still slightly racey and I have patches that would fix that, but they are rather large and this will fix it for all real world cases. The race is as follows: - task1 creates a watch and blocks in idr_new_watch() before it updates the hint. - task2 creates a watch and updates the hint. - task1 updates the hint with it's older wd - task removes the watch created by task2 - task adds a new watch and will reuse the wd originally given to task2 it requires moving some locking around the hint (last_wd) but this should solve it for the real world and be -stable safe. As a side effect this patch papers over a bug in the lib/idr code which is causing a large number WARN's to pop on people's system and many reports in kerneloops.org. I'm working on the root cause of that idr bug seperately but this should make inotify immune to that issue. Signed-off-by: Eric Paris Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/notify/inotify/inotify_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index dcd2040d330c..ca44337b06ce 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -558,7 +558,7 @@ static int inotify_new_watch(struct fsnotify_group *group, spin_lock(&group->inotify_data.idr_lock); ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry, - group->inotify_data.last_wd, + group->inotify_data.last_wd+1, &tmp_ientry->wd); spin_unlock(&group->inotify_data.idr_lock); if (ret) { @@ -638,7 +638,7 @@ static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsign spin_lock_init(&group->inotify_data.idr_lock); idr_init(&group->inotify_data.idr); - group->inotify_data.last_wd = 1; + group->inotify_data.last_wd = 0; group->inotify_data.user = user; group->inotify_data.fa = NULL; From 800c02837ef72e60fd0d61ed3c791263d9d0dc36 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 15 Jan 2010 12:12:25 -0500 Subject: [PATCH 340/670] inotify: only warn once for inotify problems commit 976ae32be45a736acd49215a7e4771ff91f161c3 upstream. inotify will WARN() if it finds that the idr and the fsnotify internals somehow got out of sync. It was only supposed to do this once but due to this stupid bug it would warn every single time a problem was detected. Signed-off-by: Eric Paris Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/notify/inotify/inotify_fsnotify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index c9ee67b442e1..1afb0a10229f 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -121,7 +121,7 @@ static int idr_callback(int id, void *p, void *data) if (warned) return 0; - warned = false; + warned = true; entry = p; ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry); From 70f800ff2289dce1ecb0f941dc2f08e706d9d1ad Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 15 Jan 2010 17:01:40 -0800 Subject: [PATCH 341/670] revert "drivers/video/s3c-fb.c: fix clock setting for Samsung SoC Framebuffer" commit eb29a5cc0b601c458bae9df2f6c3696d75c2d383 upstream. Fix divide by zero and broken output. Commit 600ce1a0fa ("fix clock setting for Samsung SoC Framebuffer") introduced a mandatory refresh parameter to the platform data for the S3C framebuffer but did not introduce any validation code, causing existing platforms (none of which have refresh set) to divide by zero whenever the framebuffer is configured, generating warnings and unusable output. Ben Dooks noted several problems with the patch: - The platform data supplies the pixclk directly and should already have taken care of the refresh rate. - The addition of a window ID parameter doesn't help since only the root framebuffer can control the pixclk. - pixclk is specified in picoseconds (rather than Hz) as the patch assumed. and suggests reverting the commit so do that. Without fixing this no mainline user of the driver will produce output. [akpm@linux-foundation.org: don't revert the correct bit] Signed-off-by: Mark Brown Cc: InKi Dae Cc: Kyungmin Park Cc: Krzysztof Helt Cc: Marek Szyprowski Cc: Ben Dooks Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/s3c-fb.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index adf9632c6b1f..53cb722c45a0 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -211,21 +211,23 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, /** * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. - * @id: window id. * @sfb: The hardware state. * @pixclock: The pixel clock wanted, in picoseconds. * * Given the specified pixel clock, work out the necessary divider to get * close to the output frequency. */ -static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) +static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) { - struct s3c_fb_pd_win *win = sfb->pdata->win[id]; unsigned long clk = clk_get_rate(sfb->bus_clk); + unsigned long long tmp; unsigned int result; - pixclk *= win->win_mode.refresh; - result = clk / pixclk; + tmp = (unsigned long long)clk; + tmp *= pixclk; + + do_div(tmp, 1000000000UL); + result = (unsigned int)tmp / 1000; dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", pixclk, clk, result, clk / result); @@ -301,7 +303,7 @@ static int s3c_fb_set_par(struct fb_info *info) /* use window 0 as the basis for the lcd output timings */ if (win_no == 0) { - clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); + clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); data = sfb->pdata->vidcon0; data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); From 4334ab76da3dc18a531948882ff6247764d96ea8 Mon Sep 17 00:00:00 2001 From: Daisuke Nishimura Date: Fri, 15 Jan 2010 17:01:30 -0800 Subject: [PATCH 342/670] memcg: ensure list is empty at rmdir commit fce66477578d081f19aef5ea218664ff7758c33a upstream. Current mem_cgroup_force_empty() only ensures mem->res.usage == 0 on success. But this doesn't guarantee memcg's LRU is really empty, because there are some cases in which !PageCgrupUsed pages exist on memcg's LRU. For example: - Pages can be uncharged by its owner process while they are on LRU. - race between mem_cgroup_add_lru_list() and __mem_cgroup_uncharge_common(). So there can be a case in which the usage is zero but some of the LRUs are not empty. OTOH, mem_cgroup_del_lru_list(), which can be called asynchronously with rmdir, accesses the mem_cgroup, so this access can cause a problem if it races with rmdir because the mem_cgroup might have been freed by rmdir. Actually, I saw a bug which seems to be caused by this race. [1530745.949906] BUG: unable to handle kernel NULL pointer dereference at 0000000000000230 [1530745.950651] IP: [] mem_cgroup_del_lru_list+0x30/0x80 [1530745.950651] PGD 3863de067 PUD 3862c7067 PMD 0 [1530745.950651] Oops: 0002 [#1] SMP [1530745.950651] last sysfs file: /sys/devices/system/cpu/cpu7/cache/index1/shared_cpu_map [1530745.950651] CPU 3 [1530745.950651] Modules linked in: configs ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp nfsd nfs_acl auth_rpcgss exportfs autofs4 hidp rfcomm l2cap crc16 bluetooth lockd sunrpc ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp bnx2i cnic uio ipv6 cxgb3i cxgb3 mdio libiscsi_tcp libiscsi scsi_transport_iscsi dm_mirror dm_multipath scsi_dh video output sbs sbshc battery ac lp kvm_intel kvm sg ide_cd_mod cdrom serio_raw tpm_tis tpm tpm_bios acpi_memhotplug button parport_pc parport rtc_cmos rtc_core rtc_lib e1000 i2c_i801 i2c_core pcspkr dm_region_hash dm_log dm_mod ata_piix libata shpchp megaraid_mbox sd_mod scsi_mod megaraid_mm ext3 jbd uhci_hcd ohci_hcd ehci_hcd [last unloaded: freq_table] [1530745.950651] Pid: 19653, comm: shmem_test_02 Tainted: G M 2.6.32-mm1-00701-g2b04386 #3 Express5800/140Rd-4 [N8100-1065] [1530745.950651] RIP: 0010:[] [] mem_cgroup_del_lru_list+0x30/0x80 [1530745.950651] RSP: 0018:ffff8803863ddcb8 EFLAGS: 00010002 [1530745.950651] RAX: 00000000000001e0 RBX: ffff8803abc02238 RCX: 00000000000001e0 [1530745.950651] RDX: 0000000000000000 RSI: ffff88038611a000 RDI: ffff8803abc02238 [1530745.950651] RBP: ffff8803863ddcc8 R08: 0000000000000002 R09: ffff8803a04c8643 [1530745.950651] R10: 0000000000000000 R11: ffffffff810c7333 R12: 0000000000000000 [1530745.950651] R13: ffff880000017f00 R14: 0000000000000092 R15: ffff8800179d0310 [1530745.950651] FS: 0000000000000000(0000) GS:ffff880017800000(0000) knlGS:0000000000000000 [1530745.950651] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [1530745.950651] CR2: 0000000000000230 CR3: 0000000379d87000 CR4: 00000000000006e0 [1530745.950651] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [1530745.950651] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [1530745.950651] Process shmem_test_02 (pid: 19653, threadinfo ffff8803863dc000, task ffff88038612a8a0) [1530745.950651] Stack: [1530745.950651] ffffea00040c2fe8 0000000000000000 ffff8803863ddd98 ffffffff810c739a [1530745.950651] <0> 00000000863ddd18 000000000000000c 0000000000000000 0000000000000000 [1530745.950651] <0> 0000000000000002 0000000000000000 ffff8803863ddd68 0000000000000046 [1530745.950651] Call Trace: [1530745.950651] [] release_pages+0x142/0x1e7 [1530745.950651] [] ? pagevec_move_tail+0x6e/0x112 [1530745.950651] [] pagevec_move_tail+0xfd/0x112 [1530745.950651] [] lru_add_drain+0x76/0x94 [1530745.950651] [] exit_mmap+0x6e/0x145 [1530745.950651] [] mmput+0x5e/0xcf [1530745.950651] [] exit_mm+0x11c/0x129 [1530745.950651] [] ? audit_free+0x196/0x1c9 [1530745.950651] [] do_exit+0x1f5/0x6b7 [1530745.950651] [] ? up_read+0x2b/0x2f [1530745.950651] [] ? lockdep_sys_exit_thunk+0x35/0x67 [1530745.950651] [] do_group_exit+0x83/0xb0 [1530745.950651] [] sys_exit_group+0x17/0x1b [1530745.950651] [] system_call_fastpath+0x16/0x1b [1530745.950651] Code: 54 53 0f 1f 44 00 00 83 3d cc 29 7c 00 00 41 89 f4 75 63 eb 4e 48 83 7b 08 00 75 04 0f 0b eb fe 48 89 df e8 18 f3 ff ff 44 89 e2 <48> ff 4c d0 50 48 8b 05 2b 2d 7c 00 48 39 43 08 74 39 48 8b 4b [1530745.950651] RIP [] mem_cgroup_del_lru_list+0x30/0x80 [1530745.950651] RSP [1530745.950651] CR2: 0000000000000230 [1530745.950651] ---[ end trace c3419c1bb8acc34f ]--- [1530745.950651] Fixing recursive fault but reboot is needed! The problem here is pages on LRU may contain pointer to stale memcg. To make res->usage to be 0, all pages on memcg must be uncharged or moved to another(parent) memcg. Moved page_cgroup have already removed from original LRU, but uncharged page_cgroup contains pointer to memcg withou PCG_USED bit. (This asynchronous LRU work is for improving performance.) If PCG_USED bit is not set, page_cgroup will never be added to memcg's LRU. So, about pages not on LRU, they never access stale pointer. Then, what we have to take care of is page_cgroup _on_ LRU list. This patch fixes this problem by making mem_cgroup_force_empty() visit all LRUs before exiting its loop and guarantee there are no pages on its LRU. Signed-off-by: Daisuke Nishimura Acked-by: KAMEZAWA Hiroyuki Cc: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memcontrol.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 5dc10374d769..66035bf92612 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2381,7 +2381,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *mem, bool free_all) if (free_all) goto try_to_free; move_account: - while (mem->res.usage > 0) { + do { ret = -EBUSY; if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children)) goto out; @@ -2408,8 +2408,8 @@ static int mem_cgroup_force_empty(struct mem_cgroup *mem, bool free_all) if (ret == -ENOMEM) goto try_to_free; cond_resched(); - } - ret = 0; + /* "ret" should also be checked to ensure all lists are empty. */ + } while (mem->res.usage > 0 || ret); out: css_put(&mem->css); return ret; @@ -2442,10 +2442,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *mem, bool free_all) } lru_add_drain(); /* try move_account...there may be some *locked* pages. */ - if (mem->res.usage) - goto move_account; - ret = 0; - goto out; + goto move_account; } int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event) From 8a9c3f5c34a93fd4635aa739810280c4752eaa6e Mon Sep 17 00:00:00 2001 From: Zou Nan hai Date: Fri, 15 Jan 2010 10:29:06 +0800 Subject: [PATCH 343/670] drm/i915: remove loop in Ironlake interrupt handler commit c7c85101afd0cb8ce497456d12ee1cad4aad152f upstream. On Ironlake, there is an interrupt master control bit. With the bit disabled before clearing IIR, we do not need to handle extra interrupt in a loop. This patch removes the loop in Ironlake interrupt handler. It fixed irq lost issue on some Ironlake platforms. Signed-off-by: Zou Nan hai Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_irq.c | 45 ++++++++++++++------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index aa7fd82aa6eb..7d1357e54eef 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -255,7 +255,6 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = IRQ_NONE; u32 de_iir, gt_iir, de_ier; - u32 new_de_iir, new_gt_iir; struct drm_i915_master_private *master_priv; /* disable master interrupt before clearing iir */ @@ -266,35 +265,29 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) de_iir = I915_READ(DEIIR); gt_iir = I915_READ(GTIIR); - for (;;) { - if (de_iir == 0 && gt_iir == 0) - break; + if (de_iir == 0 && gt_iir == 0) + goto done; - ret = IRQ_HANDLED; + ret = IRQ_HANDLED; - I915_WRITE(DEIIR, de_iir); - new_de_iir = I915_READ(DEIIR); - I915_WRITE(GTIIR, gt_iir); - new_gt_iir = I915_READ(GTIIR); - - if (dev->primary->master) { - master_priv = dev->primary->master->driver_priv; - if (master_priv->sarea_priv) - master_priv->sarea_priv->last_dispatch = - READ_BREADCRUMB(dev_priv); - } - - if (gt_iir & GT_USER_INTERRUPT) { - u32 seqno = i915_get_gem_seqno(dev); - dev_priv->mm.irq_gem_seqno = seqno; - trace_i915_gem_request_complete(dev, seqno); - DRM_WAKEUP(&dev_priv->irq_queue); - } - - de_iir = new_de_iir; - gt_iir = new_gt_iir; + if (dev->primary->master) { + master_priv = dev->primary->master->driver_priv; + if (master_priv->sarea_priv) + master_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); } + if (gt_iir & GT_USER_INTERRUPT) { + u32 seqno = i915_get_gem_seqno(dev); + dev_priv->mm.irq_gem_seqno = seqno; + trace_i915_gem_request_complete(dev, seqno); + DRM_WAKEUP(&dev_priv->irq_queue); + } + + I915_WRITE(GTIIR, gt_iir); + I915_WRITE(DEIIR, de_iir); + +done: I915_WRITE(DEIER, de_ier); (void)I915_READ(DEIER); From 1bd24fdff4b0bd7f0a50f330165a82be690a919c Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Fri, 15 Jan 2010 01:55:07 -0500 Subject: [PATCH 344/670] block: Fix incorrect reporting of partition alignment commit 81744ee44ab2845c16ffd7d6f762f7b4a49a4750 upstream queue_sector_alignment_offset returned the wrong value which caused partitions to report an incorrect alignment_offset. Since offset calculation is needed several places it has been split into a separate helper function. Signed-off-by: Martin K. Petersen Tested-by: Mike Snitzer Cc: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- include/linux/blkdev.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 221cecd86bd3..adf99c617cd3 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1114,11 +1114,18 @@ static inline int queue_alignment_offset(struct request_queue *q) return q->limits.alignment_offset; } +static inline int queue_limit_alignment_offset(struct queue_limits *lim, sector_t offset) +{ + unsigned int granularity = max(lim->physical_block_size, lim->io_min); + + offset &= granularity - 1; + return (granularity + lim->alignment_offset - offset) & (granularity - 1); +} + static inline int queue_sector_alignment_offset(struct request_queue *q, sector_t sector) { - return ((sector << 9) - q->limits.alignment_offset) - & (q->limits.io_min - 1); + return queue_limit_alignment_offset(&q->limits, sector << 9); } static inline int bdev_alignment_offset(struct block_device *bdev) From 8410b13cced2fa9aee301d4722a5ce751fcc253a Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 14 Dec 2009 17:56:34 +0900 Subject: [PATCH 345/670] x86, mce: Thermal monitoring depends on APIC being enabled commit 485a2e1973fd9f98c2c6776e66ac4721882b69e0 upstream. Add check if APIC is not disabled since thermal monitoring depends on it. As only apic gets disabled we should not try to install "thermal monitor" vector, print out that thermal monitoring is enabled and etc... Note that "Intel Correct Machine Check Interrupts" already has such a check. Also I decided to not add cpu_has_apic check into mcheck_intel_therm_init since even if it'll call apic_read on disabled apic -- it's safe here and allow us to save a few code bytes. Reported-by: Thomas Gleixner Signed-off-by: Cyrill Gorcunov Signed-off-by: Hidetoshi Seto LKML-Reference: <4B25FDC2.3020401@jp.fujitsu.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/mcheck/therm_throt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 4fef985fc221..687638e655d3 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -274,8 +274,9 @@ void intel_init_thermal(struct cpuinfo_x86 *c) int tm2 = 0; u32 l, h; - /* Thermal monitoring depends on ACPI and clock modulation*/ - if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC)) + /* Thermal monitoring depends on APIC, ACPI and clock modulation */ + if (!cpu_has_apic || !cpu_has(c, X86_FEATURE_ACPI) || + !cpu_has(c, X86_FEATURE_ACC)) return; /* From d4c893f20758ff549e4aaa4a02a79e563deaebb9 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Tue, 5 Jan 2010 16:32:43 +0900 Subject: [PATCH 346/670] futexes: Remove rw parameter from get_futex_key() commit 7485d0d3758e8e6491a5c9468114e74dc050785d upstream. Currently, futexes have two problem: A) The current futex code doesn't handle private file mappings properly. get_futex_key() uses PageAnon() to distinguish file and anon, which can cause the following bad scenario: 1) thread-A call futex(private-mapping, FUTEX_WAIT), it sleeps on file mapping object. 2) thread-B writes a variable and it makes it cow. 3) thread-B calls futex(private-mapping, FUTEX_WAKE), it wakes up blocked thread on the anonymous page. (but it's nothing) B) Current futex code doesn't handle zero page properly. Read mode get_user_pages() can return zero page, but current futex code doesn't handle it at all. Then, zero page makes infinite loop internally. The solution is to use write mode get_user_page() always for page lookup. It prevents the lookup of both file page of private mappings and zero page. Performance concerns: Probaly very little, because glibc always initialize variables for futex before to call futex(). It means glibc users never see the overhead of this patch. Compatibility concerns: This patch has few compatibility issues. After this patch, FUTEX_WAIT require writable access to futex variables (read-only mappings makes EFAULT). But practically it's not a problem, glibc always initalizes variables for futexes explicitly - nobody uses read-only mappings. Reported-by: Hugh Dickins Signed-off-by: KOSAKI Motohiro Acked-by: Peter Zijlstra Acked-by: Darren Hart Cc: Linus Torvalds Cc: KAMEZAWA Hiroyuki Cc: Nick Piggin Cc: Ulrich Drepper LKML-Reference: <20100105162633.45A2.A69D9226@jp.fujitsu.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index d73ef1f3e55d..3b749090411d 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -203,8 +203,6 @@ static void drop_futex_key_refs(union futex_key *key) * @uaddr: virtual address of the futex * @fshared: 0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED * @key: address where result is stored. - * @rw: mapping needs to be read/write (values: VERIFY_READ, - * VERIFY_WRITE) * * Returns a negative error code or 0 * The key words are stored in *key on success. @@ -216,7 +214,7 @@ static void drop_futex_key_refs(union futex_key *key) * lock_page() might sleep, the caller should not hold a spinlock. */ static int -get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) +get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key) { unsigned long address = (unsigned long)uaddr; struct mm_struct *mm = current->mm; @@ -239,7 +237,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) * but access_ok() should be faster than find_vma() */ if (!fshared) { - if (unlikely(!access_ok(rw, uaddr, sizeof(u32)))) + if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) return -EFAULT; key->private.mm = mm; key->private.address = address; @@ -248,7 +246,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) } again: - err = get_user_pages_fast(address, 1, rw == VERIFY_WRITE, &page); + err = get_user_pages_fast(address, 1, 1, &page); if (err < 0) return err; @@ -867,7 +865,7 @@ static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset) if (!bitset) return -EINVAL; - ret = get_futex_key(uaddr, fshared, &key, VERIFY_READ); + ret = get_futex_key(uaddr, fshared, &key); if (unlikely(ret != 0)) goto out; @@ -913,10 +911,10 @@ futex_wake_op(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, int ret, op_ret; retry: - ret = get_futex_key(uaddr1, fshared, &key1, VERIFY_READ); + ret = get_futex_key(uaddr1, fshared, &key1); if (unlikely(ret != 0)) goto out; - ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE); + ret = get_futex_key(uaddr2, fshared, &key2); if (unlikely(ret != 0)) goto out_put_key1; @@ -1175,11 +1173,10 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, pi_state = NULL; } - ret = get_futex_key(uaddr1, fshared, &key1, VERIFY_READ); + ret = get_futex_key(uaddr1, fshared, &key1); if (unlikely(ret != 0)) goto out; - ret = get_futex_key(uaddr2, fshared, &key2, - requeue_pi ? VERIFY_WRITE : VERIFY_READ); + ret = get_futex_key(uaddr2, fshared, &key2); if (unlikely(ret != 0)) goto out_put_key1; @@ -1738,7 +1735,7 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, int fshared, */ retry: q->key = FUTEX_KEY_INIT; - ret = get_futex_key(uaddr, fshared, &q->key, VERIFY_READ); + ret = get_futex_key(uaddr, fshared, &q->key); if (unlikely(ret != 0)) return ret; @@ -1904,7 +1901,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, q.requeue_pi_key = NULL; retry: q.key = FUTEX_KEY_INIT; - ret = get_futex_key(uaddr, fshared, &q.key, VERIFY_WRITE); + ret = get_futex_key(uaddr, fshared, &q.key); if (unlikely(ret != 0)) goto out; @@ -2023,7 +2020,7 @@ static int futex_unlock_pi(u32 __user *uaddr, int fshared) if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current)) return -EPERM; - ret = get_futex_key(uaddr, fshared, &key, VERIFY_WRITE); + ret = get_futex_key(uaddr, fshared, &key); if (unlikely(ret != 0)) goto out; @@ -2215,7 +2212,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared, rt_waiter.task = NULL; key2 = FUTEX_KEY_INIT; - ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE); + ret = get_futex_key(uaddr2, fshared, &key2); if (unlikely(ret != 0)) goto out; From c91ab0438c6700e4be078d64cfb01879986e3bde Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Fri, 15 Jan 2010 17:01:18 -0800 Subject: [PATCH 347/670] page allocator: update NR_FREE_PAGES only when necessary commit 6ccf80eb15ccaca4d3f1ab5162b9ded5eecd9971 upstream. commit f2260e6b (page allocator: update NR_FREE_PAGES only as necessary) made one minor regression. if __rmqueue() was failed, NR_FREE_PAGES stat go wrong. this patch fixes it. Signed-off-by: KOSAKI Motohiro Cc: Mel Gorman Reviewed-by: Minchan Kim Reported-by: Huang Shijie Reviewed-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2bc2ac63f41e..3a78e2e864e8 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1225,10 +1225,10 @@ struct page *buffered_rmqueue(struct zone *preferred_zone, } spin_lock_irqsave(&zone->lock, flags); page = __rmqueue(zone, order, migratetype); - __mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order)); spin_unlock(&zone->lock); if (!page) goto failed; + __mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order)); } __count_zone_vm_events(PGALLOC, zone, 1 << order); From 25d5699981856908986c5afb712481a4c917e00b Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 18 Jan 2010 12:10:48 -0800 Subject: [PATCH 348/670] x86, apic: use physical mode for IBM summit platforms commit dfea91d5a7c795fd6f4e1a97489a98e4e767463e upstream. Chris McDermott from IBM confirmed that hurricane chipset in IBM summit platforms doesn't support logical flat mode. Irrespective of the other things like apic_id's, total number of logical cpu's, Linux kernel should default to physical mode for this system. The 32-bit kernel does so using the OEM checks for the IBM summit platform. Add a similar OEM platform check for the 64bit kernel too. Otherwise the linux kernel boot can hang on this platform under certain bios/platform settings. Signed-off-by: Suresh Siddha Tested-by: Ananth N Mavinakayanahalli Cc: Chris McDermott Cc: Yinghai Lu Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/apic_flat_64.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index d0c99abc26c3..873f81f0bbd8 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -240,6 +240,11 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) printk(KERN_DEBUG "system APIC only can use physical flat"); return 1; } + + if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) { + printk(KERN_DEBUG "IBM Summit detected, will use apic physical"); + return 1; + } #endif return 0; From 7f40c6b6ad3b97dc8aceb3ce73d4d6ed335a8d6d Mon Sep 17 00:00:00 2001 From: Tamas Vincze Date: Fri, 15 Jan 2010 17:01:10 -0800 Subject: [PATCH 349/670] edac: i5000_edac critical fix panic out of bounds commit 118f3e1afd5534c15f9701f33514186cfc841a27 upstream. EDAC MC0: INTERNAL ERROR: channel-b out of range (4 >= 4) Kernel panic - not syncing: EDAC MC0: Uncorrected Error (XEN) Domain 0 crashed: 'noreboot' set - not rebooting. This happens because FERR_NF_FBD bit 28 is not updated on i5000. Due to that, both bits 28 and 29 may be equal to one, returning channel = 3. As this value is invalid, EDAC core generates the panic. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=14568 Signed-off-by: Tamas Vincze Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Doug Thompson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/edac/i5000_edac.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 77a9579d7167..adc10a2ac5f6 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -577,7 +577,13 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, debugf0("\tUncorrected bits= 0x%x\n", ue_errors); branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd); - channel = branch; + + /* + * According with i5000 datasheet, bit 28 has no significance + * for errors M4Err-M12Err and M17Err-M21Err, on FERR_NF_FBD + */ + channel = branch & 2; + bank = NREC_BANK(info->nrecmema); rank = NREC_RANK(info->nrecmema); rdwr = NREC_RDWR(info->nrecmema); From 7f08f93d08ac8363a0c73b98ec3e2f24e952ea8a Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Fri, 8 Jan 2010 12:13:54 -0800 Subject: [PATCH 350/670] x86: SGI UV: Fix mapping of MMIO registers commit fcfbb2b5facd65efa7284cc315225bfe3d1856c2 upstream. This fixes the problem of the initialization code not correctly mapping the entire MMIO space on a UV system. A side effect is the map_high() interface needed to be changed to accommodate different address and size shifts. Signed-off-by: Mike Travis Reviewed-by: Mike Habeck Cc: Jack Steiner Cc: Linus Torvalds LKML-Reference: <4B479202.7080705@sgi.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/x2apic_uv_x.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 2ab35358985e..9ee87cfe0859 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -364,13 +364,13 @@ static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size) enum map_type {map_wb, map_uc}; -static __init void map_high(char *id, unsigned long base, int shift, - int max_pnode, enum map_type map_type) +static __init void map_high(char *id, unsigned long base, int pshift, + int bshift, int max_pnode, enum map_type map_type) { unsigned long bytes, paddr; - paddr = base << shift; - bytes = (1UL << shift) * (max_pnode + 1); + paddr = base << pshift; + bytes = (1UL << bshift) * (max_pnode + 1); printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, paddr + bytes); if (map_type == map_uc) @@ -386,7 +386,7 @@ static __init void map_gru_high(int max_pnode) gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR); if (gru.s.enable) - map_high("GRU", gru.s.base, shift, max_pnode, map_wb); + map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb); } static __init void map_mmr_high(int max_pnode) @@ -396,7 +396,7 @@ static __init void map_mmr_high(int max_pnode) mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR); if (mmr.s.enable) - map_high("MMR", mmr.s.base, shift, max_pnode, map_uc); + map_high("MMR", mmr.s.base, shift, shift, max_pnode, map_uc); } static __init void map_mmioh_high(int max_pnode) @@ -406,7 +406,8 @@ static __init void map_mmioh_high(int max_pnode) mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR); if (mmioh.s.enable) - map_high("MMIOH", mmioh.s.base, shift, max_pnode, map_uc); + map_high("MMIOH", mmioh.s.base, shift, mmioh.s.m_io, + max_pnode, map_uc); } static __init void uv_rtc_init(void) From 33faa3c2d01eaff106a231a3fb01f9f532e9821b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 7 Jan 2010 16:16:14 +0000 Subject: [PATCH 351/670] mfd: WM835x GPIO direction register is not locked commit 8e6ba2dfa2d6c4691a83a63e211990a8bd7b788b upstream. No need to set the security key when writing to it. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/wm8350-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index ba27c9dc1ad3..ca6b098a8fd6 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -134,8 +134,7 @@ static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) return 0; - if ((reg == WM8350_GPIO_CONFIGURATION_I_O) || - (reg >= WM8350_GPIO_FUNCTION_SELECT_1 && + if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && reg <= WM8350_GPIO_FUNCTION_SELECT_4) || (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) From 34e7aa0779b24f22d38b31a804bca700a0d38ea1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 4 Jan 2010 18:05:00 +0000 Subject: [PATCH 352/670] mfd: Correct WM835x ISINK ramp time defines commit 9dffe2a32b0deef52605d50527c0d240b15cabf7 upstream. The constants used to specify ISINK ramp times for WM835x had the wrong shifts so that the on times applied to the off ramp and vice versa. The masks for the bitfields are correct. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz Signed-off-by: Greg Kroah-Hartman --- include/linux/mfd/wm8350/pmic.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/include/linux/mfd/wm8350/pmic.h b/include/linux/mfd/wm8350/pmic.h index be3264e286e0..e786fe9841ef 100644 --- a/include/linux/mfd/wm8350/pmic.h +++ b/include/linux/mfd/wm8350/pmic.h @@ -666,20 +666,20 @@ #define WM8350_ISINK_FLASH_DUR_64MS (1 << 8) #define WM8350_ISINK_FLASH_DUR_96MS (2 << 8) #define WM8350_ISINK_FLASH_DUR_1024MS (3 << 8) -#define WM8350_ISINK_FLASH_ON_INSTANT (0 << 4) -#define WM8350_ISINK_FLASH_ON_0_25S (1 << 4) -#define WM8350_ISINK_FLASH_ON_0_50S (2 << 4) -#define WM8350_ISINK_FLASH_ON_1_00S (3 << 4) -#define WM8350_ISINK_FLASH_ON_1_95S (1 << 4) -#define WM8350_ISINK_FLASH_ON_3_91S (2 << 4) -#define WM8350_ISINK_FLASH_ON_7_80S (3 << 4) -#define WM8350_ISINK_FLASH_OFF_INSTANT (0 << 0) -#define WM8350_ISINK_FLASH_OFF_0_25S (1 << 0) -#define WM8350_ISINK_FLASH_OFF_0_50S (2 << 0) -#define WM8350_ISINK_FLASH_OFF_1_00S (3 << 0) -#define WM8350_ISINK_FLASH_OFF_1_95S (1 << 0) -#define WM8350_ISINK_FLASH_OFF_3_91S (2 << 0) -#define WM8350_ISINK_FLASH_OFF_7_80S (3 << 0) +#define WM8350_ISINK_FLASH_ON_INSTANT (0 << 0) +#define WM8350_ISINK_FLASH_ON_0_25S (1 << 0) +#define WM8350_ISINK_FLASH_ON_0_50S (2 << 0) +#define WM8350_ISINK_FLASH_ON_1_00S (3 << 0) +#define WM8350_ISINK_FLASH_ON_1_95S (1 << 0) +#define WM8350_ISINK_FLASH_ON_3_91S (2 << 0) +#define WM8350_ISINK_FLASH_ON_7_80S (3 << 0) +#define WM8350_ISINK_FLASH_OFF_INSTANT (0 << 4) +#define WM8350_ISINK_FLASH_OFF_0_25S (1 << 4) +#define WM8350_ISINK_FLASH_OFF_0_50S (2 << 4) +#define WM8350_ISINK_FLASH_OFF_1_00S (3 << 4) +#define WM8350_ISINK_FLASH_OFF_1_95S (1 << 4) +#define WM8350_ISINK_FLASH_OFF_3_91S (2 << 4) +#define WM8350_ISINK_FLASH_OFF_7_80S (3 << 4) /* * Regulator Interrupts. From fe52cee99c5cf51c38c4d150fbc8a84fb8ed97d6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 14 Jan 2010 12:39:02 +0100 Subject: [PATCH 353/670] ALSA: hda - Fix missing capture mixer for ALC861/660 codecs commit c7a8eb103248a110cdbe0530d8c5ce987f099eee upstream. The capture-related mixer elements are missing with ALC861/ALC660 codecs when quirks are present, due to missing call of set_capture_mixer(). Reference: Novell bnc#567340 http://bugzilla.novell.com/show_bug.cgi?id=567340 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a4cb18341d12..075c3a678e2e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -14685,6 +14685,8 @@ static int patch_alc861(struct hda_codec *codec) spec->stream_digital_playback = &alc861_pcm_digital_playback; spec->stream_digital_capture = &alc861_pcm_digital_capture; + if (!spec->cap_mixer) + set_capture_mixer(codec); set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); spec->vmaster_nid = 0x03; From 56a7f72d020e86c33b3c829c9a89d33f8c359305 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 18 Dec 2009 12:22:43 -0300 Subject: [PATCH 354/670] V4L/DVB (13868): gspca - sn9c20x: Fix test of unsigned. commit c60503c1db76bd46577cc7ff4fafa033b675e0e5 upstream. Signed-off-by: Roel Kluin Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/sn9c20x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index cdad3db33367..e0a3b759a4c7 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -2319,7 +2319,7 @@ static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) } } if (avg_lum > MAX_AVG_LUM) { - if (sd->gain - 1 >= 0) { + if (sd->gain >= 1) { sd->gain--; set_gain(gspca_dev); } From 781d5c42490436e4e0b6b624088b109695cf6b00 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 17 Dec 2009 15:27:06 -0800 Subject: [PATCH 355/670] reiserfs: truncate blocks not used by a write commit ec8e2f7466ca370f5e09000ca40a71759afc9ac8 upstream. It can happen that write does not use all the blocks allocated in write_begin either because of some filesystem error (like ENOSPC) or because page with data to write has been removed from memory. We truncate these blocks so that we don't have dangling blocks beyond i_size. Cc: Jeff Mahoney Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/inode.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index a14d6cd9eeda..d240c15bf086 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -2531,6 +2531,12 @@ static int reiserfs_writepage(struct page *page, struct writeback_control *wbc) return reiserfs_write_full_page(page, wbc); } +static void reiserfs_truncate_failed_write(struct inode *inode) +{ + truncate_inode_pages(inode->i_mapping, inode->i_size); + reiserfs_truncate_file(inode, 0); +} + static int reiserfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, @@ -2597,6 +2603,8 @@ static int reiserfs_write_begin(struct file *file, if (ret) { unlock_page(page); page_cache_release(page); + /* Truncate allocated blocks */ + reiserfs_truncate_failed_write(inode); } return ret; } @@ -2689,8 +2697,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, ** transaction tracking stuff when the size changes. So, we have ** to do the i_size updates here. */ - pos += copied; - if (pos > inode->i_size) { + if (pos + copied > inode->i_size) { struct reiserfs_transaction_handle myth; reiserfs_write_lock(inode->i_sb); /* If the file have grown beyond the border where it @@ -2708,7 +2715,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, goto journal_error; } reiserfs_update_inode_transaction(inode); - inode->i_size = pos; + inode->i_size = pos + copied; /* * this will just nest into our transaction. It's important * to use mark_inode_dirty so the inode gets pushed around on the @@ -2735,6 +2742,10 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, out: unlock_page(page); page_cache_release(page); + + if (pos + len > inode->i_size) + reiserfs_truncate_failed_write(inode); + return ret == 0 ? copied : ret; journal_error: From eecd8a9ec6488e6b5c43c1c12368d6fdb8aa9430 Mon Sep 17 00:00:00 2001 From: Christian Schuerer-Waldheim Date: Wed, 6 Jan 2010 14:49:57 +0100 Subject: [PATCH 356/670] HID: add device IDs for new model of Apple Wireless Keyboard commit 23aeb61e7e1f02fb0f3b8f9e798e75537ca1731d upstream. Added device IDs for the new model of the Apple Wireless Keyboard (November 2009). Signed-off-by: Christian Schuerer-Waldheim Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-apple.c | 7 +++++++ drivers/hid/hid-core.c | 3 +++ drivers/hid/hid-ids.h | 3 +++ 3 files changed, 13 insertions(+) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 4b96e7a898cf..5b4d66dc1a05 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -431,6 +431,13 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | + APPLE_ISO_KEYBOARD }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7d05c4bb201e..96783542f7f5 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1287,6 +1287,9 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index adbef5d069c4..e380e7bee8c1 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -88,6 +88,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 From 2db740cb364a38b6bf50e1c61dc6d9615bfe390c Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 19 Jan 2010 12:42:19 +0100 Subject: [PATCH 357/670] PCI/cardbus: Add a fixup hook and fix powerpc commit 2d1c861871d767153538a77c498752b36d4bb4b8 upstream The cardbus code creates PCI devices without ever going through the necessary fixup bits and pieces that normal PCI devices go through. There's in fact a commented out call to pcibios_fixup_bus() in there, it's commented because ... it doesn't work. I could make pcibios_fixup_bus() do the right thing on powerpc easily but I felt it cleaner instead to provide a specific hook pci_fixup_cardbus for which a weak empty implementation is provided by the PCI core. This fixes cardbus on powerbooks and probably all other PowerPC platforms which was broken completely for ever on some platforms and since 2.6.31 on others such as PowerBooks when we made the DMA ops mandatory (since those are setup by the fixups). Acked-by: Dominik Brodowski Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Jesse Barnes Signed-off-by: Stefan Bader Acked-by: Benjamin Herrenschmidt Acked-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/pci-common.c | 13 +++++++++++++ drivers/pci/pci.c | 5 +++++ drivers/pcmcia/cardbus.c | 2 +- include/linux/pci.h | 3 +++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index e8dfdbd9327a..cadbed679fbb 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1107,6 +1107,12 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { struct dev_archdata *sd = &dev->dev.archdata; + /* Cardbus can call us to add new devices to a bus, so ignore + * those who are already fully discovered + */ + if (dev->is_added) + continue; + /* Setup OF node pointer in archdata */ sd->of_node = pci_device_to_OF_node(dev); @@ -1147,6 +1153,13 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) } EXPORT_SYMBOL(pcibios_fixup_bus); +void __devinit pci_fixup_cardbus(struct pci_bus *bus) +{ + /* Now fixup devices on that bus */ + pcibios_setup_bus_devices(bus); +} + + static int skip_isa_ioresource_align(struct pci_dev *dev) { if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) && diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4e4c295a049f..64777220a719 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2723,6 +2723,11 @@ int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev) return 1; } +void __weak pci_fixup_cardbus(struct pci_bus *bus) +{ +} +EXPORT_SYMBOL(pci_fixup_cardbus); + static int __init pci_setup(char *str) { while (str) { diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index db77e1f3309a..5c2679355b72 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -214,7 +214,7 @@ int __ref cb_alloc(struct pcmcia_socket * s) unsigned int max, pass; s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); -// pcibios_fixup_bus(bus); + pci_fixup_cardbus(bus); max = bus->secondary; for (pass = 0; pass < 2; pass++) diff --git a/include/linux/pci.h b/include/linux/pci.h index f5c7cd343e56..2547515f7e92 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -564,6 +564,9 @@ void pcibios_align_resource(void *, struct resource *, resource_size_t, resource_size_t); void pcibios_update_irq(struct pci_dev *, int irq); +/* Weak but can be overriden by arch */ +void pci_fixup_cardbus(struct pci_bus *); + /* Generic PCI functions used internally */ extern struct pci_bus *pci_find_bus(int domain, int busnr); From 94249e60370f0094831ba673881222252d799257 Mon Sep 17 00:00:00 2001 From: "Bryn M. Reeves" Date: Thu, 12 Nov 2009 18:31:54 +0000 Subject: [PATCH 358/670] megaraid_sas: remove sysfs poll_mode_io world writeable permissions commit bb7d3f24c71e528989501617651b669fbed798cb upstream. /sys/bus/pci/drivers/megaraid_sas/poll_mode_io defaults to being world-writable, which seems bad (letting any user affect kernel driver behavior). This turns off group and user write permissions, so that on typical production systems only root can write to it. Signed-off-by: Bryn M. Reeves Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/megaraid/megaraid_sas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 507ccc682046..518712cc7253 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -3451,7 +3451,7 @@ megasas_sysfs_set_poll_mode_io(struct device_driver *dd, return retval; } -static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO, +static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR, megasas_sysfs_show_poll_mode_io, megasas_sysfs_set_poll_mode_io); From 2196ca4e67b04a1e083337aae825c381df0a919c Mon Sep 17 00:00:00 2001 From: Tai-hwa Liang Date: Wed, 13 Jan 2010 00:16:27 -0800 Subject: [PATCH 359/670] Input: pmouse - move Sentelic probe down the list commit 4a18b3ab6ed537b055e3fcfca64ab870b4f9acf0 upstream. Sentelic probes confuse IBM trackpoints so they stop responding to TP_READ_ID command. See: http://bugzilla.kernel.org/show_bug.cgi?id=14970 Let's move FSP detection lower so it is probed after trackpoint and others, just before we strat probing for Intellimouse Explorer. Signed-off-by: Tai-hwa Liang Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/psmouse-base.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 07c53798301a..0876d82cecfc 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -667,19 +667,6 @@ static int psmouse_extensions(struct psmouse *psmouse, max_proto = PSMOUSE_IMEX; } -/* - * Try Finger Sensing Pad - */ - if (max_proto > PSMOUSE_IMEX) { - if (fsp_detect(psmouse, set_properties) == 0) { - if (!set_properties || fsp_init(psmouse) == 0) - return PSMOUSE_FSP; -/* - * Init failed, try basic relative protocols - */ - max_proto = PSMOUSE_IMEX; - } - } if (max_proto > PSMOUSE_IMEX) { if (genius_detect(psmouse, set_properties) == 0) @@ -695,6 +682,21 @@ static int psmouse_extensions(struct psmouse *psmouse, return PSMOUSE_TOUCHKIT_PS2; } +/* + * Try Finger Sensing Pad. We do it here because its probe upsets + * Trackpoint devices (causing TP_READ_ID command to time out). + */ + if (max_proto > PSMOUSE_IMEX) { + if (fsp_detect(psmouse, set_properties) == 0) { + if (!set_properties || fsp_init(psmouse) == 0) + return PSMOUSE_FSP; +/* + * Init failed, try basic relative protocols + */ + max_proto = PSMOUSE_IMEX; + } + } + /* * Reset to defaults in case the device got confused by extended * protocol probes. Note that we follow up with full reset because From 9fc68ca0778831d6901fc9bcfa65db214770f97f Mon Sep 17 00:00:00 2001 From: Ike Panhc Date: Thu, 3 Dec 2009 07:45:11 +0000 Subject: [PATCH 360/670] asus-laptop: add Lenovo SL hotkey support commit 14f8af311e7d3e4198cbaade84a34f86505dcb37 upstream. Lenovo SL series laptop has a very similar DSDT with Asus laptops. We can easily have the extra ACPI function support with little modification in asus-laptop.c Here is the hotkey enablement for Lenovo SL series laptop. This patch will enable the following hotkey: - Volumn Up - Volumn Down - Mute - Screen Lock (Fn+F2) - Battery Status (Fn+F3) - WLAN switch (Fn+F5) - Video output switch (Fn+F7) - Touchpad switch (Fn+F8) - Screen Magnifier (Fn+Space) The following function of Lenovo SL laptop is still need to be enabled: - Hotkey: KEY_SUSPEND (Fn+F4), KEY_SLEEP (Fn+F12), Dock Eject (Fn+F9) - Rfkill for bluetooth and wlan - LenovoCare LED - Hwmon for fan speed - Fingerprint scanner - Active Protection System Signed-off-by: Ike Panhc Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/asus-laptop.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 849359a80942..767cb61c1a80 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -221,6 +221,7 @@ static struct asus_hotk *hotk; */ static const struct acpi_device_id asus_device_ids[] = { {"ATK0100", 0}, + {"ATK0101", 0}, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, asus_device_ids); @@ -293,6 +294,11 @@ struct key_entry { enum { KE_KEY, KE_END }; static struct key_entry asus_keymap[] = { + {KE_KEY, 0x02, KEY_SCREENLOCK}, + {KE_KEY, 0x05, KEY_WLAN}, + {KE_KEY, 0x08, BTN_TOUCH}, + {KE_KEY, 0x17, KEY_ZOOM}, + {KE_KEY, 0x1f, KEY_BATTERY}, {KE_KEY, 0x30, KEY_VOLUMEUP}, {KE_KEY, 0x31, KEY_VOLUMEDOWN}, {KE_KEY, 0x32, KEY_MUTE}, @@ -312,6 +318,8 @@ static struct key_entry asus_keymap[] = { {KE_KEY, 0x5F, KEY_WLAN}, {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, + {KE_KEY, 0x62, KEY_SWITCHVIDEOMODE}, + {KE_KEY, 0x63, KEY_SWITCHVIDEOMODE}, {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ {KE_KEY, 0x82, KEY_CAMERA}, {KE_KEY, 0x8A, KEY_PROG1}, From 896fb0d2fb2f6ba691eeac7fc6fde604629d0b59 Mon Sep 17 00:00:00 2001 From: David Miller Date: Sun, 13 Dec 2009 18:25:02 -0800 Subject: [PATCH 361/670] sched: Fix cpu_clock() in NMIs, on !CONFIG_HAVE_UNSTABLE_SCHED_CLOCK commit b9f8fcd55bbdb037e5332dbdb7b494f0b70861ac upstream. Relax stable-sched-clock architectures to not save/disable/restore hardirqs in cpu_clock(). The background is that I was trying to resolve a sparc64 perf issue when I discovered this problem. On sparc64 I implement pseudo NMIs by simply running the kernel at IRQ level 14 when local_irq_disable() is called, this allows performance counter events to still come in at IRQ level 15. This doesn't work if any code in an NMI handler does local_irq_save() or local_irq_disable() since the "disable" will kick us back to cpu IRQ level 14 thus letting NMIs back in and we recurse. The only path which that does that in the perf event IRQ handling path is the code supporting frequency based events. It uses cpu_clock(). cpu_clock() simply invokes sched_clock() with IRQs disabled. And that's a fundamental bug all on it's own, particularly for the HAVE_UNSTABLE_SCHED_CLOCK case. NMIs can thus get into the sched_clock() code interrupting the local IRQ disable code sections of it. Furthermore, for the not-HAVE_UNSTABLE_SCHED_CLOCK case, the IRQ disabling done by cpu_clock() is just pure overhead and completely unnecessary. So the core problem is that sched_clock() is not NMI safe, but we are invoking it from NMI contexts in the perf events code (via cpu_clock()). A less important issue is the overhead of IRQ disabling when it isn't necessary in cpu_clock(). CONFIG_HAVE_UNSTABLE_SCHED_CLOCK architectures are not affected by this patch. Signed-off-by: David S. Miller Acked-by: Peter Zijlstra Cc: Mike Galbraith LKML-Reference: <20091213.182502.215092085.davem@davemloft.net> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched_clock.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/kernel/sched_clock.c b/kernel/sched_clock.c index 479ce5682d7c..5b496132c28a 100644 --- a/kernel/sched_clock.c +++ b/kernel/sched_clock.c @@ -236,6 +236,18 @@ void sched_clock_idle_wakeup_event(u64 delta_ns) } EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event); +unsigned long long cpu_clock(int cpu) +{ + unsigned long long clock; + unsigned long flags; + + local_irq_save(flags); + clock = sched_clock_cpu(cpu); + local_irq_restore(flags); + + return clock; +} + #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ void sched_clock_init(void) @@ -251,17 +263,12 @@ u64 sched_clock_cpu(int cpu) return sched_clock(); } -#endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ unsigned long long cpu_clock(int cpu) { - unsigned long long clock; - unsigned long flags; - - local_irq_save(flags); - clock = sched_clock_cpu(cpu); - local_irq_restore(flags); - - return clock; + return sched_clock_cpu(cpu); } + +#endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ + EXPORT_SYMBOL_GPL(cpu_clock); From 9d6567c5369d439440ad96e8b402919d4480e2c6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 4 Jan 2010 15:37:04 -0800 Subject: [PATCH 362/670] sparc64: Fix NMI programming when perf events are active. [ Upstream commit 8183e2b38480672a1f61d416812ac078ce94b67b ] If perf events are active, we should not reset the %pcr to PCR_PIC_PRIV. That perf events code does the management. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/nmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index b129611590a4..477127450e53 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c @@ -96,7 +96,6 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) int cpu = smp_processor_id(); clear_softint(1 << irq); - pcr_ops->write(PCR_PIC_PRIV); local_cpu_data().__nmi_count++; @@ -105,6 +104,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) if (notify_die(DIE_NMI, "nmi", regs, 0, pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) touched = 1; + else + pcr_ops->write(PCR_PIC_PRIV); sum = kstat_irqs_cpu(0, cpu); if (__get_cpu_var(nmi_touch)) { From 4bff5fff57875872c813022bfa3a523b88196c98 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 4 Jan 2010 23:16:03 -0800 Subject: [PATCH 363/670] sparc64: Fix Niagara2 perf event handling. [ Upstream commit e04ed38d4e0cd32141f723560efcc8252b0241e2 ] For chips like Niagara2 that have true overflow indications in the %pcr (which we don't actually need and don't use) the interrupt signal persists until the overflow bits are cleared by an explicit %pcr write. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- arch/sparc/kernel/perf_event.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index fa5936e1c3b9..198fb4e79ba2 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -986,6 +986,17 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self, data.addr = 0; cpuc = &__get_cpu_var(cpu_hw_events); + + /* If the PMU has the TOE IRQ enable bits, we need to do a + * dummy write to the %pcr to clear the overflow bits and thus + * the interrupt. + * + * Do this before we peek at the counters to determine + * overflow so we don't lose any events. + */ + if (sparc_pmu->irq_bit) + pcr_ops->write(cpuc->pcr); + for (idx = 0; idx < MAX_HWEVENTS; idx++) { struct perf_event *event = cpuc->events[idx]; struct hw_perf_event *hwc; From c1f77a7025d7802dc29ca1a8fe84e416973525ed Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Sat, 16 Jan 2010 20:43:13 +0100 Subject: [PATCH 364/670] i2c: Do not use device name after device_unregister MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c556752109794a5ff199b80a1673336b4df8433a upstream. dev_dbg outputs dev_name, which is released with device_unregister. This bug resulted in output like this: i2c Xy2�0: adapter [SMBus I801 adapter at 1880] unregistered The right output would be: i2c i2c-0: adapter [SMBus I801 adapter at 1880] unregistered Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 296504355142..3bf7b0a270f5 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -801,6 +801,9 @@ int i2c_del_adapter(struct i2c_adapter *adap) adap->dev.parent); #endif + /* device name is gone after device_unregister */ + dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); + /* clean up the sysfs representation */ init_completion(&adap->dev_released); device_unregister(&adap->dev); @@ -813,8 +816,6 @@ int i2c_del_adapter(struct i2c_adapter *adap) idr_remove(&i2c_adapter_idr, adap->nr); mutex_unlock(&core_lock); - dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); - /* Clear the device structure in case this adapter is ever going to be added again */ memset(&adap->dev, 0, sizeof(adap->dev)); From 2d22b3821b34d2dec1e263820ffa0b43311d92d2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 16 Jan 2010 20:43:13 +0100 Subject: [PATCH 365/670] i2c/pca: Don't use *_interruptible commit 22f8b2695eda496026623020811cae34590ee3d7 upstream. Unexpected signals can disturb the bus-handling and lock it up. Don't use interruptible in 'wait_event_*' and 'wake_*' as in commits dc1972d02747d2170fb1d78d114801f5ecb27506 (for cpm), 1ab082d7cbd0f34e39a5396cc6340c00bc5d66ef (for mpc), b7af349b175af45f9d87b3bf3f0a221e1831ed39 (for omap). Signed-off-by: Wolfram Sang Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-pca-isa.c | 4 ++-- drivers/i2c/busses/i2c-pca-platform.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index 0ed68e2ccd22..f7346a9bd95f 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -75,7 +75,7 @@ static int pca_isa_waitforcompletion(void *pd) unsigned long timeout; if (irq > -1) { - ret = wait_event_interruptible_timeout(pca_wait, + ret = wait_event_timeout(pca_wait, pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI, pca_isa_ops.timeout); } else { @@ -96,7 +96,7 @@ static void pca_isa_resetchip(void *pd) } static irqreturn_t pca_handler(int this_irq, void *dev_id) { - wake_up_interruptible(&pca_wait); + wake_up(&pca_wait); return IRQ_HANDLED; } diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index c4df9d411cd5..5b2213df5ed0 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -84,7 +84,7 @@ static int i2c_pca_pf_waitforcompletion(void *pd) unsigned long timeout; if (i2c->irq) { - ret = wait_event_interruptible_timeout(i2c->wait, + ret = wait_event_timeout(i2c->wait, i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI, i2c->adap.timeout); } else { @@ -122,7 +122,7 @@ static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id) if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) return IRQ_NONE; - wake_up_interruptible(&i2c->wait); + wake_up(&i2c->wait); return IRQ_HANDLED; } From fdc360e9cd88b119fa978cc812d1f0be69087f9a Mon Sep 17 00:00:00 2001 From: Ping Date: Fri, 15 Jan 2010 17:01:07 -0800 Subject: [PATCH 366/670] serial/8250_pnp: add a new Fujitsu Wacom Tablet PC device commit 3018aa4b1a46946dfd0ee73a533038f24e390539 upstream. This is a new two finger touch Fujitsu Wacom Tablet PC. Signed-off-by: Ping Cheng Cc: Alan Cox Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250_pnp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index d71dfe398940..0cce8a41e696 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -354,6 +354,8 @@ static const struct pnp_device_id pnp_dev_table[] = { { "FUJ02E5", 0 }, /* Fujitsu P-series tablet PC device */ { "FUJ02E6", 0 }, + /* Fujitsu Wacom 2FGT Tablet PC device */ + { "FUJ02E7", 0 }, /* * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in * disguise) From 26931397cc71bcac187efdcd2fc43ce0d41e4eb0 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 4 Dec 2009 09:59:02 +0100 Subject: [PATCH 367/670] sched: Fix task priority bug commit 57785df5ac53c70da9fb53696130f3c551bfe1f9 upstream. 83f9ac removed a call to effective_prio() in wake_up_new_task(), which leads to tasks running at MAX_PRIO. This is caused by the idle thread being set to MAX_PRIO before forking off init. O(1) used that to make sure idle was always preempted, CFS uses check_preempt_curr_idle() for that so we can savely remove this bit of legacy code. Reported-by: Mike Galbraith Tested-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1259754383.4003.610.camel@laptop> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index dd0dccde5df0..bf841d85b9ba 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3177,10 +3177,6 @@ static void pull_task(struct rq *src_rq, struct task_struct *p, deactivate_task(src_rq, p, 0); set_task_cpu(p, this_cpu); activate_task(this_rq, p, 0); - /* - * Note that idle threads have a prio of MAX_PRIO, for this test - * to be always true for them. - */ check_preempt_curr(this_rq, p, 0); } @@ -6982,7 +6978,6 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) __sched_fork(idle); idle->se.exec_start = sched_clock(); - idle->prio = idle->normal_prio = MAX_PRIO; cpumask_copy(&idle->cpus_allowed, cpumask_of(cpu)); __set_task_cpu(idle, cpu); @@ -7686,7 +7681,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) spin_lock_irq(&rq->lock); update_rq_clock(rq); deactivate_task(rq, rq->idle, 0); - rq->idle->static_prio = MAX_PRIO; __setscheduler(rq, rq->idle, SCHED_NORMAL, 0); rq->idle->sched_class = &idle_sched_class; migrate_dead_tasks(cpu); From af55a3da5049fb26a84ba562c7c8b55b910ff234 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Wed, 13 Jan 2010 21:14:09 +0900 Subject: [PATCH 368/670] vfs: Fix vmtruncate() regression commit cedabed49b39b4319bccc059a63344b6232b619c upstream. If __block_prepare_write() was failed in block_write_begin(), the allocated blocks can be outside of ->i_size. But new truncate_pagecache() in vmtuncate() does nothing if new < old. It means the above usage is not working anymore. So, this patch fixes it by removing "new < old" check. It would need more cleanup/change. But, now -rc and truncate working is in progress, so, this tried to fix it minimum change. Acked-by: Nick Piggin Signed-off-by: OGAWA Hirofumi Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/truncate.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/mm/truncate.c b/mm/truncate.c index 450cebdabfc0..258bda7ec31d 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -516,22 +516,20 @@ EXPORT_SYMBOL_GPL(invalidate_inode_pages2); */ void truncate_pagecache(struct inode *inode, loff_t old, loff_t new) { - if (new < old) { - struct address_space *mapping = inode->i_mapping; + struct address_space *mapping = inode->i_mapping; - /* - * unmap_mapping_range is called twice, first simply for - * efficiency so that truncate_inode_pages does fewer - * single-page unmaps. However after this first call, and - * before truncate_inode_pages finishes, it is possible for - * private pages to be COWed, which remain after - * truncate_inode_pages finishes, hence the second - * unmap_mapping_range call must be made for correctness. - */ - unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); - truncate_inode_pages(mapping, new); - unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); - } + /* + * unmap_mapping_range is called twice, first simply for + * efficiency so that truncate_inode_pages does fewer + * single-page unmaps. However after this first call, and + * before truncate_inode_pages finishes, it is possible for + * private pages to be COWed, which remain after + * truncate_inode_pages finishes, hence the second + * unmap_mapping_range call must be made for correctness. + */ + unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); + truncate_inode_pages(mapping, new); + unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); } EXPORT_SYMBOL(truncate_pagecache); From a2febcd43d859a48672ad922990bd27e5628271f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 22 Jan 2010 15:23:21 -0800 Subject: [PATCH 369/670] Linux 2.6.32.5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6d13598f153f..4ebd3f16a716 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = .4 +EXTRAVERSION = .5 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* From d547e913ca2e6ec29510cca3e72a3cc430e53b89 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 15 Dec 2009 15:13:07 -0800 Subject: [PATCH 370/670] x86, msr/cpuid: Register enough minors for the MSR and CPUID drivers commit 0b962d473af32ec334df271b54ff4973cb2b4c73 upstream. register_chrdev() hardcodes registering 256 minors, presumably to avoid breaking old drivers. However, we need to register enough minors so that we have all possible CPUs. checkpatch warns on this patch, but the patch is correct: NR_CPUS here is a static *upper bound* on the *maximum CPU index* (not *number of CPUs!*) and that is what we want. Reported-and-tested-by: Russ Anderson Cc: Tejun Heo Cc: Alan Cox Cc: Takashi Iwai Cc: Alexander Viro Signed-off-by: H. Peter Anvin LKML-Reference: Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpuid.c | 5 +++-- arch/x86/kernel/msr.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 6a52d4b36a30..f8590c509423 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -192,7 +192,8 @@ static int __init cpuid_init(void) int i, err = 0; i = 0; - if (register_chrdev(CPUID_MAJOR, "cpu/cpuid", &cpuid_fops)) { + if (__register_chrdev(CPUID_MAJOR, 0, NR_CPUS, + "cpu/cpuid", &cpuid_fops)) { printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n", CPUID_MAJOR); err = -EBUSY; @@ -221,7 +222,7 @@ static int __init cpuid_init(void) } class_destroy(cpuid_class); out_chrdev: - unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); + __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid"); out: return err; } diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 6a3cefc7dda1..b42e63baa8e4 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -251,7 +251,7 @@ static int __init msr_init(void) int i, err = 0; i = 0; - if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) { + if (__register_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr", &msr_fops)) { printk(KERN_ERR "msr: unable to get major %d for msr\n", MSR_MAJOR); err = -EBUSY; @@ -279,7 +279,7 @@ static int __init msr_init(void) msr_device_destroy(i); class_destroy(msr_class); out_chrdev: - unregister_chrdev(MSR_MAJOR, "cpu/msr"); + __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); out: return err; } From ccb90b8b6aae814987b23d60d13b4d32dc03a389 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 10 Jan 2010 04:32:11 -0300 Subject: [PATCH 371/670] V4L/DVB (13900): gspca - sunplus: Fix bridge exchanges. commit 07d1c69b2dcfdd1b21e36af0ff8b9506234908ee upstream. A previous code optimization inverted bridge registers and values, doing a regression in kernel 2.6.32. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/gspca/sunplus.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index aa8f995ce04e..28b4625bc1a8 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -705,7 +705,7 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) rc = spca504B_PollingDataReady(gspca_dev); /* Init the cam width height with some values get on init ? */ - reg_w_riv(dev, 0x31, 0, 0x04); + reg_w_riv(dev, 0x31, 0x04, 0); spca504B_WaitCmdStatus(gspca_dev); rc = spca504B_PollingDataReady(gspca_dev); break; @@ -807,14 +807,14 @@ static void init_ctl_reg(struct gspca_dev *gspca_dev) default: /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA504B: */ - reg_w_riv(dev, 0, 0x00, 0x21ad); /* hue */ - reg_w_riv(dev, 0, 0x01, 0x21ac); /* sat/hue */ - reg_w_riv(dev, 0, 0x00, 0x21a3); /* gamma */ + reg_w_riv(dev, 0, 0x21ad, 0x00); /* hue */ + reg_w_riv(dev, 0, 0x21ac, 0x01); /* sat/hue */ + reg_w_riv(dev, 0, 0x21a3, 0x00); /* gamma */ break; case BRIDGE_SPCA536: - reg_w_riv(dev, 0, 0x40, 0x20f5); - reg_w_riv(dev, 0, 0x01, 0x20f4); - reg_w_riv(dev, 0, 0x00, 0x2089); + reg_w_riv(dev, 0, 0x20f5, 0x40); + reg_w_riv(dev, 0, 0x20f4, 0x01); + reg_w_riv(dev, 0, 0x2089, 0x00); break; } if (pollreg) @@ -888,11 +888,11 @@ static int sd_init(struct gspca_dev *gspca_dev) switch (sd->bridge) { case BRIDGE_SPCA504B: reg_w_riv(dev, 0x1d, 0x00, 0); - reg_w_riv(dev, 0, 0x01, 0x2306); - reg_w_riv(dev, 0, 0x00, 0x0d04); - reg_w_riv(dev, 0, 0x00, 0x2000); - reg_w_riv(dev, 0, 0x13, 0x2301); - reg_w_riv(dev, 0, 0x00, 0x2306); + reg_w_riv(dev, 0, 0x2306, 0x01); + reg_w_riv(dev, 0, 0x0d04, 0x00); + reg_w_riv(dev, 0, 0x2000, 0x00); + reg_w_riv(dev, 0, 0x2301, 0x13); + reg_w_riv(dev, 0, 0x2306, 0x00); /* fall thru */ case BRIDGE_SPCA533: spca504B_PollingDataReady(gspca_dev); @@ -1011,7 +1011,7 @@ static int sd_start(struct gspca_dev *gspca_dev) spca504B_WaitCmdStatus(gspca_dev); break; default: - reg_w_riv(dev, 0x31, 0, 0x04); + reg_w_riv(dev, 0x31, 0x04, 0); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; From 50e49751f94abb0b79563b69bd31392b8b477a2a Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Wed, 23 Dec 2009 10:27:22 -0200 Subject: [PATCH 372/670] Staging: asus_oled: fix oops in 2.6.32.2 commit 20633bf0141c5e93e3396770d5eb7d200ee4068a upstream. After updating to 2.6.32 kernel, I started experiencing Oopses caused by the asus_oled module. After quick investigation, I wrapped this simple patch which fixes an Oops in by asus_oled module on 2.6.32.2 kernel, caused by incorrect usage of strict_strtoul function call within set_enabled and set_disabled functions. This can be triggered by simple running the userspace client for asus_old (e.g., 'asusoled -e' or 'asusoled -d'). Signed-off-by: Eugeni Dodonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/asus_oled/asus_oled.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index f4c26572c7df..43c57b7688ab 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -194,9 +194,11 @@ static ssize_t set_enabled(struct device *dev, struct device_attribute *attr, { struct usb_interface *intf = to_usb_interface(dev); struct asus_oled_dev *odev = usb_get_intfdata(intf); - int temp = strict_strtoul(buf, 10, NULL); + unsigned long value; + if (strict_strtoul(buf, 10, &value)) + return -EINVAL; - enable_oled(odev, temp); + enable_oled(odev, value); return count; } @@ -207,10 +209,12 @@ static ssize_t class_set_enabled(struct device *device, { struct asus_oled_dev *odev = (struct asus_oled_dev *) dev_get_drvdata(device); + unsigned long value; - int temp = strict_strtoul(buf, 10, NULL); + if (strict_strtoul(buf, 10, &value)) + return -EINVAL; - enable_oled(odev, temp); + enable_oled(odev, value); return count; } From b70922a1819f26c3962a184070d9370dfae634a9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 8 Jan 2010 09:06:40 -0800 Subject: [PATCH 373/670] Staging: hv: fix smp problems in the hyperv core code commit 7692fd4d441afac728cb83fdd33349d5ba07406c upstream. This fixes a number of SMP problems that were in the hyperv core code. Patch originally written by K. Y. Srinivasan but forward ported to the latest in-kernel code and tweaked slightly by me. Novell, Inc. hereby disclaims all copyright in any derivative work copyright associated with this patch. Signed-off-by: K. Y. Srinivasan Cc: Hank Janssen Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/Hv.c | 50 +++++++++++++++++++------------------- drivers/staging/hv/Hv.h | 6 ++--- drivers/staging/hv/Vmbus.c | 12 +++++---- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c index c5b6613f2f2f..c2809f2a2ce0 100644 --- a/drivers/staging/hv/Hv.c +++ b/drivers/staging/hv/Hv.c @@ -386,7 +386,7 @@ u16 HvSignalEvent(void) * retrieve the initialized message and event pages. Otherwise, we create and * initialize the message and event pages. */ -int HvSynicInit(u32 irqVector) +void HvSynicInit(void *irqarg) { u64 version; union hv_synic_simp simp; @@ -394,13 +394,14 @@ int HvSynicInit(u32 irqVector) union hv_synic_sint sharedSint; union hv_synic_scontrol sctrl; u64 guestID; - int ret = 0; + u32 irqVector = *((u32 *)(irqarg)); + int cpu = smp_processor_id(); DPRINT_ENTER(VMBUS); if (!gHvContext.HypercallPage) { DPRINT_EXIT(VMBUS); - return ret; + return; } /* Check the version */ @@ -425,27 +426,27 @@ int HvSynicInit(u32 irqVector) */ rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID); if (guestID == HV_LINUX_GUEST_ID) { - gHvContext.synICMessagePage[0] = + gHvContext.synICMessagePage[cpu] = phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT); - gHvContext.synICEventPage[0] = + gHvContext.synICEventPage[cpu] = phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT); } else { DPRINT_ERR(VMBUS, "unknown guest id!!"); goto Cleanup; } DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p", - gHvContext.synICMessagePage[0], - gHvContext.synICEventPage[0]); + gHvContext.synICMessagePage[cpu], + gHvContext.synICEventPage[cpu]); } else { - gHvContext.synICMessagePage[0] = osd_PageAlloc(1); - if (gHvContext.synICMessagePage[0] == NULL) { + gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); + if (gHvContext.synICMessagePage[cpu] == NULL) { DPRINT_ERR(VMBUS, "unable to allocate SYNIC message page!!"); goto Cleanup; } - gHvContext.synICEventPage[0] = osd_PageAlloc(1); - if (gHvContext.synICEventPage[0] == NULL) { + gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); + if (gHvContext.synICEventPage[cpu] == NULL) { DPRINT_ERR(VMBUS, "unable to allocate SYNIC event page!!"); goto Cleanup; @@ -454,7 +455,7 @@ int HvSynicInit(u32 irqVector) /* Setup the Synic's message page */ rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); simp.SimpEnabled = 1; - simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0]) + simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu]) >> PAGE_SHIFT; DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", @@ -465,7 +466,7 @@ int HvSynicInit(u32 irqVector) /* Setup the Synic's event page */ rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); siefp.SiefpEnabled = 1; - siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0]) + siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu]) >> PAGE_SHIFT; DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", @@ -501,32 +502,30 @@ int HvSynicInit(u32 irqVector) DPRINT_EXIT(VMBUS); - return ret; + return; Cleanup: - ret = -1; - if (gHvContext.GuestId == HV_LINUX_GUEST_ID) { - if (gHvContext.synICEventPage[0]) - osd_PageFree(gHvContext.synICEventPage[0], 1); + if (gHvContext.synICEventPage[cpu]) + osd_PageFree(gHvContext.synICEventPage[cpu], 1); - if (gHvContext.synICMessagePage[0]) - osd_PageFree(gHvContext.synICMessagePage[0], 1); + if (gHvContext.synICMessagePage[cpu]) + osd_PageFree(gHvContext.synICMessagePage[cpu], 1); } DPRINT_EXIT(VMBUS); - - return ret; + return; } /** * HvSynicCleanup - Cleanup routine for HvSynicInit(). */ -void HvSynicCleanup(void) +void HvSynicCleanup(void *arg) { union hv_synic_sint sharedSint; union hv_synic_simp simp; union hv_synic_siefp siefp; + int cpu = smp_processor_id(); DPRINT_ENTER(VMBUS); @@ -539,6 +538,7 @@ void HvSynicCleanup(void) sharedSint.Masked = 1; + /* Need to correctly cleanup in the case of SMP!!! */ /* Disable the interrupt */ wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); @@ -560,8 +560,8 @@ void HvSynicCleanup(void) wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); - osd_PageFree(gHvContext.synICMessagePage[0], 1); - osd_PageFree(gHvContext.synICEventPage[0], 1); + osd_PageFree(gHvContext.synICMessagePage[cpu], 1); + osd_PageFree(gHvContext.synICEventPage[cpu], 1); } DPRINT_EXIT(VMBUS); diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h index 5379e4bfc56e..fce4b5cdac30 100644 --- a/drivers/staging/hv/Hv.h +++ b/drivers/staging/hv/Hv.h @@ -93,7 +93,7 @@ static const struct hv_guid VMBUS_SERVICE_ID = { }, }; -#define MAX_NUM_CPUS 1 +#define MAX_NUM_CPUS 32 struct hv_input_signal_event_buffer { @@ -137,8 +137,8 @@ extern u16 HvPostMessage(union hv_connection_id connectionId, extern u16 HvSignalEvent(void); -extern int HvSynicInit(u32 irqVector); +extern void HvSynicInit(void *irqarg); -extern void HvSynicCleanup(void); +extern void HvSynicCleanup(void *arg); #endif /* __HV_H__ */ diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c index a4dd06f6d459..35a023e9f9d1 100644 --- a/drivers/staging/hv/Vmbus.c +++ b/drivers/staging/hv/Vmbus.c @@ -129,7 +129,7 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo) /* strcpy(dev->name, "vmbus"); */ /* SynIC setup... */ - ret = HvSynicInit(*irqvector); + on_each_cpu(HvSynicInit, (void *)irqvector, 1); /* Connect to VMBus in the root partition */ ret = VmbusConnect(); @@ -150,7 +150,7 @@ static int VmbusOnDeviceRemove(struct hv_device *dev) DPRINT_ENTER(VMBUS); VmbusChannelReleaseUnattachedChannels(); VmbusDisconnect(); - HvSynicCleanup(); + on_each_cpu(HvSynicCleanup, NULL, 1); DPRINT_EXIT(VMBUS); return ret; @@ -173,7 +173,8 @@ static void VmbusOnCleanup(struct hv_driver *drv) */ static void VmbusOnMsgDPC(struct hv_driver *drv) { - void *page_addr = gHvContext.synICMessagePage[0]; + int cpu = smp_processor_id(); + void *page_addr = gHvContext.synICMessagePage[cpu]; struct hv_message *msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; struct hv_message *copied; @@ -230,11 +231,12 @@ static void VmbusOnEventDPC(struct hv_driver *drv) static int VmbusOnISR(struct hv_driver *drv) { int ret = 0; + int cpu = smp_processor_id(); void *page_addr; struct hv_message *msg; union hv_synic_event_flags *event; - page_addr = gHvContext.synICMessagePage[0]; + page_addr = gHvContext.synICMessagePage[cpu]; msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; DPRINT_ENTER(VMBUS); @@ -248,7 +250,7 @@ static int VmbusOnISR(struct hv_driver *drv) } /* TODO: Check if there are events to be process */ - page_addr = gHvContext.synICEventPage[0]; + page_addr = gHvContext.synICEventPage[cpu]; event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; /* Since we are a child, we only need to check bit 0 */ From 179b7e53797c61a7652075eb48c6008dbd2b88d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 17 Dec 2009 07:07:19 -0800 Subject: [PATCH 374/670] tty: fix race in tty_fasync commit 703625118069f9f8960d356676662d3db5a9d116 upstream. We need to keep the lock held over the call to __f_setown() to prevent a PID race. Thanks to Al Viro for pointing out the problem, and to Travis for making us look here in the first place. Cc: Eric W. Biederman Cc: Al Viro Cc: Alan Cox Cc: Linus Torvalds Cc: Tavis Ormandy Cc: Jeff Dike Cc: Julien Tinnes Cc: Matt Mackall Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 59499ee0fe6a..e919bd9c92d2 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1930,8 +1930,8 @@ static int tty_fasync(int fd, struct file *filp, int on) pid = task_pid(current); type = PIDTYPE_PID; } - spin_unlock_irqrestore(&tty->ctrl_lock, flags); retval = __f_setown(filp, pid, type, 0); + spin_unlock_irqrestore(&tty->ctrl_lock, flags); if (retval) goto out; } else { From 36212162584e722f432f531d7611099e31fe9f3e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Jan 2010 12:34:32 +0300 Subject: [PATCH 375/670] ecryptfs: use after free commit ece550f51ba175c14ec3ec047815927d7386ea1f upstream. The "full_alg_name" variable is used on a couple error paths, so we shouldn't free it until the end. Signed-off-by: Dan Carpenter Signed-off-by: Tyler Hicks 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 fbb6e5eed697..7cb0a59f4b9d 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1748,7 +1748,7 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, size_t *key_size) { char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; - char *full_alg_name; + char *full_alg_name = NULL; int rc; *key_tfm = NULL; @@ -1763,7 +1763,6 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm, if (rc) goto out; *key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); - kfree(full_alg_name); if (IS_ERR(*key_tfm)) { rc = PTR_ERR(*key_tfm); printk(KERN_ERR "Unable to allocate crypto cipher with name " @@ -1786,6 +1785,7 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm, goto out; } out: + kfree(full_alg_name); return rc; } From 8c535426188c312914bebec8158324dbdbdca2d3 Mon Sep 17 00:00:00 2001 From: Erez Zadok Date: Thu, 3 Dec 2009 13:35:27 -0500 Subject: [PATCH 376/670] ecryptfs: initialize private persistent file before dereferencing pointer commit e27759d7a333d1f25d628c4f7caf845c51be51c2 upstream. Ecryptfs_open dereferences a pointer to the private lower file (the one stored in the ecryptfs inode), without checking if the pointer is NULL. Right afterward, it initializes that pointer if it is NULL. Swap order of statements to first initialize. Bug discovered by Duckjin Kang. Signed-off-by: Duckjin Kang Signed-off-by: Erez Zadok Cc: Dustin Kirkland Cc: Al Viro Signed-off-by: Tyler Hicks Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/file.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 9e944057001b..1744f17ce96e 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -191,13 +191,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | ECRYPTFS_ENCRYPTED); } mutex_unlock(&crypt_stat->cs_mutex); - if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY) - && !(file->f_flags & O_RDONLY)) { - rc = -EPERM; - printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " - "file must hence be opened RO\n", __func__); - goto out; - } if (!ecryptfs_inode_to_private(inode)->lower_file) { rc = ecryptfs_init_persistent_file(ecryptfs_dentry); if (rc) { @@ -208,6 +201,13 @@ static int ecryptfs_open(struct inode *inode, struct file *file) goto out; } } + if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY) + && !(file->f_flags & O_RDONLY)) { + rc = -EPERM; + printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " + "file must hence be opened RO\n", __func__); + goto out; + } ecryptfs_set_file_lower( file, ecryptfs_inode_to_private(inode)->lower_file); if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { From 6fc7937a46b9a5d6b7f61005055a856736f31442 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Jan 2010 16:26:50 +0000 Subject: [PATCH 377/670] nozomi: quick fix for the close/close bug commit eeec32a731631a9bad9abb21c626b9f2840bee0d upstream. Nozomi goes wrong if you get the sequence open open close [stuff] close which turns out to occur on some ppp type setups. This is a quick patch up for the problem. It's not really fixing Nozomi which completely fails to implement tty open/close semantics and all the other needed stuff. Doing it right is a rather more invasive patch set and not one that will backport. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/nozomi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index d3400b20444f..dc52f75a8109 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -1629,10 +1629,10 @@ static void ntty_close(struct tty_struct *tty, struct file *file) dc->open_ttys--; port->count--; - tty_port_tty_set(port, NULL); if (port->count == 0) { DBG1("close: %d", nport->token_dl); + tty_port_tty_set(port, NULL); spin_lock_irqsave(&dc->spin_mutex, flags); dc->last_ier &= ~(nport->token_dl); writew(dc->last_ier, dc->reg_ier); From 04f7ec720e5bc4413540ca5dedde8b9e5a30c401 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 9 Dec 2009 12:31:37 -0800 Subject: [PATCH 378/670] serial: 8250_pnp: use wildcard for serial Wacom tablets commit 6d34855d9aa281f72c533ecb827405139d1b0fe9 upstream. Wacom claims that the WACF namespace will always be devoted to serial Wacom tablets. Remove the existing entries and add a wildcard to avoid having to update the kernel every time they add a new device. Signed-off-by: Ping Cheng Signed-off-by: Matthew Garrett Tested-by: Ping Cheng Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250_pnp.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 0cce8a41e696..deac67e35ce9 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -328,15 +328,7 @@ static const struct pnp_device_id pnp_dev_table[] = { /* U.S. Robotics 56K Voice INT PnP*/ { "USR9190", 0 }, /* Wacom tablets */ - { "WACF004", 0 }, - { "WACF005", 0 }, - { "WACF006", 0 }, - { "WACF007", 0 }, - { "WACF008", 0 }, - { "WACF009", 0 }, - { "WACF00A", 0 }, - { "WACF00B", 0 }, - { "WACF00C", 0 }, + { "WACFXXX", 0 }, /* Compaq touchscreen */ { "FPI2002", 0 }, /* Fujitsu Stylistic touchscreens */ From 911b8be09d303ee5c63295be2ad7b39eec899f45 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 6 Jan 2010 15:48:42 -0800 Subject: [PATCH 379/670] usb: serial: fix memory leak in generic driver commit 2591530204a76fecc843529ade56afe865dd2657 upstream. Fix a regression introduced by commit 715b1dc01fe44537e8fce9566e4bb48d6821d84b ("USB: usb_debug, usb_generic_serial: implement multi urb write"). URB transfer buffer was never freed when using multi-urb writes. Currently the only driver enabling multi-urb writes is usb_debug. Signed-off-by: Johan Hovold Cc: Greg KH Acked-by: Jason Wessel Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index bbe005cefcfb..e0fb294291e3 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -489,6 +489,8 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) dbg("%s - port %d", __func__, port->number); if (port->serial->type->max_in_flight_urbs) { + kfree(urb->transfer_buffer); + spin_lock_irqsave(&port->lock, flags); --port->urbs_in_flight; port->tx_bytes_flight -= urb->transfer_buffer_length; From fa68188da8abe7c20cf44f19326c81a74498b921 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 22 Dec 2009 23:16:32 -0500 Subject: [PATCH 380/670] USB: fix bitmask merge error commit a91b593edd4b3e8aa91f671b763b27b8119eb49d upstream. This patch adds a mask bit which was mistakenly omitted from the as1311 patch (usb-storage: add BAD_SENSE flag). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 716c8d7885fa..33197fa22715 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -430,7 +430,8 @@ static void adjust_quirks(struct us_data *us) u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor); u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct); unsigned f = 0; - unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY | + unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE | + US_FL_FIX_CAPACITY | US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE | US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 | US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | From 186c74d336e2c1377df9e5dc88f7966b2dd6acf7 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 12 Jan 2010 12:32:50 +0100 Subject: [PATCH 381/670] USB: Don't use GFP_KERNEL while we cannot reset a storage device commit acbe2febe71abb2360b008e9ab3ee5c44169f78c upstream. Memory allocations with GFP_KERNEL can cause IO to a storage device which can fail resulting in a need to reset the device. Therefore GFP_KERNEL cannot be safely used between usb_lock_device() and usb_unlock_device(). Replace by GFP_NOIO. Signed-off-by: Oliver Neukum Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 2 +- drivers/usb/core/message.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 96f11715cd26..355dffcc23b0 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -494,7 +494,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, return 0; /* allocate 2^1 pages = 8K (on i386); * should be more than enough for one device */ - pages_start = (char *)__get_free_pages(GFP_KERNEL, 1); + pages_start = (char *)__get_free_pages(GFP_NOIO, 1); if (!pages_start) return -ENOMEM; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index da718e84d58d..980a8d27fa50 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -911,11 +911,11 @@ char *usb_cache_string(struct usb_device *udev, int index) if (index <= 0) return NULL; - buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL); + buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO); if (buf) { len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE); if (len > 0) { - smallbuf = kmalloc(++len, GFP_KERNEL); + smallbuf = kmalloc(++len, GFP_NOIO); if (!smallbuf) return buf; memcpy(smallbuf, buf, len); @@ -1682,7 +1682,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp) { nintf = cp->desc.bNumInterfaces; new_interfaces = kmalloc(nintf * sizeof(*new_interfaces), - GFP_KERNEL); + GFP_NOIO); if (!new_interfaces) { dev_err(&dev->dev, "Out of memory\n"); return -ENOMEM; @@ -1691,7 +1691,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) for (; n < nintf; ++n) { new_interfaces[n] = kzalloc( sizeof(struct usb_interface), - GFP_KERNEL); + GFP_NOIO); if (!new_interfaces[n]) { dev_err(&dev->dev, "Out of memory\n"); ret = -ENOMEM; From 07d577f8868a40466bf3044d8911c06cc7dc283e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 8 Jan 2010 11:17:55 -0500 Subject: [PATCH 382/670] USB: EHCI: fix handling of unusual interrupt intervals commit 1b9a38bfa6e664ff02511314f5586d711c83cc91 upstream. This patch (as1320) fixes two problems related to interrupt-URB scheduling in ehci-hcd. URBs with an interval of 2 or 4 microframes aren't handled. For the time being, the patch reduces to interval to 1 uframe. URBs are constrained to have an interval no larger than 1024 frames by usb_submit_urb(). But some EHCI controllers allow use of a schedule as short as 256 frames; for these controllers we may have to decrease the interval to the actual schedule length. The second problem isn't very significant since few devices expose interrupt endpoints with an interval larger than 256 frames. But the first problem is critical; it will prevent the kernel from working with devices having interrupt intervals of 2 or 4 uframes. Signed-off-by: Alan Stern Tested-by: Glynn Farrow Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 139a2cc3f641..c0d4b39a1180 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -827,9 +827,10 @@ qh_make ( * But interval 1 scheduling is simpler, and * includes high bandwidth. */ - dbg ("intr period %d uframes, NYET!", - urb->interval); - goto done; + urb->interval = 1; + } else if (qh->period > ehci->periodic_size) { + qh->period = ehci->periodic_size; + urb->interval = qh->period << 3; } } else { int think_time; @@ -852,6 +853,10 @@ qh_make ( usb_calc_bus_time (urb->dev->speed, is_input, 0, max_packet (maxp))); qh->period = urb->interval; + if (qh->period > ehci->periodic_size) { + qh->period = ehci->periodic_size; + urb->interval = qh->period; + } } } From bfec5cee7784fdc9c07c9ef72312dbad0bff5690 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 8 Jan 2010 11:18:20 -0500 Subject: [PATCH 383/670] USB: EHCI & UHCI: fix race between root-hub suspend and port resume commit cec3a53c7fe794237b582e8e77fc0e48465e65ee upstream. This patch (as1321) fixes a problem with EHCI and UHCI root-hub suspends: If the suspend occurs while a port is trying to resume, the resume doesn't finish and simply gets lost. When remote wakeup is enabled, this is undesirable behavior. The patch checks first to see if any port resumes are in progress, and if they are then it fails the root-hub suspend with -EBUSY. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 20 +++++++++++++++++++- drivers/usb/host/uhci-hcd.c | 15 ++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 1b6f1c0e5cee..698f46135d5e 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -120,9 +120,26 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) del_timer_sync(&ehci->watchdog); del_timer_sync(&ehci->iaa_watchdog); - port = HCS_N_PORTS (ehci->hcs_params); spin_lock_irq (&ehci->lock); + /* Once the controller is stopped, port resumes that are already + * in progress won't complete. Hence if remote wakeup is enabled + * for the root hub and any ports are in the middle of a resume or + * remote wakeup, we must fail the suspend. + */ + if (hcd->self.root_hub->do_remote_wakeup) { + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { + if (ehci->reset_done[port] != 0) { + spin_unlock_irq(&ehci->lock); + ehci_dbg(ehci, "suspend failed because " + "port %d is resuming\n", + port + 1); + return -EBUSY; + } + } + } + /* stop schedules, clean any completed work */ if (HC_IS_RUNNING(hcd->state)) { ehci_quiesce (ehci); @@ -138,6 +155,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) */ ehci->bus_suspended = 0; ehci->owned_ports = 0; + port = HCS_N_PORTS(ehci->hcs_params); while (port--) { u32 __iomem *reg = &ehci->regs->port_status [port]; u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 5cd0e48f67fb..99cd00fd3514 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -749,7 +749,20 @@ static int uhci_rh_suspend(struct usb_hcd *hcd) spin_lock_irq(&uhci->lock); if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) rc = -ESHUTDOWN; - else if (!uhci->dead) + else if (uhci->dead) + ; /* Dead controllers tell no tales */ + + /* Once the controller is stopped, port resumes that are already + * in progress won't complete. Hence if remote wakeup is enabled + * for the root hub and any ports are in the middle of a resume or + * remote wakeup, we must fail the suspend. + */ + else if (hcd->self.root_hub->do_remote_wakeup && + uhci->resuming_ports) { + dev_dbg(uhci_dev(uhci), "suspend failed because a port " + "is resuming\n"); + rc = -EBUSY; + } else suspend_rh(uhci, UHCI_RH_SUSPENDED); spin_unlock_irq(&uhci->lock); return rc; From a2a5b33aa3675f267259604218d0663b9778227f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 8 Jan 2010 11:18:38 -0500 Subject: [PATCH 384/670] USB: add missing delay during remote wakeup commit 49d0f078f494b9d81e820a13dd8093a9bfb0b6b1 upstream. This patch (as1330) fixes a bug in khbud's handling of remote wakeups. When a device sends a remote-wakeup request, the parent hub (or the host controller driver, for directly attached devices) begins the resume sequence and notifies khubd when the sequence finishes. At this point the port's SUSPEND feature is automatically turned off. However the device needs an additional 10-ms resume-recovery time (TRSMRCY in the USB spec). Khubd does not wait for this delay if the SUSPEND feature is off, and as a result some devices fail to behave properly following a remote wakeup. This patch adds the missing delay to the remote-wakeup path. It also extends the resume-signalling delay used by ehci-hcd and uhci-hcd from 20 ms (the value in the spec) to 25 ms (the value we use for non-remote-wakeup resumes). The extra time appears to help some devices. Signed-off-by: Alan Stern Cc: Rickard Bellini Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 3 +++ drivers/usb/host/ehci-hcd.c | 5 +++-- drivers/usb/host/uhci-hub.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8b0c2350d951..1a7d54b7745e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3286,6 +3286,9 @@ static void hub_events(void) USB_PORT_FEAT_C_SUSPEND); udev = hdev->children[i-1]; if (udev) { + /* TRSMRCY = 10 msec */ + msleep(10); + usb_lock_device(udev); ret = remote_wakeup(hdev-> children[i-1]); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f5f5601701c9..e18c6773809f 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -785,9 +785,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* start 20 msec resume signaling from this port, * and make khubd collect PORT_STAT_C_SUSPEND to - * stop that signaling. + * stop that signaling. Use 5 ms extra for safety, + * like usb_port_resume() does. */ - ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); + ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); mod_timer(&hcd->rh_timer, ehci->reset_done[i]); } diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 885b585360b9..8270055848ca 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -167,7 +167,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci) /* Port received a wakeup request */ set_bit(port, &uhci->resuming_ports); uhci->ports_timeout = jiffies + - msecs_to_jiffies(20); + msecs_to_jiffies(25); /* Make sure we see the port again * after the resuming period is over. */ From 111ab4bcb4a3c6d803f4cefde0c910de1fdbfc90 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 Jan 2010 10:33:19 -0800 Subject: [PATCH 385/670] USB: add speed values for USB 3.0 and wireless controllers commit b132b04e193908a94d95065d0628f8fb0159cc55 upstream. These controllers say "unknown" for their speed in sysfs, which obviously isn't correct. Reported-by: Kurt Garloff Cc: Sarah Sharp Cc: David Vrabel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 8752e5532369..fcdcad424b7a 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -115,6 +115,12 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf) case USB_SPEED_HIGH: speed = "480"; break; + case USB_SPEED_VARIABLE: + speed = "480"; + break; + case USB_SPEED_SUPER: + speed = "5000"; + break; default: speed = "unknown"; } From 1ff7b99e4983d9e93d25e98ba1ce303ad4e4909e Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 24 Dec 2009 11:34:16 +0300 Subject: [PATCH 386/670] ACPI: EC: Accelerate query execution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a62e8f1978f49e52f87a711ff6711b323d4b12ff upstream. Split EC query handling into acknowledge and execution phase. This allows much smaller pending query lattency and lowers chances of EC going "wild" and losing events. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14858 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown Cc: François Valenduc Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/ec.c | 122 +++++++++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 45 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7511029a1e0b..8aea2f4fe593 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -201,14 +201,13 @@ static void advance_transaction(struct acpi_ec *ec, u8 status) spin_unlock_irqrestore(&ec->curr_lock, flags); } -static void acpi_ec_gpe_query(void *ec_cxt); +static int acpi_ec_sync_query(struct acpi_ec *ec); -static int ec_check_sci(struct acpi_ec *ec, u8 state) +static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) { if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - return acpi_os_execute(OSL_EC_BURST_HANDLER, - acpi_ec_gpe_query, ec); + return acpi_ec_sync_query(ec); } return 0; } @@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, { unsigned long tmp; int ret = 0; - pr_debug(PREFIX "transaction start\n"); - /* disable GPE during transaction if storm is detected */ - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - acpi_disable_gpe(NULL, ec->gpe); - } if (EC_FLAGS_MSI) udelay(ACPI_EC_MSI_UDELAY); /* start transaction */ @@ -269,16 +263,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; spin_unlock_irqrestore(&ec->curr_lock, tmp); - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - /* check if we received SCI during transaction */ - ec_check_sci(ec, acpi_ec_read_status(ec)); - /* it is safe to enable GPE outside of transaction */ - acpi_enable_gpe(NULL, ec->gpe); - } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { - pr_info(PREFIX "GPE storm detected, " - "transactions will use polling mode\n"); - set_bit(EC_FLAGS_GPE_STORM, &ec->flags); - } return ret; } @@ -321,7 +305,24 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) status = -ETIME; goto end; } + pr_debug(PREFIX "transaction start\n"); + /* disable GPE during transaction if storm is detected */ + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + acpi_disable_gpe(NULL, ec->gpe); + } + status = acpi_ec_transaction_unlocked(ec, t); + + /* check if we received SCI during transaction */ + ec_check_sci_sync(ec, acpi_ec_read_status(ec)); + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + /* it is safe to enable GPE outside of transaction */ + acpi_enable_gpe(NULL, ec->gpe); + } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { + pr_info(PREFIX "GPE storm detected, " + "transactions will use polling mode\n"); + set_bit(EC_FLAGS_GPE_STORM, &ec->flags); + } end: if (ec->global_lock) acpi_release_global_lock(glk); @@ -443,7 +444,7 @@ int ec_transaction(u8 command, EXPORT_SYMBOL(ec_transaction); -static int acpi_ec_query(struct acpi_ec *ec, u8 * data) +static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) { int result; u8 d; @@ -452,20 +453,16 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) .wlen = 0, .rlen = 1}; if (!ec || !data) return -EINVAL; - /* * Query the EC to find out which _Qxx method we need to evaluate. * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - - result = acpi_ec_transaction(ec, &t); + result = acpi_ec_transaction_unlocked(ec, &t); if (result) return result; - if (!d) return -ENODATA; - *data = d; return 0; } @@ -509,43 +506,78 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); -static void acpi_ec_gpe_query(void *ec_cxt) +static void acpi_ec_run(void *cxt) { - struct acpi_ec *ec = ec_cxt; - u8 value = 0; - struct acpi_ec_query_handler *handler, copy; - - if (!ec || acpi_ec_query(ec, &value)) + struct acpi_ec_query_handler *handler = cxt; + if (!handler) return; - mutex_lock(&ec->lock); + pr_debug(PREFIX "start query execution\n"); + if (handler->func) + handler->func(handler->data); + else if (handler->handle) + acpi_evaluate_object(handler->handle, NULL, NULL, NULL); + pr_debug(PREFIX "stop query execution\n"); + kfree(handler); +} + +static int acpi_ec_sync_query(struct acpi_ec *ec) +{ + u8 value = 0; + int status; + struct acpi_ec_query_handler *handler, *copy; + if ((status = acpi_ec_query_unlocked(ec, &value))) + return status; list_for_each_entry(handler, &ec->list, node) { if (value == handler->query_bit) { /* have custom handler for this bit */ - memcpy(©, handler, sizeof(copy)); - mutex_unlock(&ec->lock); - if (copy.func) { - copy.func(copy.data); - } else if (copy.handle) { - acpi_evaluate_object(copy.handle, NULL, NULL, NULL); - } - return; + copy = kmalloc(sizeof(*handler), GFP_KERNEL); + if (!copy) + return -ENOMEM; + memcpy(copy, handler, sizeof(*copy)); + pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); + return acpi_os_execute(OSL_GPE_HANDLER, + acpi_ec_run, copy); } } + return 0; +} + +static void acpi_ec_gpe_query(void *ec_cxt) +{ + struct acpi_ec *ec = ec_cxt; + if (!ec) + return; + mutex_lock(&ec->lock); + acpi_ec_sync_query(ec); mutex_unlock(&ec->lock); } +static void acpi_ec_gpe_query(void *ec_cxt); + +static int ec_check_sci(struct acpi_ec *ec, u8 state) +{ + if (state & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { + pr_debug(PREFIX "push gpe query to the queue\n"); + return acpi_os_execute(OSL_NOTIFY_HANDLER, + acpi_ec_gpe_query, ec); + } + } + return 0; +} + static u32 acpi_ec_gpe_handler(void *data) { struct acpi_ec *ec = data; - u8 status; pr_debug(PREFIX "~~~> interrupt\n"); - status = acpi_ec_read_status(ec); - advance_transaction(ec, status); - if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) + advance_transaction(ec, acpi_ec_read_status(ec)); + if (ec_transaction_done(ec) && + (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { wake_up(&ec->wait); - ec_check_sci(ec, status); + ec_check_sci(ec, acpi_ec_read_status(ec)); + } return ACPI_INTERRUPT_HANDLED; } From 5f0ab2dfbf84454894568377e4dd6578ef3938f3 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 30 Dec 2009 15:53:10 +0300 Subject: [PATCH 387/670] ACPI: EC: Add wait for irq storm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 54070101f86ca9a6e9ba243c999d144721ec3db7 upstream. Merge of poll and irq modes accelerated EC transaction, so that keyboard starts to suffer again. Add msleep(1) into transaction path for the storm to allow keyboard controller to do its job. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14747 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown Cc: François Valenduc Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 8aea2f4fe593..f1670e0ef9bb 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -259,7 +259,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp); ret = ec_poll(ec); - pr_debug(PREFIX "transaction end\n"); spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; spin_unlock_irqrestore(&ec->curr_lock, tmp); @@ -316,6 +315,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) /* check if we received SCI during transaction */ ec_check_sci_sync(ec, acpi_ec_read_status(ec)); if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + msleep(1); /* it is safe to enable GPE outside of transaction */ acpi_enable_gpe(NULL, ec->gpe); } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { @@ -323,6 +323,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } + pr_debug(PREFIX "transaction end\n"); end: if (ec->global_lock) acpi_release_global_lock(glk); From 8cef765ff1eafb77cc40e8dad7a7a00190d9a6fc Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 26 Nov 2009 09:50:20 -0600 Subject: [PATCH 388/670] SCSI: enclosure: fix oops while iterating enclosure_status array commit cc9b2e9f6603190c009e5d2629ce8e3f99571346 upstream. Based on patch originally by Jeff Mahoney enclosure_status is expected to be a NULL terminated array of strings but isn't actually NULL terminated. When writing an invalid value to /sys/class/enclosure/.../.../status, it goes off the end of the array and Oopses. Fix by making the assumption true and adding NULL at the end. Reported-by: Artur Wojcik Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/misc/enclosure.c | 1 + include/linux/enclosure.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index e9eae4a78402..1eac626e710a 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c @@ -391,6 +391,7 @@ static const char *const enclosure_status [] = { [ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed", [ENCLOSURE_STATUS_UNKNOWN] = "unknown", [ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable", + [ENCLOSURE_STATUS_MAX] = NULL, }; static const char *const enclosure_type [] = { diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h index 90d1c2184112..9a33c5f7e126 100644 --- a/include/linux/enclosure.h +++ b/include/linux/enclosure.h @@ -42,6 +42,8 @@ enum enclosure_status { ENCLOSURE_STATUS_NOT_INSTALLED, ENCLOSURE_STATUS_UNKNOWN, ENCLOSURE_STATUS_UNAVAILABLE, + /* last element for counting purposes */ + ENCLOSURE_STATUS_MAX }; /* SFF-8485 activity light settings */ From 4fb77a3f85d3e4633e6ef3a8b319f882caf7c623 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 10:58:19 +0800 Subject: [PATCH 389/670] drm/i915: Read the response after issuing DDC bus switch command commit 6a304caf0bf9c429fc261f260b86cabf5bde2cbb upstream. For some SDVO cards based on conexant chip, we can't read the EDID if we don't read the response after issuing SDVO DDC bus switch command. From the SDVO spec once when another I2C transaction is finished after completing the I2C transaction of issuing the bus switch command, it will be switched back to the SDVO internal state again. So we can't initiate a new I2C transaction to read the response after issuing the DDC bus switch command. Instead we should issue DDC bus switch command and read the response in the same I2C transaction. https://bugs.freedesktop.org/show_bug.cgi?id=23842 https://bugs.freedesktop.org/show_bug.cgi?id=24458 https://bugs.freedesktop.org/show_bug.cgi?id=24522 https://bugs.freedesktop.org/show_bug.cgi?id=24282 Signed-off-by: Zhao Yakui Tested-by: Sebastien Caty Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_sdvo.c | 57 ++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 083bec2e50f9..d522a62c4dbb 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -472,14 +472,63 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) } /** - * Don't check status code from this as it switches the bus back to the - * SDVO chips which defeats the purpose of doing a bus switch in the first - * place. + * Try to read the response after issuie the DDC switch command. But it + * is noted that we must do the action of reading response and issuing DDC + * switch command in one I2C transaction. Otherwise when we try to start + * another I2C transaction after issuing the DDC bus switch, it will be + * switched to the internal SDVO register. */ static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output, u8 target) { - intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u8 out_buf[2], cmd_buf[2], ret_value[2], ret; + struct i2c_msg msgs[] = { + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = 0, + .len = 2, + .buf = out_buf, + }, + /* the following two are to read the response */ + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = 0, + .len = 1, + .buf = cmd_buf, + }, + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = I2C_M_RD, + .len = 1, + .buf = ret_value, + }, + }; + + intel_sdvo_debug_write(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, + &target, 1); + /* write the DDC switch command argument */ + intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0, target); + + out_buf[0] = SDVO_I2C_OPCODE; + out_buf[1] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; + cmd_buf[0] = SDVO_I2C_CMD_STATUS; + cmd_buf[1] = 0; + ret_value[0] = 0; + ret_value[1] = 0; + + ret = i2c_transfer(intel_output->i2c_bus, msgs, 3); + if (ret != 3) { + /* failure in I2C transfer */ + DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); + return; + } + if (ret_value[0] != SDVO_CMD_STATUS_SUCCESS) { + DRM_DEBUG_KMS("DDC switch command returns response %d\n", + ret_value[0]); + return; + } + return; } static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1) From ed0cd89c7333b17d50812201602f436b57ef1482 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 10:58:20 +0800 Subject: [PATCH 390/670] drm/i915: try another possible DDC bus for the SDVO device with multiple outputs commit 7c3f0a2726fed78e0e0afe3b6fc3c1f5b298e447 upstream. There exist multiple DDC buses for the SDVO cards with multiple outputs. When we can't get the EDID by using the select DDC bus, we can try the other possible DDC bus to see whether the EDID can be obtained. https://bugs.freedesktop.org/show_bug.cgi?id=23842 Signed-off-by: Zhao Yakui Tested-by: Sebastien Caty Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_sdvo.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index d522a62c4dbb..29e21d32f9ce 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1638,6 +1638,32 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); + /* This is only applied to SDVO cards with multiple outputs */ + if (edid == NULL && intel_sdvo_multifunc_encoder(intel_output)) { + uint8_t saved_ddc, temp_ddc; + saved_ddc = sdvo_priv->ddc_bus; + temp_ddc = sdvo_priv->ddc_bus >> 1; + /* + * Don't use the 1 as the argument of DDC bus switch to get + * the EDID. It is used for SDVO SPD ROM. + */ + while(temp_ddc > 1) { + sdvo_priv->ddc_bus = temp_ddc; + edid = drm_get_edid(&intel_output->base, + intel_output->ddc_bus); + if (edid) { + /* + * When we can get the EDID, maybe it is the + * correct DDC bus. Update it. + */ + sdvo_priv->ddc_bus = temp_ddc; + break; + } + temp_ddc >>= 1; + } + if (edid == NULL) + sdvo_priv->ddc_bus = saved_ddc; + } /* when there is no edid and no monitor is connected with VGA * port, try to use the CRT ddc to read the EDID for DVI-connector */ From fbe2992083cc1e865a91a4a101e97c2c35667acf Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Mon, 11 Jan 2010 03:21:49 -0500 Subject: [PATCH 391/670] block: bdev_stack_limits wrapper commit 17be8c245054b9c7786545af3ba3ca4e54cd4ad9 upstream. DM does not want to know about partition offsets. Add a partition-aware wrapper that DM can use when stacking block devices. Signed-off-by: Martin K. Petersen Acked-by: Mike Snitzer Reviewed-by: Alasdair G Kergon Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-settings.c | 22 ++++++++++++++++++++++ include/linux/blkdev.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/block/blk-settings.c b/block/blk-settings.c index 66d4aa8799b7..d5aa8865c644 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -559,6 +559,28 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, } EXPORT_SYMBOL(blk_stack_limits); +/** + * bdev_stack_limits - adjust queue limits for stacked drivers + * @t: the stacking driver limits (top device) + * @bdev: the component block_device (bottom) + * @start: first data sector within component device + * + * Description: + * Merges queue limits for a top device and a block_device. Returns + * 0 if alignment didn't change. Returns -1 if adding the bottom + * device caused misalignment. + */ +int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev, + sector_t start) +{ + struct request_queue *bq = bdev_get_queue(bdev); + + start += get_start_sect(bdev); + + return blk_stack_limits(t, &bq->limits, start << 9); +} +EXPORT_SYMBOL(bdev_stack_limits); + /** * disk_stack_limits - adjust queue limits for stacked drivers * @disk: MD/DM gendisk (top) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index adf99c617cd3..912b8ff3f272 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -942,6 +942,8 @@ extern void blk_queue_io_opt(struct request_queue *q, unsigned int opt); extern void blk_set_default_limits(struct queue_limits *lim); extern int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, sector_t offset); +extern int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev, + sector_t offset); extern void disk_stack_limits(struct gendisk *disk, struct block_device *bdev, sector_t offset); extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b); From e0f5cfa7c18b411634e73923841eccd3a4c0ce7f Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Mon, 11 Jan 2010 03:21:50 -0500 Subject: [PATCH 392/670] DM: Fix device mapper topology stacking commit b27d7f16d3c6c27345d4280a739809c1c2c4c0b5 upstream. Make DM use bdev_stack_limits() function so that partition offsets get taken into account when calculating alignment. Clarify stacking warnings. Also remove obsolete clearing of final alignment_offset and misalignment flag. Signed-off-by: Martin K. Petersen Signed-off-by: Mike Snitzer Cc: Alasdair G. Kergon Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-table.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 1a6cb3c7822e..e86912864e04 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -499,16 +499,15 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, return 0; } - if (blk_stack_limits(limits, &q->limits, start << 9) < 0) - DMWARN("%s: target device %s is misaligned: " + if (bdev_stack_limits(limits, bdev, start) < 0) + DMWARN("%s: adding target device %s caused an alignment inconsistency: " "physical_block_size=%u, logical_block_size=%u, " "alignment_offset=%u, start=%llu", dm_device_name(ti->table->md), bdevname(bdev, b), q->limits.physical_block_size, q->limits.logical_block_size, q->limits.alignment_offset, - (unsigned long long) start << 9); - + (unsigned long long) start << SECTOR_SHIFT); /* * Check if merge fn is supported. @@ -1025,9 +1024,9 @@ int dm_calculate_queue_limits(struct dm_table *table, * for the table. */ if (blk_stack_limits(limits, &ti_limits, 0) < 0) - DMWARN("%s: target device " + DMWARN("%s: adding target device " "(start sect %llu len %llu) " - "is misaligned", + "caused an alignment inconsistency", dm_device_name(table->md), (unsigned long long) ti->begin, (unsigned long long) ti->len); @@ -1078,15 +1077,6 @@ static void dm_table_set_integrity(struct dm_table *t) void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, struct queue_limits *limits) { - /* - * Each target device in the table has a data area that should normally - * be aligned such that the DM device's alignment_offset is 0. - * FIXME: Propagate alignment_offsets up the stack and warn of - * sub-optimal or inconsistent settings. - */ - limits->alignment_offset = 0; - limits->misaligned = 0; - /* * Copy table's limits to the DM device's request_queue */ From 538a6fdbcffffe7ddecf13f94129502524f771d5 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 26 Oct 2009 13:21:32 -0800 Subject: [PATCH 393/670] x86/PCI/PAT: return EINVAL for pci mmap WC request for !pat_enabled commit 2992e545ea006992ec9dc91c4fa996ce1e15f921 upstream. Thomas Schlichter reported: > X.org uses libpciaccess which tries to mmap with write combining enabled via > /sys/bus/pci/devices/*/resource0_wc. Currently, when PAT is not enabled, the > kernel does fall back to uncached mmap. Then libpciaccess thinks it succeeded > mapping with write combining enabled and does not set up suited MTRR entries. > ;-( Instead of silently mapping pci mmap region as UC minus in the case of !pat_enabled and wc request, we can return error. Eric Anholt mentioned that caller (like X) typically follows up with UC minus pci mmap request and if there is a free mtrr slot, caller will manage adding WC mtrr. Jesse Barnes says: > Older versions of libpciaccess will behave better if we do it that way > (iirc it only allocates an MTRR if the resource_wc file doesn't exist or > fails to get mapped). Reported-by: Thomas Schlichter Signed-off-by: Thomas Schlichter Signed-off-by: Suresh Siddha Acked-by: Eric Anholt Acked-by: Jesse Barnes Signed-off-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- arch/x86/pci/i386.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index b22d13b0c71d..a672f12afe34 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -282,6 +282,15 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, return -EINVAL; prot = pgprot_val(vma->vm_page_prot); + + /* + * Return error if pat is not enabled and write_combine is requested. + * Caller can followup with UC MINUS request and add a WC mtrr if there + * is a free mtrr slot. + */ + if (!pat_enabled && write_combine) + return -EINVAL; + if (pat_enabled && write_combine) prot |= _PAGE_CACHE_WC; else if (pat_enabled || boot_cpu_data.x86 > 3) From 3d0cc9a9a1cd4a043ffcd3251161d07a846a103c Mon Sep 17 00:00:00 2001 From: Ryan May Date: Wed, 6 Jan 2010 10:09:25 -0600 Subject: [PATCH 394/670] USB: fix usbstorage for 2770:915d delivers no FAT commit 10d2cdb6102669279bee2d9a00a22431b74583d5 upstream. Resolves kernel.org bug 14914. Remove entry for 2770:915d (usb digital camera with mass storage support) from unusual_devs.h. The fix triggered by the entry causes the file system on the camera to be completely inaccessible (no partition table, the device is not mountable). The patch works, but let me clarify a few things about it. All the patch does is remove the entry for this device from the drivers/usb/storage/unusual_devs.h, which is supposed to help with a problem with the device's reported size (I think). I'm pretty sure it was originally added for a reason, so I'm not sure removing it won't cause other problems to reappear. Also, I should note that this unusual_devs.h entry was present (and activating workarounds) in 2.6.29, but in that version everything works fine. Starting with 2.6.30, things no longer work. Signed-off-by: Ryan May Cc: Rohan Hart Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 64a0a2c27e12..c932f9053188 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1807,13 +1807,6 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_GO_SLOW ), -/* Reported by Rohan Hart */ -UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010, - "INTOVA", - "Pixtreme", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), - /* Reported by Frederic Marchal * Mio Moov 330 */ From f2fa92b29da64ead309293a048fe41776338a280 Mon Sep 17 00:00:00 2001 From: Yongseok Koh Date: Tue, 19 Jan 2010 17:33:49 +0900 Subject: [PATCH 395/670] vmalloc: remove BUG_ON due to racy counting of VM_LAZY_FREE commit 88f5004430babb836cfce886d5d54c82166f8ba4 upstream. In free_unmap_area_noflush(), va->flags is marked as VM_LAZY_FREE first, and then vmap_lazy_nr is increased atomically. But, in __purge_vmap_area_lazy(), while traversing of vmap_are_list, nr is counted by checking VM_LAZY_FREE is set to va->flags. After counting the variable nr, kernel reads vmap_lazy_nr atomically and checks a BUG_ON condition whether nr is greater than vmap_lazy_nr to prevent vmap_lazy_nr from being negative. The problem is that, if interrupted right after marking VM_LAZY_FREE, increment of vmap_lazy_nr can be delayed. Consequently, BUG_ON condition can be met because nr is counted more than vmap_lazy_nr. It is highly probable when vmalloc/vfree are called frequently. This scenario have been verified by adding delay between marking VM_LAZY_FREE and increasing vmap_lazy_nr in free_unmap_area_noflush(). Even the vmap_lazy_nr is for checking high watermark, it never be the strict watermark. Although the BUG_ON condition is to prevent vmap_lazy_nr from being negative, vmap_lazy_nr is signed variable. So, it could go down to negative value temporarily. Consequently, removing the BUG_ON condition is proper. A possible BUG_ON message is like the below. kernel BUG at mm/vmalloc.c:517! invalid opcode: 0000 [#1] SMP EIP: 0060:[] EFLAGS: 00010297 CPU: 3 EIP is at __purge_vmap_area_lazy+0x144/0x150 EAX: ee8a8818 EBX: c08e77d4 ECX: e7c7ae40 EDX: c08e77ec ESI: 000081fe EDI: e7c7ae60 EBP: e7c7ae64 ESP: e7c7ae3c DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Call Trace: [] free_unmap_vmap_area_noflush+0x69/0x70 [] remove_vm_area+0x22/0x70 [] __vunmap+0x45/0xe0 [] vmalloc+0x2c/0x30 Code: 8d 59 e0 eb 04 66 90 89 cb 89 d0 e8 87 fe ff ff 8b 43 20 89 da 8d 48 e0 8d 43 20 3b 04 24 75 e7 fe 05 a8 a5 a3 c0 e9 78 ff ff ff <0f> 0b eb fe 90 8d b4 26 00 00 00 00 56 89 c6 b8 ac a5 a3 c0 31 EIP: [] __purge_vmap_area_lazy+0x144/0x150 SS:ESP 0068:e7c7ae3c [ See also http://marc.info/?l=linux-kernel&m=126335856228090&w=2 ] Signed-off-by: Yongseok Koh Reviewed-by: Minchan Kim Cc: Nick Piggin Cc: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmalloc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 775872681d0c..a3a99d39188b 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -555,10 +555,8 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end, } rcu_read_unlock(); - if (nr) { - BUG_ON(nr > atomic_read(&vmap_lazy_nr)); + if (nr) atomic_sub(nr, &vmap_lazy_nr); - } if (nr || force_flush) flush_tlb_kernel_range(*start, *end); From 5a20267b12fec85520acc1e839ee61f2ea16413d Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 16 Jan 2010 12:53:19 -0800 Subject: [PATCH 396/670] perf timechart: Use tid not pid for COMM change commit 8f06d7e6e1bbfb32698d6d455583ab7460c090e2 upstream. A process that changes its comm field, does this on a per kernel task struct basis. The timechart tool used, incorrectly, the pid to track this, and should have used the tid instead... Signed-off-by: Arjan van de Ven Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: <20100116125319.34ac3edd@infradead.org> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- tools/perf/builtin-timechart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index e8a510d935e5..4101afeb4675 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -275,7 +275,7 @@ static u64 cpus_pstate_state[MAX_CPUS]; static int process_comm_event(event_t *event) { - pid_set_comm(event->comm.pid, event->comm.comm); + pid_set_comm(event->comm.tid, event->comm.comm); return 0; } static int From b0a93920c4117933657cb5572157ce502ef0fc57 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 17 Dec 2009 13:16:32 +0100 Subject: [PATCH 397/670] perf events: Dont report side-band events on each cpu for per-task-per-cpu events commit 5d27c23df09b702868d9a3bff86ec6abd22963ac upstream. Acme noticed that his FORK/MMAP numbers were inflated by about the same factor as his cpu-count. This led to the discovery of a few more sites that need to respect the event->cpu filter. Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <20091217121830.215333434@chello.nl> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/perf_event.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 6eee915a939e..6e9a31030783 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -1359,6 +1359,9 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx) if (event->state != PERF_EVENT_STATE_ACTIVE) continue; + if (event->cpu != -1 && event->cpu != smp_processor_id()) + continue; + hwc = &event->hw; interrupts = hwc->interrupts; @@ -3226,6 +3229,9 @@ static void perf_event_task_output(struct perf_event *event, static int perf_event_task_match(struct perf_event *event) { + if (event->cpu != -1 && event->cpu != smp_processor_id()) + return 0; + if (event->attr.comm || event->attr.mmap || event->attr.task) return 1; @@ -3255,13 +3261,13 @@ static void perf_event_task_event(struct perf_task_event *task_event) cpuctx = &get_cpu_var(perf_cpu_context); perf_event_task_ctx(&cpuctx->ctx, task_event); - put_cpu_var(perf_cpu_context); rcu_read_lock(); if (!ctx) ctx = rcu_dereference(task_event->task->perf_event_ctxp); if (ctx) perf_event_task_ctx(ctx, task_event); + put_cpu_var(perf_cpu_context); rcu_read_unlock(); } @@ -3338,6 +3344,9 @@ static void perf_event_comm_output(struct perf_event *event, static int perf_event_comm_match(struct perf_event *event) { + if (event->cpu != -1 && event->cpu != smp_processor_id()) + return 0; + if (event->attr.comm) return 1; @@ -3378,7 +3387,6 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) cpuctx = &get_cpu_var(perf_cpu_context); perf_event_comm_ctx(&cpuctx->ctx, comm_event); - put_cpu_var(perf_cpu_context); rcu_read_lock(); /* @@ -3388,6 +3396,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) ctx = rcu_dereference(current->perf_event_ctxp); if (ctx) perf_event_comm_ctx(ctx, comm_event); + put_cpu_var(perf_cpu_context); rcu_read_unlock(); } @@ -3462,6 +3471,9 @@ static void perf_event_mmap_output(struct perf_event *event, static int perf_event_mmap_match(struct perf_event *event, struct perf_mmap_event *mmap_event) { + if (event->cpu != -1 && event->cpu != smp_processor_id()) + return 0; + if (event->attr.mmap) return 1; @@ -3539,7 +3551,6 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) cpuctx = &get_cpu_var(perf_cpu_context); perf_event_mmap_ctx(&cpuctx->ctx, mmap_event); - put_cpu_var(perf_cpu_context); rcu_read_lock(); /* @@ -3549,6 +3560,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) ctx = rcu_dereference(current->perf_event_ctxp); if (ctx) perf_event_mmap_ctx(ctx, mmap_event); + put_cpu_var(perf_cpu_context); rcu_read_unlock(); kfree(buf); @@ -3811,6 +3823,9 @@ static int perf_swevent_match(struct perf_event *event, enum perf_type_id type, u32 event_id, struct pt_regs *regs) { + if (event->cpu != -1 && event->cpu != smp_processor_id()) + return 0; + if (!perf_swevent_is_counting(event)) return 0; From 9607f0688fe1db11f19ff43940fe4697845ec9da Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 18 Jan 2010 09:12:32 +0100 Subject: [PATCH 398/670] perf: Honour event state for aux stream data commit 22e190851f8709c48baf00ed9ce6144cdc54d025 upstream. Anton reported that perf record kept receiving events even after calling ioctl(PERF_EVENT_IOC_DISABLE). It turns out that FORK,COMM and MMAP events didn't respect the disabled state and kept flowing in. Reported-by: Anton Blanchard Signed-off-by: Peter Zijlstra Tested-by: Anton Blanchard LKML-Reference: <1263459187.4244.265.camel@laptop> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/perf_event.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 6e9a31030783..413d101ca8ee 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -3229,6 +3229,9 @@ static void perf_event_task_output(struct perf_event *event, static int perf_event_task_match(struct perf_event *event) { + if (event->state != PERF_EVENT_STATE_ACTIVE) + return 0; + if (event->cpu != -1 && event->cpu != smp_processor_id()) return 0; @@ -3344,6 +3347,9 @@ static void perf_event_comm_output(struct perf_event *event, static int perf_event_comm_match(struct perf_event *event) { + if (event->state != PERF_EVENT_STATE_ACTIVE) + return 0; + if (event->cpu != -1 && event->cpu != smp_processor_id()) return 0; @@ -3471,6 +3477,9 @@ static void perf_event_mmap_output(struct perf_event *event, static int perf_event_mmap_match(struct perf_event *event, struct perf_mmap_event *mmap_event) { + if (event->state != PERF_EVENT_STATE_ACTIVE) + return 0; + if (event->cpu != -1 && event->cpu != smp_processor_id()) return 0; From f584d374f2ab8cbc348ad23ecb82b419c0b8705c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 25 Jan 2010 10:50:10 -0800 Subject: [PATCH 399/670] Linux 2.6.32.6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4ebd3f16a716..20da31216f50 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = .5 +EXTRAVERSION = .6 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* From 08b8ff44354d5550d90eafd6cde87cb9f1d0ebcb Mon Sep 17 00:00:00 2001 From: Xiaotian Feng Date: Thu, 7 Jan 2010 11:22:44 +0800 Subject: [PATCH 400/670] clockevent: Don't remove broadcast device when cpu is dead commit ea9d8e3f45404d411c00ae67b45cc35c58265bb7 upstream. Marc reported that the BUG_ON in clockevents_notify() triggers on his system. This happens because the kernel tries to remove an active clock event device (used for broadcasting) from the device list. The handling of devices which can be used as per cpu device and as a global broadcast device is suboptimal. The simplest solution for now (and for stable) is to check whether the device is used as global broadcast device, but this needs to be revisited. [ tglx: restored the cpuweight check and massaged the changelog ] Reported-by: Marc Dionne Tested-by: Marc Dionne Signed-off-by: Xiaotian Feng LKML-Reference: <1262834564-13033-1-git-send-email-dfeng@redhat.com> Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/time/clockevents.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 9484be456d69..538589c97580 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -258,7 +258,8 @@ void clockevents_notify(unsigned long reason, void *arg) cpu = *((int *)arg); list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) { if (cpumask_test_cpu(cpu, dev->cpumask) && - cpumask_weight(dev->cpumask) == 1) { + cpumask_weight(dev->cpumask) == 1 && + !tick_is_broadcast_device(dev)) { BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); list_del(&dev->list); } From ce946bce1761f3c9f1f1ed8c15515d70d19047e9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 16 Oct 2009 18:19:01 -0400 Subject: [PATCH 401/670] clockevents: Add missing include to pacify sparse commit 8e1a928a2ed7e8d5cad97c8e985294b4caedd168 upstream. Include "tick-internal.h" in order to pick up the extern function prototype for clockevents_shutdown(). This quiets the following sparse build noise: warning: symbol 'clockevents_shutdown' was not declared. Should it be static? Signed-off-by: H Hartley Sweeten LKML-Reference: Reviewed-by: Yong Zhang Cc: johnstul@us.ibm.com Signed-off-by: Andrew Morton Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/time/clockevents.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 538589c97580..0d809ae02d60 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -20,6 +20,8 @@ #include #include +#include "tick-internal.h" + /* The registered clock event devices */ static LIST_HEAD(clockevent_devices); static LIST_HEAD(clockevents_released); From 9396c903006269d71ee54431b7a405cc8c318efd Mon Sep 17 00:00:00 2001 From: Xiaotian Feng Date: Thu, 10 Dec 2009 19:56:45 +0800 Subject: [PATCH 402/670] ACPI: don't cond_resched if irq is disabled commit c084ca704a3661bf77690a05bc6bd2c305d87c34 upstream. commit 8bd108d adds preemption point after each opcode parse, then a sleeping function called from invalid context bug was founded during suspend/resume stage. this was fixed in commit abe1dfa by don't cond_resched when irq_disabled. But recent commit 138d156 changes the behaviour to don't cond_resched when in_atomic. This makes the sleeping function called from invalid context bug happen again, which is reported in http://lkml.org/lkml/2009/12/1/371. This patch also fixes http://bugzilla.kernel.org/show_bug.cgi?id=14483 Reported-and-bisected-by: Larry Finger Reported-and-bisected-by: Justin P. Mattock Signed-off-by: Xiaotian Feng Acked-by: Alexey Starikovskiy Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- include/acpi/platform/aclinux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 9d7febde10a1..09469971472f 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -152,7 +152,7 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache) #include #define ACPI_PREEMPTION_POINT() \ do { \ - if (!in_atomic_preempt_off()) \ + if (!in_atomic_preempt_off() && !irqs_disabled()) \ cond_resched(); \ } while (0) From c97c73dead2d08a2e3eb2f84ad27b941deaef405 Mon Sep 17 00:00:00 2001 From: Neil Turton Date: Wed, 23 Dec 2009 13:47:13 +0000 Subject: [PATCH 403/670] sfc: Fix DMA mapping cleanup in case of an error in TSO commit a7ebd27a13757248863cd61e541af7fa9e7727ee upstream. We need buffer->len to remain valid to work out the correct address to be unmapped. We therefore need to clear buffer->len after the unmap operation. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/sfc/tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index 489c4de31447..d443ad7d8064 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -821,8 +821,6 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) tx_queue->efx->type->txd_ring_mask]; efx_tsoh_free(tx_queue, buffer); EFX_BUG_ON_PARANOID(buffer->skb); - buffer->len = 0; - buffer->continuation = true; if (buffer->unmap_len) { unmap_addr = (buffer->dma_addr + buffer->len - buffer->unmap_len); @@ -836,6 +834,8 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) PCI_DMA_TODEVICE); buffer->unmap_len = 0; } + buffer->len = 0; + buffer->continuation = true; } } From 879c8e8fe006114b844580b7ab5cd30073914ea6 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 16 Oct 2009 18:02:12 -0700 Subject: [PATCH 404/670] be2net: Add support for next generation of BladeEngine device. commit 12d7ea2c5a5c87834daf9fcd920aab80ff6248b1 upstream. Add new PCI ids to support next generation of BladeEngine device. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/benet/be.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 3b79a225628a..a84f1c55378d 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -35,20 +35,31 @@ #define DRV_VER "2.101.205" #define DRV_NAME "be2net" #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" +#define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" #define OC_NAME "Emulex OneConnect 10Gbps NIC" +#define OC_NAME1 "Emulex OneConnect 10Gbps NIC (be3)" #define DRV_DESC BE_NAME "Driver" #define BE_VENDOR_ID 0x19a2 #define BE_DEVICE_ID1 0x211 +#define BE_DEVICE_ID2 0x221 #define OC_DEVICE_ID1 0x700 #define OC_DEVICE_ID2 0x701 +#define OC_DEVICE_ID3 0x710 static inline char *nic_name(struct pci_dev *pdev) { - if (pdev->device == OC_DEVICE_ID1 || pdev->device == OC_DEVICE_ID2) + switch (pdev->device) { + case OC_DEVICE_ID1: + case OC_DEVICE_ID2: return OC_NAME; - else + case OC_DEVICE_ID3: + return OC_NAME1; + case BE_DEVICE_ID2: + return BE3_NAME; + default: return BE_NAME; + } } /* Number of bytes of an RX frame that are copied to skb->data */ From 90ee3cae9a305273b03231176be15e50f23c78ba Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Thu, 29 Oct 2009 01:11:06 -0700 Subject: [PATCH 405/670] be2net: Add the new PCI IDs to PCI_DEVICE_TABLE. commit 59fd5d87a4243a992f3a3e69f3627cf4c509608e upstream. This patch adds the PCI IDs for the next generation chip to the PCI_DEVICE_ID table. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/benet/be_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 876b357101fa..3749bb1e8ba5 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -31,8 +31,10 @@ MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, + { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, + { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) }, { 0 } }; MODULE_DEVICE_TABLE(pci, be_dev_ids); From 002464c610da98684edbde2aaf8d728c098f3486 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Wed, 23 Sep 2009 17:24:27 +0530 Subject: [PATCH 406/670] mpt2sas: New device SAS2208 support is added commit db27136a89d061bf9dceb28953a61a8ef862ca7f upstream. Added device ids range for { 0x80 - 87 } , modified mpi/mpi2_cnfg.h containing MPI2_MFGPAGE_DEVID_SAS2208_X. Signed-off-by: Kashyap Desai Signed-off-by: Eric Moore Signed-off-by: James Bottomley Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h | 8 ++++++++ drivers/scsi/mpt2sas/mpt2sas_scsih.c | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h index ab47c4679640..5af66dbe3239 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h @@ -348,6 +348,14 @@ typedef struct _MPI2_CONFIG_REPLY #define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077) #define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064) #define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065) +#define MPI2_MFGPAGE_DEVID_SAS2208_1 (0x0080) +#define MPI2_MFGPAGE_DEVID_SAS2208_2 (0x0081) +#define MPI2_MFGPAGE_DEVID_SAS2208_3 (0x0082) +#define MPI2_MFGPAGE_DEVID_SAS2208_4 (0x0083) +#define MPI2_MFGPAGE_DEVID_SAS2208_5 (0x0084) +#define MPI2_MFGPAGE_DEVID_SAS2208_6 (0x0085) +#define MPI2_MFGPAGE_DEVID_SAS2208_7 (0x0086) +#define MPI2_MFGPAGE_DEVID_SAS2208_8 (0x0087) /* Manufacturing Page 0 */ diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 86ab32d7ab15..1743640070ca 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -196,10 +196,28 @@ static struct pci_device_id scsih_pci_table[] = { PCI_ANY_ID, PCI_ANY_ID }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, PCI_ANY_ID, PCI_ANY_ID }, + /* Meteor ~ 2116 */ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, PCI_ANY_ID, PCI_ANY_ID }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, PCI_ANY_ID, PCI_ANY_ID }, + /* Thunderbolt ~ 2208 */ + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_7, + PCI_ANY_ID, PCI_ANY_ID }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_8, + PCI_ANY_ID, PCI_ANY_ID }, {0} /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, scsih_pci_table); From a98917c181b0f37a9ec47f15853d4742a1d38b3b Mon Sep 17 00:00:00 2001 From: Thomas Klute Date: Tue, 17 Nov 2009 11:58:18 +0100 Subject: [PATCH 407/670] ar9170: Add support for D-Link DWA 160 A2 commit 15295380f45aa0d35665f6e5596ac98c081d95b9 upstream. At least two revisions of the D-Link DWA 160 exist, called A1 and A2. A1 (USB-ID 07d1:3c10) is already listed in usb.c as D-Link DWA 160A. A2 (USB-ID 07d1:3a09) works if added to ar9170_usb_ids. I didn't do much testing until now, but I was able to connect to APs using WPA or WEP and transmit data. Summary: * Add model revision number to the comment for D-Link DWA 160 A1 (07d1:3c10) * Add support for D-Link DWA 160 A2 (07d1:3a09) Signed-off-by: Thomas Klute Signed-off-by: John W. Linville Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ar9170/usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e974e5829e1a..f141a4f711a1 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -68,8 +68,10 @@ static struct usb_device_id ar9170_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x1002) }, /* Cace Airpcap NX */ { USB_DEVICE(0xcace, 0x0300) }, - /* D-Link DWA 160A */ + /* D-Link DWA 160 A1 */ { USB_DEVICE(0x07d1, 0x3c10) }, + /* D-Link DWA 160 A2 */ + { USB_DEVICE(0x07d1, 0x3a09) }, /* Netgear WNDA3100 */ { USB_DEVICE(0x0846, 0x9010) }, /* Netgear WN111 v2 */ From c375e84ef885bcf95b2ac1964b4dad64238f3b89 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 23 Jan 2010 14:27:55 +0000 Subject: [PATCH 408/670] powerpc/fsl: Add PCI device ids for new QoirQ chips commit a3f62bd2b20c769ddc989b242ddd274179e19ee6 upstream by Kumar Gala . I have adjusted the patch context for 2.6.32. Signed-off-by: Kumar Gala Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/sysdev/fsl_pci.c | 14 ++++++++++++++ include/linux/pci_ids.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index ae88b1448018..e82749b954cd 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -392,8 +392,22 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header); +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header); #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 84cf1f3b7838..1b7f2a7939cb 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2290,6 +2290,20 @@ #define PCI_DEVICE_ID_MPC8536 0x0051 #define PCI_DEVICE_ID_P2020E 0x0070 #define PCI_DEVICE_ID_P2020 0x0071 +#define PCI_DEVICE_ID_P2010E 0x0078 +#define PCI_DEVICE_ID_P2010 0x0079 +#define PCI_DEVICE_ID_P1020E 0x0100 +#define PCI_DEVICE_ID_P1020 0x0101 +#define PCI_DEVICE_ID_P1011E 0x0108 +#define PCI_DEVICE_ID_P1011 0x0109 +#define PCI_DEVICE_ID_P1022E 0x0110 +#define PCI_DEVICE_ID_P1022 0x0111 +#define PCI_DEVICE_ID_P1013E 0x0118 +#define PCI_DEVICE_ID_P1013 0x0119 +#define PCI_DEVICE_ID_P4080E 0x0400 +#define PCI_DEVICE_ID_P4080 0x0401 +#define PCI_DEVICE_ID_P4040E 0x0408 +#define PCI_DEVICE_ID_P4040 0x0409 #define PCI_DEVICE_ID_MPC8641 0x7010 #define PCI_DEVICE_ID_MPC8641D 0x7011 #define PCI_DEVICE_ID_MPC8610 0x7018 From 30dc12eeba955e22fdb4e64c1af5f6373220555e Mon Sep 17 00:00:00 2001 From: Hemant Pedanekar Date: Wed, 2 Sep 2009 16:49:35 +0530 Subject: [PATCH 409/670] davinci: dm646x: Add support for 3.x silicon revision commit f63dd12da29f47c37bbc093abec098538e04357c upstream. DM6467 silicon revisions 3.x have variant field in JTAGID register as '1'. This path adds entry for the same in dm646x_ids to be able to boot on boards with 3.x revision chips. Also modifies name for 'variant=0' (revisions 1.0, 1.1). Signed-off-by: Hemant Pedanekar Signed-off-by: Kevin Hilman Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/dm646x.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 0976049c7b3b..36e4fb4fada8 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -789,7 +789,14 @@ static struct davinci_id dm646x_ids[] = { .part_no = 0xb770, .manufacturer = 0x017, .cpu_id = DAVINCI_CPU_ID_DM6467, - .name = "dm6467", + .name = "dm6467_rev1.x", + }, + { + .variant = 0x1, + .part_no = 0xb770, + .manufacturer = 0x017, + .cpu_id = DAVINCI_CPU_ID_DM6467, + .name = "dm6467_rev3.x", }, }; From 04daa51ee473ca536c225539699af0cdf7d165c6 Mon Sep 17 00:00:00 2001 From: Sebastian Kapfer Date: Fri, 15 Jan 2010 10:11:22 -0800 Subject: [PATCH 410/670] Input: ALPS - add interleaved protocol support (Dell E6x00 series) commit 1d9f26262aef6d63ff65eba0fd5f1583f342b69b upstream Properly handle version of the protocol where standard PS/2 packets from trackpoint are stuffed into middle (byte 3-6) of the standard ALPS packets when both the touchpad and trackpoint are used together. The patch is based on work done by Matthew Chapman and additional research done by David Kubicek and Erik Osterholm: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/296610 Many thanks to David Kubicek for his efforts in researching fine points of this new version of the protocol, especially interaction between pad and stick in these models. Cc: Andy Isaacson Signed-off-by: Sebastian Kapfer Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/mouse/alps.c | 254 +++++++++++++++++++++++++++++++++---- drivers/input/mouse/alps.h | 1 + 2 files changed, 229 insertions(+), 26 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index f36110689aae..fc8823bcf20c 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -5,6 +5,7 @@ * Copyright (c) 2003-2005 Peter Osterlund * Copyright (c) 2004 Dmitry Torokhov * Copyright (c) 2005 Vojtech Pavlik + * Copyright (c) 2009 Sebastian Kapfer * * ALPS detection, tap switching and status querying info is taken from * tpconfig utility (by C. Scott Ananian and Bruce Kall). @@ -35,6 +36,8 @@ #define ALPS_OLDPROTO 0x10 #define ALPS_PASS 0x20 #define ALPS_FW_BK_2 0x40 +#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with + 6-byte ALPS packet */ static const struct alps_model_info alps_model_data[] = { { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ @@ -55,7 +58,9 @@ static const struct alps_model_info alps_model_data[] = { { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ - { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ + /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ + { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */ }; @@ -66,20 +71,88 @@ static const struct alps_model_info alps_model_data[] = { */ /* - * ALPS abolute Mode - new format + * PS/2 packet format + * + * byte 0: 0 0 YSGN XSGN 1 M R L + * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 + * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 + * + * Note that the device never signals overflow condition. + * + * ALPS absolute Mode - new format * * byte 0: 1 ? ? ? 1 ? ? ? * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 - * byte 2: 0 x10 x9 x8 x7 ? fin ges + * byte 2: 0 x10 x9 x8 x7 ? fin ges * byte 3: 0 y9 y8 y7 1 M R L * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 * + * Dualpoint device -- interleaved packet format + * + * byte 0: 1 1 0 0 1 1 1 1 + * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 + * byte 2: 0 x10 x9 x8 x7 0 fin ges + * byte 3: 0 0 YSGN XSGN 1 1 1 1 + * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 + * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 + * byte 6: 0 y9 y8 y7 1 m r l + * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 + * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 + * + * CAPITALS = stick, miniscules = touchpad + * * ?'s can have different meanings on different models, * such as wheel rotation, extra buttons, stick buttons * on a dualpoint, etc. */ +static bool alps_is_valid_first_byte(const struct alps_model_info *model, + unsigned char data) +{ + return (data & model->mask0) == model->byte0; +} + +static void alps_report_buttons(struct psmouse *psmouse, + struct input_dev *dev1, struct input_dev *dev2, + int left, int right, int middle) +{ + struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; + + if (model->flags & ALPS_PS2_INTERLEAVED) { + struct input_dev *dev; + + /* + * If shared button has already been reported on the + * other device (dev2) then this event should be also + * sent through that device. + */ + dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_LEFT, left); + + dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_RIGHT, right); + + dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_MIDDLE, middle); + + /* + * Sync the _other_ device now, we'll do the first + * device later once we report the rest of the events. + */ + input_sync(dev2); + } else { + /* + * For devices with non-interleaved packets we know what + * device buttons belong to so we can simply report them. + */ + input_report_key(dev1, BTN_LEFT, left); + input_report_key(dev1, BTN_RIGHT, right); + input_report_key(dev1, BTN_MIDDLE, middle); + } +} + static void alps_process_packet(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; @@ -89,18 +162,6 @@ static void alps_process_packet(struct psmouse *psmouse) int x, y, z, ges, fin, left, right, middle; int back = 0, forward = 0; - if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ - input_report_key(dev2, BTN_LEFT, packet[0] & 1); - input_report_key(dev2, BTN_RIGHT, packet[0] & 2); - input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); - input_report_rel(dev2, REL_X, - packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); - input_report_rel(dev2, REL_Y, - packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); - input_sync(dev2); - return; - } - if (priv->i->flags & ALPS_OLDPROTO) { left = packet[2] & 0x10; right = packet[2] & 0x08; @@ -136,18 +197,13 @@ static void alps_process_packet(struct psmouse *psmouse) input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); - input_report_key(dev2, BTN_LEFT, left); - input_report_key(dev2, BTN_RIGHT, right); - input_report_key(dev2, BTN_MIDDLE, middle); + alps_report_buttons(psmouse, dev2, dev, left, right, middle); - input_sync(dev); input_sync(dev2); return; } - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_RIGHT, right); - input_report_key(dev, BTN_MIDDLE, middle); + alps_report_buttons(psmouse, dev, dev2, left, right, middle); /* Convert hardware tap to a reasonable Z value */ if (ges && !fin) z = 40; @@ -188,25 +244,168 @@ static void alps_process_packet(struct psmouse *psmouse) input_sync(dev); } -static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) +static void alps_report_bare_ps2_packet(struct psmouse *psmouse, + unsigned char packet[], + bool report_buttons) +{ + struct alps_data *priv = psmouse->private; + struct input_dev *dev2 = priv->dev2; + + if (report_buttons) + alps_report_buttons(psmouse, dev2, psmouse->dev, + packet[0] & 1, packet[0] & 2, packet[0] & 4); + + input_report_rel(dev2, REL_X, + packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); + input_report_rel(dev2, REL_Y, + packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); + + input_sync(dev2); +} + +static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; + if (psmouse->pktcnt < 6) + return PSMOUSE_GOOD_DATA; + + if (psmouse->pktcnt == 6) { + /* + * Start a timer to flush the packet if it ends up last + * 6-byte packet in the stream. Timer needs to fire + * psmouse core times out itself. 20 ms should be enough + * to decide if we are getting more data or not. + */ + mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20)); + return PSMOUSE_GOOD_DATA; + } + + del_timer(&priv->timer); + + if (psmouse->packet[6] & 0x80) { + + /* + * Highest bit is set - that means we either had + * complete ALPS packet and this is start of the + * next packet or we got garbage. + */ + + if (((psmouse->packet[3] | + psmouse->packet[4] | + psmouse->packet[5]) & 0x80) || + (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { + dbg("refusing packet %x %x %x %x " + "(suspected interleaved ps/2)\n", + psmouse->packet[3], psmouse->packet[4], + psmouse->packet[5], psmouse->packet[6]); + return PSMOUSE_BAD_DATA; + } + + alps_process_packet(psmouse); + + /* Continue with the next packet */ + psmouse->packet[0] = psmouse->packet[6]; + psmouse->pktcnt = 1; + + } else { + + /* + * High bit is 0 - that means that we indeed got a PS/2 + * packet in the middle of ALPS packet. + * + * There is also possibility that we got 6-byte ALPS + * packet followed by 3-byte packet from trackpoint. We + * can not distinguish between these 2 scenarios but + * becase the latter is unlikely to happen in course of + * normal operation (user would need to press all + * buttons on the pad and start moving trackpoint + * without touching the pad surface) we assume former. + * Even if we are wrong the wost thing that would happen + * the cursor would jump but we should not get protocol + * desynchronization. + */ + + alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], + false); + + /* + * Continue with the standard ALPS protocol handling, + * but make sure we won't process it as an interleaved + * packet again, which may happen if all buttons are + * pressed. To avoid this let's reset the 4th bit which + * is normally 1. + */ + psmouse->packet[3] = psmouse->packet[6] & 0xf7; + psmouse->pktcnt = 4; + } + + return PSMOUSE_GOOD_DATA; +} + +static void alps_flush_packet(unsigned long data) +{ + struct psmouse *psmouse = (struct psmouse *)data; + + serio_pause_rx(psmouse->ps2dev.serio); + + if (psmouse->pktcnt == 6) { + + /* + * We did not any more data in reasonable amount of time. + * Validate the last 3 bytes and process as a standard + * ALPS packet. + */ + if ((psmouse->packet[3] | + psmouse->packet[4] | + psmouse->packet[5]) & 0x80) { + dbg("refusing packet %x %x %x " + "(suspected interleaved ps/2)\n", + psmouse->packet[3], psmouse->packet[4], + psmouse->packet[5]); + } else { + alps_process_packet(psmouse); + } + psmouse->pktcnt = 0; + } + + serio_continue_rx(psmouse->ps2dev.serio); +} + +static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) +{ + struct alps_data *priv = psmouse->private; + const struct alps_model_info *model = priv->i; + if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ if (psmouse->pktcnt == 3) { - alps_process_packet(psmouse); + alps_report_bare_ps2_packet(psmouse, psmouse->packet, + true); return PSMOUSE_FULL_PACKET; } return PSMOUSE_GOOD_DATA; } - if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0) + /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ + + if ((model->flags & ALPS_PS2_INTERLEAVED) && + psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { + return alps_handle_interleaved_ps2(psmouse); + } + + if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { + dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", + psmouse->packet[0], model->mask0, model->byte0); return PSMOUSE_BAD_DATA; + } /* Bytes 2 - 6 should have 0 in the highest bit */ if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { + dbg("refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); return PSMOUSE_BAD_DATA; + } if (psmouse->pktcnt == 6) { alps_process_packet(psmouse); @@ -445,6 +644,7 @@ static void alps_disconnect(struct psmouse *psmouse) struct alps_data *priv = psmouse->private; psmouse_reset(psmouse); + del_timer_sync(&priv->timer); input_unregister_device(priv->dev2); kfree(priv); } @@ -461,6 +661,8 @@ int alps_init(struct psmouse *psmouse) goto init_fail; priv->dev2 = dev2; + setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); + psmouse->private = priv; if (alps_hw_init(psmouse, &version)) diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index bc87936fee1a..904ed8b3c8be 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h @@ -23,6 +23,7 @@ struct alps_data { char phys[32]; /* Phys */ const struct alps_model_info *i;/* Info */ int prev_fin; /* Finger bit from previous packet */ + struct timer_list timer; }; #ifdef CONFIG_MOUSE_PS2_ALPS From da30443952067e4abb1f3e50b226b8669c62dc02 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 30 Oct 2009 12:48:32 +0100 Subject: [PATCH 411/670] Driver-Core: devtmpfs - set root directory mode to 0755 commit 03d673e6af6490371aaf64dfe1f84c658c48b71d upstream. Signed-off-by: Kay Sievers Cc: Mark Rosenstand Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index a1cb5afe6801..318570bcecde 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -361,7 +361,7 @@ int __init devtmpfs_init(void) return err; } - mnt = kern_mount(&dev_fs_type); + mnt = kern_mount_data(&dev_fs_type, "mode=0755"); if (IS_ERR(mnt)) { err = PTR_ERR(mnt); printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); From 1b715f18181d2156290bfb8f116e233ffc8fb362 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 18 Jan 2010 14:36:12 +0100 Subject: [PATCH 412/670] driver-core: fix devtmpfs crash on s390 commit f776c5ec4690b21b3668ad5956774a22c86f541a upstream. On Mon, Jan 18, 2010 at 05:26:20PM +0530, Sachin Sant wrote: > Hello Heiko, > > Today while trying to boot next-20100118 i came across > the following Oops : > > Brought up 4 CPUs > Unable to handle kernel pointer dereference at virtual kernel address 0000000000 > 543000 > Oops: 0004 #1 SMP > Modules linked in: > CPU: 0 Not tainted 2.6.33-rc4-autotest-next-20100118-5-default #1 > Process swapper (pid: 1, task: 00000000fd792038, ksp: 00000000fd797a30) > Krnl PSW : 0704200180000000 00000000001eb0b8 (shmem_parse_options+0xc0/0x328) > R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:2 PM:0 EA:3 > Krnl GPRS: 000000000054388a 000000000000003d 0000000000543836 000000000000003d > 0000000000000000 0000000000483f28 0000000000536112 00000000fd797d00 > 00000000fd4ba100 0000000000000100 0000000000483978 0000000000543832 > 0000000000000000 0000000000465958 00000000001eb0b0 00000000fd797c58 > Krnl Code: 00000000001eb0aa: c0e5000994f1 brasl %r14,31da8c > 00000000001eb0b0: b9020022 ltgr %r2,%r2 > 00000000001eb0b4: a784010b brc 8,1eb2ca > >00000000001eb0b8: 92002000 mvi 0(%r2),0 > 00000000001eb0bc: a7080000 lhi %r0,0 > 00000000001eb0c0: 41902001 la %r9,1(%r2) > 00000000001eb0c4: b9040016 lgr %r1,%r6 > 00000000001eb0c8: b904002b lgr %r2,%r11 > Call Trace: > (<00000000fd797c50> 0xfd797c50) > <00000000001eb5da> shmem_fill_super+0x13a/0x25c > <0000000000228cfa> get_sb_single+0xbe/0xdc > <000000000034ffc0> dev_get_sb+0x2c/0x38 > <000000000066c602> devtmpfs_init+0x46/0xc0 > <000000000066c53e> driver_init+0x22/0x60 > <000000000064d40a> kernel_init+0x24e/0x3d0 > <000000000010a7ea> kernel_thread_starter+0x6/0xc > <000000000010a7e4> kernel_thread_starter+0x0/0xc > > I never tried to boot a kernel with DEVTMPFS enabled on a s390 box. > So am wondering if this is supported or not ? If you think this > is supported i will send a mail to community on this. There is nothing arch specific to devtmpfs. This part crashes because the kernel tries to modify the data read-only section which is write protected on s390. Signed-off-by: Heiko Carstens Acked-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 318570bcecde..33faaa22a19d 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -353,6 +353,7 @@ int __init devtmpfs_init(void) { int err; struct vfsmount *mnt; + char options[] = "mode=0755"; err = register_filesystem(&dev_fs_type); if (err) { @@ -361,7 +362,7 @@ int __init devtmpfs_init(void) return err; } - mnt = kern_mount_data(&dev_fs_type, "mode=0755"); + mnt = kern_mount_data(&dev_fs_type, options); if (IS_ERR(mnt)) { err = PTR_ERR(mnt); printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); From 4bc685e6b0d123ceca7bccb05ebce2e5e6a5ba21 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 18 Dec 2009 21:18:15 +0100 Subject: [PATCH 413/670] vfs: get_sb_single() - do not pass options twice commit 9329d1beaeed1a94f030c784dcec5ff973f402c4 upstream. Filesystem code usually destroys the option buffer while parsing it. This leads to errors when the same buffer is passed twice. In case we fill a new superblock do not call remount. This is needed to quite a warning that the debugfs code causes every boot. Cc: Miklos Szeredi Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- fs/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/super.c b/fs/super.c index 19eb70b374bc..aff046b0fe78 100644 --- a/fs/super.c +++ b/fs/super.c @@ -901,8 +901,9 @@ int get_sb_single(struct file_system_type *fs_type, return error; } s->s_flags |= MS_ACTIVE; + } else { + do_remount_sb(s, flags, data, 0); } - do_remount_sb(s, flags, data, 0); simple_set_mnt(mnt, s); return 0; } From ff23399022735e9e629919843a236ba0b9897a81 Mon Sep 17 00:00:00 2001 From: Stefan Ringel Date: Mon, 14 Dec 2009 11:27:11 +0100 Subject: [PATCH 414/670] ALSA: hda - Add PCI IDs for Nvidia G2xx-series commit 6dd7dc767e35cfbb38f8c63a50b1c27acad25920 upstream. Signed-off-by: Stefan Ringel Signed-off-by: Takashi Iwai Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_intel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7e4ee4e89737..03784da6cf5d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2694,6 +2694,9 @@ static struct pci_device_id azx_ids[] = { { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA }, + { PCI_DEVICE(0x10de, 0x0be2), .driver_data = AZX_DRIVER_NVIDIA }, + { PCI_DEVICE(0x10de, 0x0be3), .driver_data = AZX_DRIVER_NVIDIA }, + { PCI_DEVICE(0x10de, 0x0be4), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA }, From 4d3c6786cace38eb34ee6f00fc59ef8b848ebd8c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 30 Nov 2009 18:22:10 -0300 Subject: [PATCH 415/670] V4L/DVB (13569): smsusb: add autodetection support for five additional Hauppauge USB IDs commit 20d15a200d34cfb7141fb4558895d7d5233db84b upstream. Add support for five new Hauppauge Device USB IDs: 2040:b980 2040:b990 2040:c010 2040:c080 2040:c090 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/siano/smsusb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 8f88a586b0dd..6b03dbf3635e 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -533,8 +533,18 @@ struct usb_device_id smsusb_id_table[] = { .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0xb910), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xb980), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xb990), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0xc000), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xc010), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xc080), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xc090), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { } /* Terminating entry */ }; From 5bcaffb93f43a5e1c8906e87524f813140795ced Mon Sep 17 00:00:00 2001 From: Cliff Brake Date: Tue, 1 Dec 2009 09:53:43 -0500 Subject: [PATCH 416/670] USB: mos7840: add device IDs for B&B electronics devices commit acf509ae28301d78b022c534c26b1e4765c18f2b upstream. Reviewed-by: John Pilles Signed-off-by: Cliff Brake Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index f11abf52be7d..485fa9c5b107 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -121,8 +121,14 @@ * moschip_id_table_combined */ #define USB_VENDOR_ID_BANDB 0x0856 -#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 +#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 +#define BANDB_DEVICE_ID_USO9ML2_4 0xAC24 +#define BANDB_DEVICE_ID_US9ML2_2 0xAC29 +#define BANDB_DEVICE_ID_US9ML2_4 0xAC30 +#define BANDB_DEVICE_ID_USPTL4_2 0xAC31 +#define BANDB_DEVICE_ID_USPTL4_4 0xAC32 #define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 +#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 /* This driver also supports * ATEN UC2324 device using Moschip MCS7840 @@ -177,8 +183,14 @@ static struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, - {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ @@ -187,8 +199,14 @@ static struct usb_device_id moschip_port_id_table[] = { static __devinitdata struct usb_device_id moschip_id_table_combined[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, - {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ From 8429570c6a0a53b0b1eee1410e9b54d1b224db8d Mon Sep 17 00:00:00 2001 From: Cliff Brake Date: Tue, 1 Dec 2009 09:53:42 -0500 Subject: [PATCH 417/670] USB: ftdi_sio: add USB device ID's for B&B Electronics line commit a8cbd90a0410096e152f68a4e114a8b5c7abb49b upstream. Reviewed-by: John Pilles Signed-off-by: Cliff Brake Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 14 ++++++++++++++ drivers/usb/serial/ftdi_sio.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ebcc6d0e2e91..13a1b39f1590 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -598,6 +598,20 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOPTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USPTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_2_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR2_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USB9F_2W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USB9F_4W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_232USB9M_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USBTB_2W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_485USBTB_4W_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_TTL5USB9M_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_TTL3USB9M_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_ZZ_PROG1_USB_PID) }, { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 6f31e0d71898..4586a24fafb0 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -662,6 +662,20 @@ #define BANDB_USOTL4_PID 0xAC01 /* USOTL4 Isolated RS-485 Converter */ #define BANDB_USTL4_PID 0xAC02 /* USTL4 RS-485 Converter */ #define BANDB_USO9ML2_PID 0xAC03 /* USO9ML2 Isolated RS-232 Converter */ +#define BANDB_USOPTL4_PID 0xAC11 +#define BANDB_USPTL4_PID 0xAC12 +#define BANDB_USO9ML2DR_2_PID 0xAC16 +#define BANDB_USO9ML2DR_PID 0xAC17 +#define BANDB_USOPTL4DR2_PID 0xAC18 /* USOPTL4R-2 2-port Isolated RS-232 Converter */ +#define BANDB_USOPTL4DR_PID 0xAC19 +#define BANDB_485USB9F_2W_PID 0xAC25 +#define BANDB_485USB9F_4W_PID 0xAC26 +#define BANDB_232USB9M_PID 0xAC27 +#define BANDB_485USBTB_2W_PID 0xAC33 +#define BANDB_485USBTB_4W_PID 0xAC34 +#define BANDB_TTL5USB9M_PID 0xAC49 +#define BANDB_TTL3USB9M_PID 0xAC50 +#define BANDB_ZZ_PROG1_USB_PID 0xBA02 /* * RM Michaelides CANview USB (http://www.rmcan.com) From 96ef353c45ee9ef98c28c72c1c240c9825c75392 Mon Sep 17 00:00:00 2001 From: Danny Wood Date: Sun, 20 Sep 2009 12:14:21 -0300 Subject: [PATCH 418/670] V4L/DVB (13168): Add support for Asus Europa Hybrid DVB-T card (SAA7134 SubVendor ID: 0x1043 Device ID: 0x4847) commit e3c6e1aaa5db7822524f5b1355960fd732910068 upstream. Adds the device IDs and driver linking to allow the Asus Europa DVB-T card to operate with these drivers. The device has a SAA7134 chipset with a TD1316 Hybrid Tuner. All inputs work on the card including switching between DVB-T and Analogue TV, there is also no IR with this card. [mchehab@redhat.com: CodingStyle fixes] Signed-off-by: Danny Wood Cc: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 31 +++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 1 + drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 34 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 2620d60341ee..94e255a76f79 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -172,3 +172,4 @@ 171 -> Beholder BeholdTV X7 [5ace:7595] 172 -> RoverMedia TV Link Pro FM [19d1:0138] 173 -> Zolid Hybrid TV Tuner PCI [1131:2004] +174 -> Asus Europa Hybrid OEM [1043:4847] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 09013229d4aa..6781a07debab 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5279,6 +5279,30 @@ struct saa7134_board saa7134_boards[] = { .amux = TV, }, }, + [SAA7134_BOARD_ASUS_EUROPA_HYBRID] = { + .name = "Asus Europa Hybrid OEM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TD1316, + .radio_type = UNSET, + .tuner_addr = 0x61, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, + .mpeg = SAA7134_MPEG_DVB, + .inputs = { { + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 4, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + }, }; @@ -6417,6 +6441,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = PCI_VENDOR_ID_PHILIPS, .subdevice = 0x2004, .driver_data = SAA7134_BOARD_ZOLID_HYBRID_PCI, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1043, + .subdevice = 0x4847, + .driver_data = SAA7134_BOARD_ASUS_EUROPA_HYBRID, }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -7079,6 +7109,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) /* break intentionally omitted */ case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: + case SAA7134_BOARD_ASUS_EUROPA_HYBRID: { /* The Philips EUROPA based hybrid boards have the tuner diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index a26e997a9ce6..b8a805c69901 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1116,6 +1116,7 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_PHILIPS_EUROPA: case SAA7134_BOARD_VIDEOMATE_DVBT_300: + case SAA7134_BOARD_ASUS_EUROPA_HYBRID: fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_europa_config, &dev->i2c_adap); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f8697d46ff5f..94e1a3be3317 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -297,6 +297,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_X7 171 #define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172 #define SAA7134_BOARD_ZOLID_HYBRID_PCI 173 +#define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 From b68f61930c00abfe5e7dd6535c6e23547c77bab4 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Wed, 11 Nov 2009 02:24:01 +0100 Subject: [PATCH 419/670] iTCO_wdt: Add support for Intel Ibex Peak commit 79e8941dda254505bb8af37b3a009165dfb7e98a upstream. Add the Intel Ibex Peak (PCH) Device IDs to iTCO_wdt.c. Signed-off-by: Seth Heasley Signed-off-by: Wim Van Sebroeck Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/iTCO_wdt.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 6a51edde6ea7..4bd3877ad895 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -54,7 +54,9 @@ * 82801JIB (ICH10) : document number 319973-002, 319974-002, * 82801JIR (ICH10R) : document number 319973-002, 319974-002, * 82801JD (ICH10D) : document number 319973-002, 319974-002, - * 82801JDO (ICH10DO) : document number 319973-002, 319974-002 + * 82801JDO (ICH10DO) : document number 319973-002, 319974-002, + * 5 Series (PCH) : document number 322169-001, 322170-001, + * 3400 Series (PCH) : document number 322169-001, 322170-001 */ /* @@ -122,6 +124,9 @@ enum iTCO_chipsets { TCO_ICH10R, /* ICH10R */ TCO_ICH10D, /* ICH10D */ TCO_ICH10DO, /* ICH10DO */ + TCO_PCH, /* PCH Desktop Full Featured */ + TCO_PCHM, /* PCH Mobile Full Featured */ + TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ }; static struct { @@ -162,6 +167,9 @@ static struct { {"ICH10R", 2}, {"ICH10D", 2}, {"ICH10DO", 2}, + {"PCH Desktop Full Featured", 2}, + {"PCH Mobile Full Featured", 2}, + {"PCH Mobile SFF Full Featured", 2}, {NULL, 0} }; @@ -230,6 +238,9 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x3a16, TCO_ICH10R)}, { ITCO_PCI_DEVICE(0x3a1a, TCO_ICH10D)}, { ITCO_PCI_DEVICE(0x3a14, TCO_ICH10DO)}, + { ITCO_PCI_DEVICE(0x3b00, TCO_PCH)}, + { ITCO_PCI_DEVICE(0x3b01, TCO_PCHM)}, + { ITCO_PCI_DEVICE(0x3b0d, TCO_PCHMSFF)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); From f7b17144048d7b1feda0dd1f255629bb187ac30f Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Sun, 6 Dec 2009 23:16:58 +0000 Subject: [PATCH 420/670] atl1c:use common_task instead of reset_task and link_chg_task commit cb19054697e92a793f336380fd72c588521178ff upstream. use common_task instead of reset_task and link_chg_task, so it fix "call cancel_work_sync from the work itself". Signed-off-by: Jie Yang Signed-off-by: David S. Miller Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/atl1c/atl1c.h | 6 ++- drivers/net/atl1c/atl1c_main.c | 72 ++++++++++++++++------------------ 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index 2a1120ad2e74..790e55bf3fa2 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h @@ -534,6 +534,9 @@ struct atl1c_adapter { #define __AT_TESTING 0x0001 #define __AT_RESETTING 0x0002 #define __AT_DOWN 0x0003 + u8 work_event; +#define ATL1C_WORK_EVENT_RESET 0x01 +#define ATL1C_WORK_EVENT_LINK_CHANGE 0x02 u32 msg_enable; bool have_msi; @@ -545,8 +548,7 @@ struct atl1c_adapter { spinlock_t tx_lock; atomic_t irq_sem; - struct work_struct reset_task; - struct work_struct link_chg_task; + struct work_struct common_task; struct timer_list watchdog_timer; struct timer_list phy_config_timer; diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 1372e9a99f5b..be00ee973546 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -198,27 +198,12 @@ static void atl1c_phy_config(unsigned long data) void atl1c_reinit_locked(struct atl1c_adapter *adapter) { - WARN_ON(in_interrupt()); atl1c_down(adapter); atl1c_up(adapter); clear_bit(__AT_RESETTING, &adapter->flags); } -static void atl1c_reset_task(struct work_struct *work) -{ - struct atl1c_adapter *adapter; - struct net_device *netdev; - - adapter = container_of(work, struct atl1c_adapter, reset_task); - netdev = adapter->netdev; - - netif_device_detach(netdev); - atl1c_down(adapter); - atl1c_up(adapter); - netif_device_attach(netdev); -} - static void atl1c_check_link_status(struct atl1c_adapter *adapter) { struct atl1c_hw *hw = &adapter->hw; @@ -275,18 +260,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) } } -/* - * atl1c_link_chg_task - deal with link change event Out of interrupt context - * @netdev: network interface device structure - */ -static void atl1c_link_chg_task(struct work_struct *work) -{ - struct atl1c_adapter *adapter; - - adapter = container_of(work, struct atl1c_adapter, link_chg_task); - atl1c_check_link_status(adapter); -} - static void atl1c_link_chg_event(struct atl1c_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -311,19 +284,39 @@ static void atl1c_link_chg_event(struct atl1c_adapter *adapter) adapter->link_speed = SPEED_0; } } - schedule_work(&adapter->link_chg_task); + + adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE; + schedule_work(&adapter->common_task); } +static void atl1c_common_task(struct work_struct *work) +{ + struct atl1c_adapter *adapter; + struct net_device *netdev; + + adapter = container_of(work, struct atl1c_adapter, common_task); + netdev = adapter->netdev; + + if (adapter->work_event & ATL1C_WORK_EVENT_RESET) { + netif_device_detach(netdev); + atl1c_down(adapter); + atl1c_up(adapter); + netif_device_attach(netdev); + return; + } + + if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) + atl1c_check_link_status(adapter); + + return; +} + + static void atl1c_del_timer(struct atl1c_adapter *adapter) { del_timer_sync(&adapter->phy_config_timer); } -static void atl1c_cancel_work(struct atl1c_adapter *adapter) -{ - cancel_work_sync(&adapter->reset_task); - cancel_work_sync(&adapter->link_chg_task); -} /* * atl1c_tx_timeout - Respond to a Tx Hang @@ -334,7 +327,8 @@ static void atl1c_tx_timeout(struct net_device *netdev) struct atl1c_adapter *adapter = netdev_priv(netdev); /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); + adapter->work_event |= ATL1C_WORK_EVENT_RESET; + schedule_work(&adapter->common_task); } /* @@ -1536,7 +1530,8 @@ static irqreturn_t atl1c_intr(int irq, void *data) /* reset MAC */ hw->intr_mask &= ~ISR_ERROR; AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); - schedule_work(&adapter->reset_task); + adapter->work_event |= ATL1C_WORK_EVENT_RESET; + schedule_work(&adapter->common_task); break; } @@ -2200,8 +2195,7 @@ void atl1c_down(struct atl1c_adapter *adapter) struct net_device *netdev = adapter->netdev; atl1c_del_timer(adapter); - atl1c_cancel_work(adapter); - + adapter->work_event = 0; /* clear all event */ /* signal that we're down so the interrupt handler does not * reschedule our watchdog timer */ set_bit(__AT_DOWN, &adapter->flags); @@ -2601,8 +2595,8 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]); atl1c_hw_set_mac_addr(&adapter->hw); - INIT_WORK(&adapter->reset_task, atl1c_reset_task); - INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task); + INIT_WORK(&adapter->common_task, atl1c_common_task); + adapter->work_event = 0; err = register_netdev(netdev); if (err) { dev_err(&pdev->dev, "register netdevice failed\n"); From 857ffb889a5d4760b14e5e46bbe6308fd02d0526 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Tue, 1 Dec 2009 17:18:34 +0000 Subject: [PATCH 421/670] atl1e:disable NETIF_F_TSO6 for hardware limit commit 7c7afb083675b3d4d012a2aacec3a958ba484ab0 upstream. For hardware limit to support TSOV6, just disable this feature Signed-off-by: Jie Yang Signed-off-by: David S. Miller Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/net/atl1e/atl1e_main.c | 36 ---------------------------------- 1 file changed, 36 deletions(-) diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 955da733c2ad..1b5facfcdc08 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -1666,41 +1666,6 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter, } return 0; } - - if (offload_type & SKB_GSO_TCPV6) { - real_len = (((unsigned char *)ipv6_hdr(skb) - skb->data) - + ntohs(ipv6_hdr(skb)->payload_len)); - if (real_len < skb->len) - pskb_trim(skb, real_len); - - /* check payload == 0 byte ? */ - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); - if (unlikely(skb->len == hdr_len)) { - /* only xsum need */ - dev_warn(&pdev->dev, - "IPV6 tso with zero data??\n"); - goto check_sum; - } else { - tcp_hdr(skb)->check = ~csum_ipv6_magic( - &ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - tpd->word3 |= 1 << TPD_IP_VERSION_SHIFT; - hdr_len >>= 1; - tpd->word3 |= (hdr_len & TPD_V6_IPHLLO_MASK) << - TPD_V6_IPHLLO_SHIFT; - tpd->word3 |= ((hdr_len >> 3) & - TPD_V6_IPHLHI_MASK) << - TPD_V6_IPHLHI_SHIFT; - tpd->word3 |= (tcp_hdrlen(skb) >> 2 & - TPD_TCPHDRLEN_MASK) << - TPD_TCPHDRLEN_SHIFT; - tpd->word3 |= ((skb_shinfo(skb)->gso_size) & - TPD_MSS_MASK) << TPD_MSS_SHIFT; - tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT; - } - } - return 0; } check_sum: @@ -2289,7 +2254,6 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; netdev->features |= NETIF_F_LLTX; netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; return 0; } From 35f42c92098c70fc576e3baa8955db9fb2ba9cb5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 3 Dec 2009 19:50:35 -0300 Subject: [PATCH 422/670] V4L/DVB (13680a): DocBook/media: copy images after building HTML commit 49b14650ba5bf80234cb1984fd8396aff03430ce upstream. The rule for %.html removes the output directory, so there is no point in copying images before building HTML. Documentation/DocBook/Makefile | 10 +++++----- Signed-off-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- Documentation/DocBook/Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index ab8300f67182..22bbf7e39018 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -32,7 +32,7 @@ PS_METHOD = $(prefer-db2x) ### # The targets that may be used. -PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs media +PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs BOOKS := $(addprefix $(obj)/,$(DOCBOOKS)) xmldocs: $(BOOKS) @@ -45,15 +45,15 @@ PDF := $(patsubst %.xml, %.pdf, $(BOOKS)) pdfdocs: $(PDF) HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS))) -htmldocs: media $(HTML) +htmldocs: $(HTML) $(call build_main_index) + $(call build_images) MAN := $(patsubst %.xml, %.9, $(BOOKS)) mandocs: $(MAN) -media: - mkdir -p $(srctree)/Documentation/DocBook/media/ - cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(srctree)/Documentation/DocBook/media/ +build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \ + cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/ installmandocs: mandocs mkdir -p /usr/local/man/man9/ From 3cd4bea0c43831b242a8562f713122b1b9daf21a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 3 Dec 2009 19:51:09 -0300 Subject: [PATCH 423/670] V4L/DVB (13680b): DocBook/media: create links for included sources commit 5bf583473813530c1bf82051a35fac8d5045f4f7 upstream. If docs are being built in a separate directory, xmlto and xsltproc can't find included sources. Make links back to the source directory. I would much prefer to have xmlto and xsltproc look in the source directory for included entities but couldn't see how to do that. This needs to be solved in some way for 2.6.32, even if this patch isn't the right way to do it. Signed-off-by: Ben Hutchings Cc: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- Documentation/DocBook/Makefile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 22bbf7e39018..50075df94962 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -32,10 +32,10 @@ PS_METHOD = $(prefer-db2x) ### # The targets that may be used. -PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs +PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs xmldoclinks BOOKS := $(addprefix $(obj)/,$(DOCBOOKS)) -xmldocs: $(BOOKS) +xmldocs: $(BOOKS) xmldoclinks sgmldocs: xmldocs PS := $(patsubst %.xml, %.ps, $(BOOKS)) @@ -55,6 +55,15 @@ mandocs: $(MAN) build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \ cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/ +xmldoclinks: +ifneq ($(objtree),$(srctree)) + for dep in dvb media-entities.tmpl media-indices.tmpl v4l; do \ + rm -f $(objtree)/Documentation/DocBook/$$dep \ + && ln -s $(srctree)/Documentation/DocBook/$$dep $(objtree)/Documentation/DocBook/ \ + || exit; \ + done +endif + installmandocs: mandocs mkdir -p /usr/local/man/man9/ install Documentation/DocBook/man/*.9.gz /usr/local/man/man9/ From 8f2fefcddff63394e42a6165040945cc9967bd19 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 23 Nov 2009 10:43:57 +0100 Subject: [PATCH 424/670] netfilter: xtables: fix conntrack match v1 ipt-save output commit 3a0429292daa0e1ec848bd26479f5e48b0d54a42 upstream. commit d6d3f08b0fd998b647a05540cedd11a067b72867 (netfilter: xtables: conntrack match revision 2) does break the v1 conntrack match iptables-save output in a subtle way. Problem is as follows: up = kmalloc(sizeof(*up), GFP_KERNEL); [..] /* * The strategy here is to minimize the overhead of v1 matching, * by prebuilding a v2 struct and putting the pointer into the * v1 dataspace. */ memcpy(up, info, offsetof(typeof(*info), state_mask)); [..] *(void **)info = up; As the v2 struct pointer is saved in the match data space, it clobbers the first structure member (->origsrc_addr). Because the _v1 match function grabs this pointer and does not actually look at the v1 origsrc, run time functionality does not break. But iptables -nvL (or iptables-save) cannot know that v1 origsrc_addr has been overloaded in this way: $ iptables -p tcp -A OUTPUT -m conntrack --ctorigsrc 10.0.0.1 -j ACCEPT $ iptables-save -A OUTPUT -p tcp -m conntrack --ctorigsrc 128.173.134.206 -j ACCEPT (128.173... is the address to the v2 match structure). To fix this, we take advantage of the fact that the v1 and v2 structures are identical with exception of the last two structure members (u8 in v1, u16 in v2). We extract them as early as possible and prevent the v2 matching function from looking at those two members directly. Previously reported by Michel Messerschmidt via Ben Hutchings, also see Debian Bug tracker #556587. Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- net/netfilter/xt_conntrack.c | 61 ++++++++++-------------------------- 1 file changed, 17 insertions(+), 44 deletions(-) diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 6dc4652f2fe8..ae66305f0fe5 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c @@ -113,7 +113,8 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info, } static bool -conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) +conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par, + u16 state_mask, u16 status_mask) { const struct xt_conntrack_mtinfo2 *info = par->matchinfo; enum ip_conntrack_info ctinfo; @@ -136,7 +137,7 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) if (test_bit(IPS_DST_NAT_BIT, &ct->status)) statebit |= XT_CONNTRACK_STATE_DNAT; } - if (!!(info->state_mask & statebit) ^ + if (!!(state_mask & statebit) ^ !(info->invert_flags & XT_CONNTRACK_STATE)) return false; } @@ -172,7 +173,7 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) return false; if ((info->match_flags & XT_CONNTRACK_STATUS) && - (!!(info->status_mask & ct->status) ^ + (!!(status_mask & ct->status) ^ !(info->invert_flags & XT_CONNTRACK_STATUS))) return false; @@ -192,11 +193,17 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) static bool conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) { - const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo; - struct xt_match_param newpar = *par; + const struct xt_conntrack_mtinfo1 *info = par->matchinfo; - newpar.matchinfo = *info; - return conntrack_mt(skb, &newpar); + return conntrack_mt(skb, par, info->state_mask, info->status_mask); +} + +static bool +conntrack_mt_v2(const struct sk_buff *skb, const struct xt_match_param *par) +{ + const struct xt_conntrack_mtinfo2 *info = par->matchinfo; + + return conntrack_mt(skb, par, info->state_mask, info->status_mask); } static bool conntrack_mt_check(const struct xt_mtchk_param *par) @@ -209,45 +216,11 @@ static bool conntrack_mt_check(const struct xt_mtchk_param *par) return true; } -static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par) -{ - struct xt_conntrack_mtinfo1 *info = par->matchinfo; - struct xt_conntrack_mtinfo2 *up; - int ret = conntrack_mt_check(par); - - if (ret < 0) - return ret; - - up = kmalloc(sizeof(*up), GFP_KERNEL); - if (up == NULL) { - nf_ct_l3proto_module_put(par->family); - return -ENOMEM; - } - - /* - * The strategy here is to minimize the overhead of v1 matching, - * by prebuilding a v2 struct and putting the pointer into the - * v1 dataspace. - */ - memcpy(up, info, offsetof(typeof(*info), state_mask)); - up->state_mask = info->state_mask; - up->status_mask = info->status_mask; - *(void **)info = up; - return true; -} - static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) { nf_ct_l3proto_module_put(par->family); } -static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par) -{ - struct xt_conntrack_mtinfo2 **info = par->matchinfo; - kfree(*info); - conntrack_mt_destroy(par); -} - static struct xt_match conntrack_mt_reg[] __read_mostly = { { .name = "conntrack", @@ -255,8 +228,8 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = { .family = NFPROTO_UNSPEC, .matchsize = sizeof(struct xt_conntrack_mtinfo1), .match = conntrack_mt_v1, - .checkentry = conntrack_mt_check_v1, - .destroy = conntrack_mt_destroy_v1, + .checkentry = conntrack_mt_check, + .destroy = conntrack_mt_destroy, .me = THIS_MODULE, }, { @@ -264,7 +237,7 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = { .revision = 2, .family = NFPROTO_UNSPEC, .matchsize = sizeof(struct xt_conntrack_mtinfo2), - .match = conntrack_mt, + .match = conntrack_mt_v2, .checkentry = conntrack_mt_check, .destroy = conntrack_mt_destroy, .me = THIS_MODULE, From 6f8de29a8ef0abd5800589f3f8f4927b9a72739a Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 23 Nov 2009 09:29:58 +0100 Subject: [PATCH 425/670] partitions: read whole sector with EFI GPT header commit 87038c2d5bda2418fda8b1456a0ae81cc3ff5bd8 upstream. The size of EFI GPT header is not static, but whole sector is allocated for the header. The HeaderSize field must be greater than 92 (= sizeof(struct gpt_header) and must be less than or equal to the logical block size. It means we have to read whole sector with the header, because the header crc32 checksum is calculated according to HeaderSize. For more details see UEFI standard (version 2.3, May 2009): - 5.3.1 GUID Format overview, page 93 - Table 13. GUID Partition Table Header, page 96 Signed-off-by: Karel Zak Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/partitions/efi.c | 7 ++++--- fs/partitions/efi.h | 8 ++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c index 038a6022152f..8e5e454d94e2 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c @@ -257,15 +257,16 @@ static gpt_header * alloc_read_gpt_header(struct block_device *bdev, u64 lba) { gpt_header *gpt; + unsigned ssz = bdev_logical_block_size(bdev); + if (!bdev) return NULL; - gpt = kzalloc(sizeof (gpt_header), GFP_KERNEL); + gpt = kzalloc(ssz, GFP_KERNEL); if (!gpt) return NULL; - if (read_lba(bdev, lba, (u8 *) gpt, - sizeof (gpt_header)) < sizeof (gpt_header)) { + if (read_lba(bdev, lba, (u8 *) gpt, ssz) < ssz) { kfree(gpt); gpt=NULL; return NULL; diff --git a/fs/partitions/efi.h b/fs/partitions/efi.h index 2cc89d0475bf..6998b589abf9 100644 --- a/fs/partitions/efi.h +++ b/fs/partitions/efi.h @@ -37,7 +37,6 @@ #define EFI_PMBR_OSTYPE_EFI 0xEF #define EFI_PMBR_OSTYPE_EFI_GPT 0xEE -#define GPT_BLOCK_SIZE 512 #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL #define GPT_HEADER_REVISION_V1 0x00010000 #define GPT_PRIMARY_PARTITION_TABLE_LBA 1 @@ -79,7 +78,12 @@ typedef struct _gpt_header { __le32 num_partition_entries; __le32 sizeof_partition_entry; __le32 partition_entry_array_crc32; - u8 reserved2[GPT_BLOCK_SIZE - 92]; + + /* The rest of the logical block is reserved by UEFI and must be zero. + * EFI standard handles this by: + * + * uint8_t reserved2[ BlockSize - 92 ]; + */ } __attribute__ ((packed)) gpt_header; typedef struct _gpt_entry_attributes { From e96610c64809b253558c3706b02fe173b0b829d8 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 23 Nov 2009 09:29:13 +0100 Subject: [PATCH 426/670] partitions: use sector size for EFI GPT commit 7d13af3279985f554784a45cc961f706dbcdbdd1 upstream. Currently, kernel uses strictly 512-byte sectors for EFI GPT parsing. That's wrong. UEFI standard (version 2.3, May 2009, 5.3.1 GUID Format overview, page 95) defines that LBA is always based on the logical block size. It means bdev_logical_block_size() (aka BLKSSZGET) for Linux. This patch removes static sector size from EFI GPT parser. The problem is reproducible with the latest GNU Parted: # modprobe scsi_debug dev_size_mb=50 sector_size=4096 # ./parted /dev/sdb print Model: Linux scsi_debug (scsi) Disk /dev/sdb: 52.4MB Sector size (logical/physical): 4096B/4096B Partition Table: gpt Number Start End Size File system Name Flags 1 24.6kB 3002kB 2978kB primary 2 3002kB 6001kB 2998kB primary 3 6001kB 9003kB 3002kB primary # blockdev --rereadpt /dev/sdb # dmesg | tail -1 sdb: unknown partition table <---- !!! with this patch: # blockdev --rereadpt /dev/sdb # dmesg | tail -1 sdb: sdb1 sdb2 sdb3 Signed-off-by: Karel Zak Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/partitions/efi.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c index 8e5e454d94e2..49cfd5f54238 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c @@ -1,7 +1,9 @@ /************************************************************ * EFI GUID Partition Table handling - * Per Intel EFI Specification v1.02 - * http://developer.intel.com/technology/efi/efi.htm + * + * http://www.uefi.org/specs/ + * http://www.intel.com/technology/efi/ + * * efi.[ch] by Matt Domsch * Copyright 2000,2001,2002,2004 Dell Inc. * @@ -92,6 +94,7 @@ * ************************************************************/ #include +#include #include "check.h" #include "efi.h" @@ -141,7 +144,8 @@ last_lba(struct block_device *bdev) { if (!bdev || !bdev->bd_inode) return 0; - return (bdev->bd_inode->i_size >> 9) - 1ULL; + return div_u64(bdev->bd_inode->i_size, + bdev_logical_block_size(bdev)) - 1ULL; } static inline int @@ -188,6 +192,7 @@ static size_t read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count) { size_t totalreadcount = 0; + sector_t n = lba * (bdev_logical_block_size(bdev) / 512); if (!bdev || !buffer || lba > last_lba(bdev)) return 0; @@ -195,7 +200,7 @@ read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count) while (count) { int copied = 512; Sector sect; - unsigned char *data = read_dev_sector(bdev, lba++, §); + unsigned char *data = read_dev_sector(bdev, n++, §); if (!data) break; if (copied > count) @@ -602,6 +607,7 @@ efi_partition(struct parsed_partitions *state, struct block_device *bdev) gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; + unsigned ssz = bdev_logical_block_size(bdev) / 512; if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); @@ -612,13 +618,14 @@ efi_partition(struct parsed_partitions *state, struct block_device *bdev) pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { + u64 start = le64_to_cpu(ptes[i].starting_lba); + u64 size = le64_to_cpu(ptes[i].ending_lba) - + le64_to_cpu(ptes[i].starting_lba) + 1ULL; + if (!is_pte_valid(&ptes[i], last_lba(bdev))) continue; - put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba), - (le64_to_cpu(ptes[i].ending_lba) - - le64_to_cpu(ptes[i].starting_lba) + - 1ULL)); + put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, From eb9dbd9c1ffe8fa93e385c186e25ffa7bad53b67 Mon Sep 17 00:00:00 2001 From: Aleksey Kunitskiy Date: Sat, 14 Nov 2009 15:18:54 +0200 Subject: [PATCH 427/670] ALSA: ice1724 - Patch for suspend/resume for ESI Juli@ commit 50d40f187f9182ee8caa1b83f80a0e11e2226baa upstream. Add proper suspend/resume code for Juli@ cards. Based on ice1724 suspend/resume work of Igor Chernyshev. Fixes bug https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4413 Tested on linux-2.6.31.6 Signed-off-by: Aleksey Kunitskiy Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/ice1712/juli.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index fd948bfd9aef..f5020ad99a10 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c @@ -503,6 +503,31 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice) return 0; } +/* + * suspend/resume + * */ + +#ifdef CONFIG_PM +static int juli_resume(struct snd_ice1712 *ice) +{ + struct snd_akm4xxx *ak = ice->akm; + struct juli_spec *spec = ice->spec; + /* akm4358 un-reset, un-mute */ + snd_akm4xxx_reset(ak, 0); + /* reinit ak4114 */ + snd_ak4114_reinit(spec->ak4114); + return 0; +} + +static int juli_suspend(struct snd_ice1712 *ice) +{ + struct snd_akm4xxx *ak = ice->akm; + /* akm4358 reset and soft-mute */ + snd_akm4xxx_reset(ak, 1); + return 0; +} +#endif + /* * initialize the chip */ @@ -646,6 +671,13 @@ static int __devinit juli_init(struct snd_ice1712 *ice) ice->set_spdif_clock = juli_set_spdif_clock; ice->spdif.ops.open = juli_spdif_in_open; + +#ifdef CONFIG_PM + ice->pm_resume = juli_resume; + ice->pm_suspend = juli_suspend; + ice->pm_suspend_enabled = 1; +#endif + return 0; } From 08b84be9e906f97340acbf6c5daaa53bbf4fa194 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 2 Dec 2009 14:09:16 +1030 Subject: [PATCH 428/670] sched: Fix isolcpus boot option commit bdddd2963c0264c56f18043f6fa829d3c1d3d1c0 upstream. Anton Blanchard wrote: > We allocate and zero cpu_isolated_map after the isolcpus > __setup option has run. This means cpu_isolated_map always > ends up empty and if CPUMASK_OFFSTACK is enabled we write to a > cpumask that hasn't been allocated. I introduced this regression in 49557e620339cb13 (sched: Fix boot crash by zalloc()ing most of the cpu masks). Use the bootmem allocator if they set isolcpus=, otherwise allocate and zero like normal. Reported-by: Anton Blanchard Signed-off-by: Rusty Russell Cc: peterz@infradead.org Cc: Linus Torvalds Cc: LKML-Reference: <200912021409.17013.rusty@rustcorp.com.au> Signed-off-by: Ingo Molnar Tested-by: Anton Blanchard --- kernel/sched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index bf841d85b9ba..ab15840d3952 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -8061,6 +8061,7 @@ static cpumask_var_t cpu_isolated_map; /* Setup the mask of cpus configured for isolated domains */ static int __init isolated_cpu_setup(char *str) { + alloc_bootmem_cpumask_var(&cpu_isolated_map); cpulist_parse(str, cpu_isolated_map); return 1; } @@ -9591,7 +9592,9 @@ void __init sched_init(void) zalloc_cpumask_var(&nohz.cpu_mask, GFP_NOWAIT); alloc_cpumask_var(&nohz.ilb_grp_nohz_mask, GFP_NOWAIT); #endif - zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT); + /* May be allocated at isolcpus cmdline parse time */ + if (cpu_isolated_map == NULL) + zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT); #endif /* SMP */ perf_event_init(); From db47a1671a787a27a6f9ef780f1865fa4372f361 Mon Sep 17 00:00:00 2001 From: Christian Ehrhardt Date: Mon, 30 Nov 2009 12:16:46 +0100 Subject: [PATCH 429/670] sched: Fix missing sched tunable recalculation on cpu add/remove commit 0bcdcf28c979869f44e05121b96ff2cfb05bd8e6 upstream. Based on Peter Zijlstras patch suggestion this enables recalculation of the scheduler tunables in response of a change in the number of cpus. It also adds a max of eight cpus that are considered in that scaling. Signed-off-by: Christian Ehrhardt Signed-off-by: Peter Zijlstra LKML-Reference: <1259579808-11357-2-git-send-email-ehrhardt@linux.vnet.ibm.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 31 +++++++++++++++++-------------- kernel/sched_fair.c | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index ab15840d3952..60d74cc721cc 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -816,6 +816,7 @@ const_debug unsigned int sysctl_sched_nr_migrate = 32; * default: 0.25ms */ unsigned int sysctl_sched_shares_ratelimit = 250000; +unsigned int normalized_sysctl_sched_shares_ratelimit = 250000; /* * Inject some fuzzyness into changing the per-cpu group shares @@ -1812,6 +1813,7 @@ static void cfs_rq_set_shares(struct cfs_rq *cfs_rq, unsigned long shares) #endif static void calc_load_account_active(struct rq *this_rq); +static void update_sysctl(void); #include "sched_stats.h" #include "sched_idletask.c" @@ -7018,22 +7020,23 @@ cpumask_var_t nohz_cpu_mask; * * This idea comes from the SD scheduler of Con Kolivas: */ +static void update_sysctl(void) +{ + unsigned int cpus = min(num_online_cpus(), 8U); + unsigned int factor = 1 + ilog2(cpus); + +#define SET_SYSCTL(name) \ + (sysctl_##name = (factor) * normalized_sysctl_##name) + SET_SYSCTL(sched_min_granularity); + SET_SYSCTL(sched_latency); + SET_SYSCTL(sched_wakeup_granularity); + SET_SYSCTL(sched_shares_ratelimit); +#undef SET_SYSCTL +} + static inline void sched_init_granularity(void) { - unsigned int factor = 1 + ilog2(num_online_cpus()); - const unsigned long limit = 200000000; - - sysctl_sched_min_granularity *= factor; - if (sysctl_sched_min_granularity > limit) - sysctl_sched_min_granularity = limit; - - sysctl_sched_latency *= factor; - if (sysctl_sched_latency > limit) - sysctl_sched_latency = limit; - - sysctl_sched_wakeup_granularity *= factor; - - sysctl_sched_shares_ratelimit *= factor; + update_sysctl(); } #ifdef CONFIG_SMP diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 199228b24bbc..d80812d39d62 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -35,12 +35,14 @@ * run vmstat and monitor the context-switches (cs) field) */ unsigned int sysctl_sched_latency = 5000000ULL; +unsigned int normalized_sysctl_sched_latency = 5000000ULL; /* * Minimal preemption granularity for CPU-bound tasks: * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds) */ unsigned int sysctl_sched_min_granularity = 1000000ULL; +unsigned int normalized_sysctl_sched_min_granularity = 1000000ULL; /* * is kept at sysctl_sched_latency / sysctl_sched_min_granularity @@ -70,6 +72,7 @@ unsigned int __read_mostly sysctl_sched_compat_yield; * have immediate wakeup/sleep latencies. */ unsigned int sysctl_sched_wakeup_granularity = 1000000UL; +unsigned int normalized_sysctl_sched_wakeup_granularity = 1000000UL; const_debug unsigned int sysctl_sched_migration_cost = 500000UL; @@ -1880,6 +1883,17 @@ move_one_task_fair(struct rq *this_rq, int this_cpu, struct rq *busiest, return 0; } + +static void rq_online_fair(struct rq *rq) +{ + update_sysctl(); +} + +static void rq_offline_fair(struct rq *rq) +{ + update_sysctl(); +} + #endif /* CONFIG_SMP */ /* @@ -2027,6 +2041,8 @@ static const struct sched_class fair_sched_class = { .load_balance = load_balance_fair, .move_one_task = move_one_task_fair, + .rq_online = rq_online_fair, + .rq_offline = rq_offline_fair, #endif .set_curr_task = set_curr_task_fair, From a9238ce3bb0fda6e760780b702c6cbd3793087d3 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 18 Aug 2009 12:45:10 -0500 Subject: [PATCH 430/670] nohz: Prevent clocksource wrapping during idle commit 98962465ed9e6ea99c38e0af63fe1dcb5a79dc25 upstream. The dynamic tick allows the kernel to sleep for periods longer than a single tick, but it does not limit the sleep time currently. In the worst case the kernel could sleep longer than the wrap around time of the time keeping clock source which would result in losing track of time. Prevent this by limiting it to the safe maximum sleep time of the current time keeping clock source. The value is calculated when the clock source is registered. [ tglx: simplified the code a bit and massaged the commit msg ] Signed-off-by: Jon Hunter Cc: John Stultz LKML-Reference: <1250617512-23567-2-git-send-email-jon-hunter@ti.com> Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- include/linux/clocksource.h | 2 ++ include/linux/time.h | 1 + kernel/time/clocksource.c | 44 +++++++++++++++++++++++++++++++ kernel/time/tick-sched.c | 52 +++++++++++++++++++++++++++---------- kernel/time/timekeeping.c | 11 ++++++++ 5 files changed, 96 insertions(+), 14 deletions(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 83d2fbd81b93..64b1a4cc5a8b 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -151,6 +151,7 @@ extern u64 timecounter_cyc2time(struct timecounter *tc, * subtraction of non 64 bit counters * @mult: cycle to nanosecond multiplier * @shift: cycle to nanosecond divisor (power of two) + * @max_idle_ns: max idle time permitted by the clocksource (nsecs) * @flags: flags describing special properties * @vread: vsyscall based read * @resume: resume function for the clocksource, if necessary @@ -168,6 +169,7 @@ struct clocksource { cycle_t mask; u32 mult; u32 shift; + u64 max_idle_ns; unsigned long flags; cycle_t (*vread)(void); void (*resume)(void); diff --git a/include/linux/time.h b/include/linux/time.h index fe04e5ef6a59..6e026e45a179 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -148,6 +148,7 @@ extern void monotonic_to_bootbased(struct timespec *ts); extern struct timespec timespec_trunc(struct timespec t, unsigned gran); extern int timekeeping_valid_for_hres(void); +extern u64 timekeeping_max_deferment(void); extern void update_wall_time(void); extern void update_xtime_cache(u64 nsec); extern void timekeeping_leap_insert(int leapsecond); diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 5e18c6ab2c6a..5155dc3e2ea9 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -415,6 +415,47 @@ void clocksource_touch_watchdog(void) #ifdef CONFIG_GENERIC_TIME +/** + * clocksource_max_deferment - Returns max time the clocksource can be deferred + * @cs: Pointer to clocksource + * + */ +static u64 clocksource_max_deferment(struct clocksource *cs) +{ + u64 max_nsecs, max_cycles; + + /* + * 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)) + * 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)); + + /* + * The actual maximum number of cycles we can defer the clocksource is + * determined by the minimum of max_cycles and cs->mask. + */ + max_cycles = min_t(u64, max_cycles, (u64) cs->mask); + max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult, cs->shift); + + /* + * To ensure that the clocksource does not wrap whilst we are idle, + * limit the time the clocksource can be deferred by 12.5%. Please + * 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); +} + /** * clocksource_select - Select the best clocksource available * @@ -511,6 +552,9 @@ static void clocksource_enqueue(struct clocksource *cs) */ int clocksource_register(struct clocksource *cs) { + /* calculate max idle time permitted for this clocksource */ + cs->max_idle_ns = clocksource_max_deferment(cs); + mutex_lock(&clocksource_mutex); clocksource_enqueue(cs); clocksource_select(); diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 89aed5933ed4..44320b1e2a6c 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -216,6 +216,7 @@ void tick_nohz_stop_sched_tick(int inidle) struct tick_sched *ts; ktime_t last_update, expires, now; struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; + u64 time_delta; int cpu; local_irq_save(flags); @@ -275,6 +276,17 @@ void tick_nohz_stop_sched_tick(int inidle) seq = read_seqbegin(&xtime_lock); last_update = last_jiffies_update; last_jiffies = jiffies; + + /* + * On SMP we really should only care for the CPU which + * has the do_timer duty assigned. All other CPUs can + * sleep as long as they want. + */ + if (cpu == tick_do_timer_cpu || + tick_do_timer_cpu == TICK_DO_TIMER_NONE) + time_delta = timekeeping_max_deferment(); + else + time_delta = KTIME_MAX; } while (read_seqretry(&xtime_lock, seq)); /* Get the next timer wheel timer */ @@ -294,11 +306,26 @@ void tick_nohz_stop_sched_tick(int inidle) if ((long)delta_jiffies >= 1) { /* - * calculate the expiry time for the next timer wheel - * timer - */ - expires = ktime_add_ns(last_update, tick_period.tv64 * - delta_jiffies); + * calculate the expiry time for the next timer wheel + * timer. delta_jiffies >= NEXT_TIMER_MAX_DELTA signals + * that there is no timer pending or at least extremely + * far into the future (12 days for HZ=1000). In this + * case we set the expiry to the end of time. + */ + if (likely(delta_jiffies < NEXT_TIMER_MAX_DELTA)) { + /* + * Calculate the time delta for the next timer event. + * If the time delta exceeds the maximum time delta + * permitted by the current clocksource then adjust + * the time delta accordingly to ensure the + * clocksource does not wrap. + */ + time_delta = min_t(u64, time_delta, + tick_period.tv64 * delta_jiffies); + expires = ktime_add_ns(last_update, time_delta); + } else { + expires.tv64 = KTIME_MAX; + } /* * If this cpu is the one which updates jiffies, then @@ -342,22 +369,19 @@ void tick_nohz_stop_sched_tick(int inidle) ts->idle_sleeps++; + /* Mark expires */ + ts->idle_expires = expires; + /* - * delta_jiffies >= NEXT_TIMER_MAX_DELTA signals that - * there is no timer pending or at least extremly far - * into the future (12 days for HZ=1000). In this case - * we simply stop the tick timer: + * If the expiration time == KTIME_MAX, then + * in this case we simply stop the tick timer. */ - if (unlikely(delta_jiffies >= NEXT_TIMER_MAX_DELTA)) { - ts->idle_expires.tv64 = KTIME_MAX; + if (unlikely(expires.tv64 == KTIME_MAX)) { if (ts->nohz_mode == NOHZ_MODE_HIGHRES) hrtimer_cancel(&ts->sched_timer); goto out; } - /* Mark expiries */ - ts->idle_expires = expires; - if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { hrtimer_start(&ts->sched_timer, expires, HRTIMER_MODE_ABS_PINNED); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index c3a4e2907eaa..66d090e3c70a 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -487,6 +487,17 @@ int timekeeping_valid_for_hres(void) return ret; } +/** + * timekeeping_max_deferment - Returns max time the clocksource can be deferred + * + * Caller must observe xtime_lock via read_seqbegin/read_seqretry to + * ensure that the clocksource does not change! + */ +u64 timekeeping_max_deferment(void) +{ + return timekeeper.clock->max_idle_ns; +} + /** * read_persistent_clock - Return time from the persistent clock. * From 34911bf2037c212644cc6b3e2e3207af4e763df7 Mon Sep 17 00:00:00 2001 From: Frank Filz Date: Wed, 21 Oct 2009 16:45:02 -0700 Subject: [PATCH 431/670] nfsd: Fix sort_pacl in fs/nfsd/nf4acl.c to actually sort groups commit aba24d71580180dfdf6a1a83a5858a1c048fd785 upstream. We have been doing some extensive testing of Linux support for ACLs on NFDS v4. We have noticed that the server rejects ACLs where the groups are out of order, for example, the following ACL is rejected: A::OWNER@:rwaxtTcCy A::user101@domain:rwaxtcy A::GROUP@:rwaxtcy A:g:group102@domain:rwaxtcy A:g:group101@domain:rwaxtcy A::EVERYONE@:rwaxtcy Examining the server code, I found that after converting an NFS v4 ACL to POSIX, sort_pacl is called to sort the user ACEs and group ACEs. Unfortunately, a minor bug causes the group sort to be skipped. Signed-off-by: Frank Filz Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman --- fs/nfsd/nfs4acl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 725d02f210e2..6d9c6aabc85e 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c @@ -389,7 +389,7 @@ sort_pacl(struct posix_acl *pacl) sort_pacl_range(pacl, 1, i-1); BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ); - j = i++; + j = ++i; while (pacl->a_entries[j].e_tag == ACL_GROUP) j++; sort_pacl_range(pacl, i, j-1); From 5cf92e9a8fb63cff15027fd6a738d455b4efcd1a Mon Sep 17 00:00:00 2001 From: Mike Travis Date: Tue, 17 Nov 2009 18:22:13 -0600 Subject: [PATCH 432/670] timers, init: Limit the number of per cpu calibration bootup messages commit feae3203d711db0a9965300ee6d592257fdaae4f upstream. Limit the number of per cpu calibration messages by only printing out results for the first cpu to boot. Also, don't print "CPUx is down" as this is expected, and we don't need 4096 reminders... ;-) Signed-off-by: Mike Travis Cc: Heiko Carstens Cc: Roland Dreier Cc: Randy Dunlap Cc: Tejun Heo Cc: Andi Kleen Cc: Greg Kroah-Hartman Cc: Yinghai Lu Cc: David Rientjes Cc: Steven Rostedt Cc: Rusty Russell Cc: Hidetoshi Seto Cc: Jack Steiner Cc: Frederic Weisbecker LKML-Reference: <20091118002219.889552000@alcatraz.americas.sgi.com> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- init/calibrate.c | 24 +++++++++++++++--------- kernel/cpu.c | 5 ++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/init/calibrate.c b/init/calibrate.c index a379c9061199..6eb48e53d61c 100644 --- a/init/calibrate.c +++ b/init/calibrate.c @@ -123,23 +123,26 @@ void __cpuinit calibrate_delay(void) { unsigned long ticks, loopbit; int lps_precision = LPS_PREC; + static bool printed; if (preset_lpj) { loops_per_jiffy = preset_lpj; - printk(KERN_INFO - "Calibrating delay loop (skipped) preset value.. "); - } else if ((smp_processor_id() == 0) && lpj_fine) { + if (!printed) + pr_info("Calibrating delay loop (skipped) " + "preset value.. "); + } else if ((!printed) && lpj_fine) { loops_per_jiffy = lpj_fine; - printk(KERN_INFO - "Calibrating delay loop (skipped), " + pr_info("Calibrating delay loop (skipped), " "value calculated using timer frequency.. "); } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) { - printk(KERN_INFO - "Calibrating delay using timer specific routine.. "); + if (!printed) + pr_info("Calibrating delay using timer " + "specific routine.. "); } else { loops_per_jiffy = (1<<12); - printk(KERN_INFO "Calibrating delay loop... "); + if (!printed) + pr_info("Calibrating delay loop... "); while ((loops_per_jiffy <<= 1) != 0) { /* wait for "start of" clock tick */ ticks = jiffies; @@ -170,7 +173,10 @@ void __cpuinit calibrate_delay(void) loops_per_jiffy &= ~loopbit; } } - printk(KERN_CONT "%lu.%02lu BogoMIPS (lpj=%lu)\n", + if (!printed) + pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy); + + printed = true; } diff --git a/kernel/cpu.c b/kernel/cpu.c index b21688640377..291ac586f37f 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -400,10 +400,9 @@ int disable_nonboot_cpus(void) if (cpu == first_cpu) continue; error = _cpu_down(cpu, 1); - if (!error) { + if (!error) cpumask_set_cpu(cpu, frozen_cpus); - printk("CPU%d is down\n", cpu); - } else { + else { printk(KERN_ERR "Error taking CPU%d down: %d\n", cpu, error); break; From 83886fa2a0a80b8069b37beed574655feeb70de3 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 30 Nov 2009 14:51:44 -0700 Subject: [PATCH 433/670] PCI: Always set prefetchable base/limit upper32 registers commit 59353ea30e65ab3ae181d6175e3212e1361c3787 upstream. Prior to 1f82de10 we always initialized the upper 32bits of the prefetchable memory window, regardless of the address range used. Now we only touch it for a >32bit address, which means the upper32 registers remain whatever the BIOS initialized them too. It's valid for the BIOS to set the upper32 base/limit to 0xffffffff/0x00000000, which makes us program prefetchable ranges like 0xffffffffabc00000 - 0x00000000abc00000 Revert the chunk of 1f82de10 that made this conditional so we always write the upper32 registers and remove now unused pref_mem64 variable. Signed-off-by: Alex Williamson Signed-off-by: Jesse Barnes Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/pci/setup-bus.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index cb1a027eb552..dd58c6a36a51 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -142,7 +142,6 @@ static void pci_setup_bridge(struct pci_bus *bus) struct pci_dev *bridge = bus->self; struct pci_bus_region region; u32 l, bu, lu, io_upper16; - int pref_mem64; if (pci_is_enabled(bridge)) return; @@ -198,7 +197,6 @@ static void pci_setup_bridge(struct pci_bus *bus) pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); /* Set up PREF base/limit. */ - pref_mem64 = 0; bu = lu = 0; pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { @@ -206,7 +204,6 @@ static void pci_setup_bridge(struct pci_bus *bus) l = (region.start >> 16) & 0xfff0; l |= region.end & 0xfff00000; if (bus->resource[2]->flags & IORESOURCE_MEM_64) { - pref_mem64 = 1; bu = upper_32_bits(region.start); lu = upper_32_bits(region.end); width = 16; @@ -221,11 +218,9 @@ static void pci_setup_bridge(struct pci_bus *bus) } pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); - if (pref_mem64) { - /* Set the upper 32 bits of PREF base & limit. */ - pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); - pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); - } + /* Set the upper 32 bits of PREF base & limit. */ + pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); + pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); } From 1d42a1bd932f8963c5c5b4944baabb7e74b6e8e2 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 11 Nov 2009 16:34:34 -0600 Subject: [PATCH 434/670] iscsi class: modify handling of replacement timeout commit fdd46dcbe4468a1f47a2cc9be442d11c3d21dd68 upstream. This patch modifies the replacement/recovery_timeout so it works more like the fc fast io fail tmo. If userspace tries to set the replacement/recovery_timeout to less than zero, we will turn off the forced recovery cleanup. If userspace sets the value to 0 then we will force the recovery cleanup immediately. Signed-off-by: Mike Christie Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_transport_iscsi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index ad897df36615..de2f8c450049 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -627,8 +627,10 @@ static void __iscsi_block_session(struct work_struct *work) spin_unlock_irqrestore(&session->lock, flags); scsi_target_block(&session->dev); ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n"); - queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work, - session->recovery_tmo * HZ); + if (session->recovery_tmo >= 0) + queue_delayed_work(iscsi_eh_timer_workq, + &session->recovery_work, + session->recovery_tmo * HZ); } void iscsi_block_session(struct iscsi_cls_session *session) @@ -1348,8 +1350,7 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) switch (ev->u.set_param.param) { case ISCSI_PARAM_SESS_RECOVERY_TMO: sscanf(data, "%d", &value); - if (value != 0) - session->recovery_tmo = value; + session->recovery_tmo = value; break; default: err = transport->set_param(conn, ev->u.set_param.param, From 5e057878f946d25bf3a3bc811f4e27099f41c24f Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Thu, 3 Dec 2009 15:58:56 -0500 Subject: [PATCH 435/670] NFS: Revert default r/wsize behavior commit dd47f96c077b4516727e497e4b6fd47a06778c0a upstream. When the "rsize=" or "wsize=" mount options are not specified, text-based mounts have slightly different behavior than legacy binary mounts. Text-based mounts use the smaller of the server's maximum and the client's maximum, but binary mounts use the smaller of the server's _preferred_ size and the client's maximum. This difference is actually pretty subtle. Most servers advertise the same value as their maximum and their preferred transfer size, so the end result is the same in most cases. The reason for this difference is that for text-based mounts, if r/wsize are not specified, they are set to the largest value supported by the client. For legacy mounts, the values are set to zero if these options are not specified. nfs_server_set_fsinfo() can negotiate the transfer size defaults correctly in any case. There's no need to specify any particular value as default in the text-based option parsing logic. Note that nfs4 doesn't use nfs_server_set_fsinfo(), but the mount.nfs4 command does set rsize and wsize to 0 if the user didn't specify these options. So, make the same change for text-based NFSv4 mounts. Thanks to James Pearson for reporting and diagnosing the problem. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust Cc: Neil Brown Signed-off-by: Greg Kroah-Hartman --- fs/nfs/super.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 90be551b80c1..e71f0fdff1da 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -734,8 +734,6 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve data = kzalloc(sizeof(*data), GFP_KERNEL); if (data) { - data->rsize = NFS_MAX_FILE_IO_SIZE; - data->wsize = NFS_MAX_FILE_IO_SIZE; data->acregmin = NFS_DEF_ACREGMIN; data->acregmax = NFS_DEF_ACREGMAX; data->acdirmin = NFS_DEF_ACDIRMIN; From 001252f8ea9e1ce2e376d515d410c23d932b5a31 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 5 Nov 2009 14:08:03 +0100 Subject: [PATCH 436/670] HID: fixup quirk for NCR devices commit 5b915d9e6dc3d22fedde91dfef1cb1a8fa9a1870 upstream. NCR devices are terminally broken by design -- they claim themselves to contain proper input applications in their HID report descriptor, but behave very badly if treated in standard way. According to NCR developers, the devices get confused when queried for reports in a standard way, rendering them unusable. NCR is shipping application called "RPSL" that can be used to drive these devices through hiddev, under the assumption that in-kernel driver doesn't perform initial report query. If it does, neither in-kernel nor hiddev-based driver can operate with these devices any more. Introduce a quirk that skips the report query for all NCR devices. The previous NOGET quirk was wrong and had been introduced because I misunderstood the nature of brokenness of these devices. Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/usbhid/hid-core.c | 3 ++- drivers/hid/usbhid/hid-quirks.c | 2 +- include/linux/hid.h | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 03bd703255a3..5d901f698838 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -998,7 +998,8 @@ static int usbhid_start(struct hid_device *hid) usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); - usbhid_init_reports(hid); + if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS)) + usbhid_init_reports(hid); set_bit(HID_STARTED, &usbhid->iofl); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 0d9045aa2c4b..5713b93e76cb 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -280,7 +280,7 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct) if (idVendor == USB_VENDOR_ID_NCR && idProduct >= USB_DEVICE_ID_NCR_FIRST && idProduct <= USB_DEVICE_ID_NCR_LAST) - return HID_QUIRK_NOGET; + return HID_QUIRK_NO_INIT_REPORTS; down_read(&dquirks_rwsem); bl_entry = usbhid_exists_dquirk(idVendor, idProduct); diff --git a/include/linux/hid.h b/include/linux/hid.h index 10f628416740..87093652dda8 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -312,6 +312,7 @@ struct hid_item { #define HID_QUIRK_MULTI_INPUT 0x00000040 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 +#define HID_QUIRK_NO_INIT_REPORTS 0x20000000 /* * This is the global environment of the parser. This information is From e7c8167e4e6fc9c66740e3984add69154bf30a90 Mon Sep 17 00:00:00 2001 From: Takahiro Yasui Date: Tue, 10 Nov 2009 16:22:19 -0500 Subject: [PATCH 437/670] scsi_devinfo: update Hitachi entries (v2) commit 627511e3e67553b04f6917c03e39b797df210e04 upstream. Four models, OPEN-/DF400/DF500/DISK-SUBSYSTEM, can handle REPORT_LUN, and the BLIST_REPORTLUN2 flag needs to be set. And DF600 doesn't require any flags because it returns ANSI 03h (SPC). Signed-off-by: Takahiro Yasui Signed-off-by: James Bottomley Acked-by: Hannes Reinecke Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_devinfo.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 93c2622cb969..802e91c8892e 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -168,11 +168,10 @@ static struct { {"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN | BLIST_INQUIRY_36}, {"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN | BLIST_INQUIRY_36}, {"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN | BLIST_INQUIRY_36}, - {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, - {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN}, - {"HITACHI", "OPEN-E", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN}, + {"HITACHI", "DF400", "*", BLIST_REPORTLUN2}, + {"HITACHI", "DF500", "*", BLIST_REPORTLUN2}, + {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2}, + {"HITACHI", "OPEN-", "*", BLIST_REPORTLUN2}, {"HITACHI", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"HITACHI", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"HITACHI", "3390-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, From d502a766937129c5965bc88b8740a9362b9b263b Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Fri, 11 Sep 2009 10:20:35 -0700 Subject: [PATCH 438/670] scsi_dh: create sysfs file, dh_state for all SCSI disk devices commit 5917290ce9b376866b165d02a5ed88d5ecdb32d0 upstream. Create the sysfs file, dh_state even if the new SCSI device is not in the any of the device handler's internal lists. Signed-Off-by: Chandra Seetharaman Acked-by: Hannes Reinecke Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/device_handler/scsi_dh.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index 3ee1cbc89479..bfec4fa5addf 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c @@ -304,18 +304,15 @@ static int scsi_dh_notifier(struct notifier_block *nb, sdev = to_scsi_device(dev); if (action == BUS_NOTIFY_ADD_DEVICE) { + err = device_create_file(dev, &scsi_dh_state_attr); + /* don't care about err */ devinfo = device_handler_match(NULL, sdev); - if (!devinfo) - goto out; - - err = scsi_dh_handler_attach(sdev, devinfo); - if (!err) - err = device_create_file(dev, &scsi_dh_state_attr); + if (devinfo) + err = scsi_dh_handler_attach(sdev, devinfo); } else if (action == BUS_NOTIFY_DEL_DEVICE) { device_remove_file(dev, &scsi_dh_state_attr); scsi_dh_handler_detach(sdev, NULL); } -out: return err; } From 4b2bc96c3aa79b5d39be8ddbf903b7d19c701d88 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Fri, 9 Oct 2009 14:15:59 -0500 Subject: [PATCH 439/670] scsi_transport_fc: remove invalid BUG_ON commit 8798a694da59486e4a3ff0abeec183202fb34c20 upstream. I was doing some large lun count testing with 2.6.31 and hit a BUG_ON() in fc_timeout_deleted_rport(), and it seems like it should have been just a matter of time before someone did. It seems invalid to set port_state under lock, then expect it to remain set after releasing the lock. Another thread called fc_remote_port_add() when the lock was released, changing the port_state. This patch removes the BUG_ON and moves the test of the port_state to inside the host_lock. It's been running for several weeks now with no ill effect. Signed-off-by: Michael Reed Acked-by: James Smart Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_transport_fc.c | 68 ++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 45be82f46321..bf52decfdef4 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2395,6 +2395,7 @@ fc_rport_final_delete(struct work_struct *work) struct Scsi_Host *shost = rport_to_shost(rport); struct fc_internal *i = to_fc_internal(shost->transportt); unsigned long flags; + int do_callback = 0; /* * if a scan is pending, flush the SCSI Host work_q so that @@ -2433,8 +2434,15 @@ fc_rport_final_delete(struct work_struct *work) * Avoid this call if we already called it when we preserved the * rport for the binding. */ + spin_lock_irqsave(shost->host_lock, flags); if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) && - (i->f->dev_loss_tmo_callbk)) + (i->f->dev_loss_tmo_callbk)) { + rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; + do_callback = 1; + } + spin_unlock_irqrestore(shost->host_lock, flags); + + if (do_callback) i->f->dev_loss_tmo_callbk(rport); fc_bsg_remove(rport->rqst_q); @@ -2981,6 +2989,7 @@ fc_timeout_deleted_rport(struct work_struct *work) struct fc_internal *i = to_fc_internal(shost->transportt); struct fc_host_attrs *fc_host = shost_to_fc_host(shost); unsigned long flags; + int do_callback = 0; spin_lock_irqsave(shost->host_lock, flags); @@ -3046,7 +3055,6 @@ fc_timeout_deleted_rport(struct work_struct *work) rport->roles = FC_PORT_ROLE_UNKNOWN; rport->port_state = FC_PORTSTATE_NOTPRESENT; rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT; - rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; /* * Pre-emptively kill I/O rather than waiting for the work queue @@ -3056,32 +3064,40 @@ fc_timeout_deleted_rport(struct work_struct *work) spin_unlock_irqrestore(shost->host_lock, flags); fc_terminate_rport_io(rport); - BUG_ON(rport->port_state != FC_PORTSTATE_NOTPRESENT); + spin_lock_irqsave(shost->host_lock, flags); - /* remove the identifiers that aren't used in the consisting binding */ - switch (fc_host->tgtid_bind_type) { - case FC_TGTID_BIND_BY_WWPN: - rport->node_name = -1; - rport->port_id = -1; - break; - case FC_TGTID_BIND_BY_WWNN: - rport->port_name = -1; - rport->port_id = -1; - break; - case FC_TGTID_BIND_BY_ID: - rport->node_name = -1; - rport->port_name = -1; - break; - case FC_TGTID_BIND_NONE: /* to keep compiler happy */ - break; + if (rport->port_state == FC_PORTSTATE_NOTPRESENT) { /* still missing */ + + /* remove the identifiers that aren't used in the consisting binding */ + switch (fc_host->tgtid_bind_type) { + case FC_TGTID_BIND_BY_WWPN: + rport->node_name = -1; + rport->port_id = -1; + break; + case FC_TGTID_BIND_BY_WWNN: + rport->port_name = -1; + rport->port_id = -1; + break; + case FC_TGTID_BIND_BY_ID: + rport->node_name = -1; + rport->port_name = -1; + break; + case FC_TGTID_BIND_NONE: /* to keep compiler happy */ + break; + } + + /* + * As this only occurs if the remote port (scsi target) + * went away and didn't come back - we'll remove + * all attached scsi devices. + */ + rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; + fc_queue_work(shost, &rport->stgt_delete_work); + + do_callback = 1; } - /* - * As this only occurs if the remote port (scsi target) - * went away and didn't come back - we'll remove - * all attached scsi devices. - */ - fc_queue_work(shost, &rport->stgt_delete_work); + spin_unlock_irqrestore(shost->host_lock, flags); /* * Notify the driver that the rport is now dead. The LLDD will @@ -3089,7 +3105,7 @@ fc_timeout_deleted_rport(struct work_struct *work) * * Note: we set the CALLBK_DONE flag above to correspond */ - if (i->f->dev_loss_tmo_callbk) + if (do_callback && i->f->dev_loss_tmo_callbk) i->f->dev_loss_tmo_callbk(rport); } From 253f41bf6ec0c40f6364bdf211f7f7661667e4f8 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Fri, 18 Sep 2009 12:02:05 -0500 Subject: [PATCH 440/670] lpfc: fix hang on SGI ia64 platform commit 8e68597d087977d3e4fd3e735d290ab45fd0b5ea upstream. In testing 2.6.31 on one of our ia64 platforms I've encountered a hang due to the driver using hardware ATEs which are a limited resource. This is because the driver does not set the dma consistent mask to 64 bits. Signed-off-by: Michael Reed Acked-by: James Smart Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/lpfc/lpfc_init.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f913f1e93635..549bc7d8a361 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -4384,9 +4384,13 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba) pdev = phba->pcidev; /* Set the device DMA mask size */ - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0 + || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0 + || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) { return error; + } + } /* Get the bus address of Bar0 and Bar2 and the number of bytes * required by each mapping. @@ -5940,9 +5944,13 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) pdev = phba->pcidev; /* Set the device DMA mask size */ - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0 + || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0 + || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) { return error; + } + } /* Get the bus address of SLI4 device Bar0, Bar1, and Bar2 and the * number of bytes required by each mapping. They are actually From 1e418b2888ac64de29659d693d70614583d30ddf Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Wed, 21 Oct 2009 16:26:45 -0700 Subject: [PATCH 441/670] libfc: fix typo in retry check on received PRLI commit 85b5893ca97c69e409ecbb5ee90a5d99882369c4 upstream. A received Fibre Channel ELS PRLI request contains a bit that indicates whether the remote port supports certain retry processing sequences. The test for this bit was somehow coded to use multiply instead of AND! This case would apply only for target mode operation, and it is unlikely to be noticed as an initiator. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libfc/fc_rport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 03ea6748e7ee..bdc973278d8d 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1402,7 +1402,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, break; case FC_TYPE_FCP: fcp_parm = ntohl(rspp->spp_params); - if (fcp_parm * FCP_SPPF_RETRY) + if (fcp_parm & FCP_SPPF_RETRY) rdata->flags |= FC_RP_FLAGS_RETRY; rdata->supported_classes = FC_COS_CLASS3; if (fcp_parm & FCP_SPPF_INIT_FCN) From 34556a180553c21a2f4a935d8eb9c84d857df61c Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 21 Oct 2009 16:26:50 -0700 Subject: [PATCH 442/670] libfc: fix ddp in fc_fcp for 0 xid commit 5e472d077f45de4f37365171bd742f18b3ef20de upstream. xid 0 was used as an indication of invalid xid before but now xid 0 can be used as a valid exchange i. This patch fixes the ddp completion in fcp layer, i.e., in fc_fcp.c:fc_fcp_ddp_done() function, to make sure it does not use xid 0 for indication of an invalid xid, instead, it now uses use FC_XID_UNKNOWN for such indication. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libfc/fc_fcp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 59a4408b27b5..e6c6f4742368 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -302,10 +302,13 @@ static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) if (!fsp) return; + if (fsp->xfer_ddp == FC_XID_UNKNOWN) + return; + lp = fsp->lp; - if (fsp->xfer_ddp && lp->tt.ddp_done) { + if (lp->tt.ddp_done) { fsp->xfer_len = lp->tt.ddp_done(lp, fsp->xfer_ddp); - fsp->xfer_ddp = 0; + fsp->xfer_ddp = FC_XID_UNKNOWN; } } @@ -1708,6 +1711,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) fsp->cmd = sc_cmd; /* save the cmd */ fsp->lp = lp; /* save the softc ptr */ fsp->rport = rport; /* set the remote port ptr */ + fsp->xfer_ddp = FC_XID_UNKNOWN; sc_cmd->scsi_done = done; /* From d5d72dafd7513b5413e409d1c3618230713c882c Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 21 Oct 2009 16:26:55 -0700 Subject: [PATCH 443/670] fcoe: remove redundant checking of netdev->netdev_ops commit b04d023cf5b7f4113cc4a09405c2fe8003bfe37d upstream. Remove the redundant checking of netdev->netdev_ops as it will never be NULL. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/fcoe/fcoe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 704b8e034946..7c898875838f 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -664,7 +664,7 @@ static int fcoe_ddp_setup(struct fc_lport *lp, u16 xid, { struct net_device *n = fcoe_netdev(lp); - if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup) + if (n->netdev_ops->ndo_fcoe_ddp_setup) return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc); return 0; @@ -681,7 +681,7 @@ static int fcoe_ddp_done(struct fc_lport *lp, u16 xid) { struct net_device *n = fcoe_netdev(lp); - if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done) + if (n->netdev_ops->ndo_fcoe_ddp_done) return n->netdev_ops->ndo_fcoe_ddp_done(n, xid); return 0; } From 56320f6e40141bfbe46168083e0760e07aabe926 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 21 Oct 2009 16:27:12 -0700 Subject: [PATCH 444/670] libfc: Fix wrong scsi return status under FC_DATA_UNDRUN commit 4347fa66878e079766258bc0d077c350cb31a799 upstream. This bug is exposed when there is a link flap in LLD. Particularly, when it happens right after a SCSI write command is sent out, no FCP_DATA is sent, causing fsp->status_code to be set as FC_DATA_UNDRUN in fc_fcp_complete_locked even no SCSI status is received. Consequently, fc_io_compl treats this as DID_OK. This results in SCSI returning successful to the initial I/O request even there is no DATA actually sent. Particularly, if you run an I/O tool w/ data verification on, the read back for verification is gonna fail. This is fixed here by checking when FC_DATA_UNDRUN happens, SCSI status is received w/ FC_SRB_RCV_STATUS set in fsp->state. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libfc/fc_fcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index e6c6f4742368..15389dd013b1 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1850,7 +1850,8 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) * scsi status is good but transport level * underrun. */ - sc_cmd->result = DID_OK << 16; + sc_cmd->result = (fsp->state & FC_SRB_RCV_STATUS ? + DID_OK : DID_ERROR) << 16; } else { /* * scsi got underrun, this is an error From 83d236b7272f68e8a7736894970a6d283c74d415 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Wed, 21 Oct 2009 16:27:17 -0700 Subject: [PATCH 445/670] libfc: lport: fix minor documentation errors commit 1b69bc062c2a4c8f3e15ac69f487afec3aa8d774 upstream. Fix minor errors. A debug message said an RLIR was received instead of ECHO. "Expected" was misspelled in several places. Fix a type cast from u32 to __be32. Rob, Some of these may have been also taken care of in your other doc cleanup patch. Feel free to fold them in. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libfc/fc_lport.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index bd2f77197447..eefe87d8efb3 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -329,7 +329,7 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) * @sp: current sequence in the RLIR exchange * @fp: RLIR request frame * - * Locking Note: The lport lock is exected to be held before calling + * Locking Note: The lport lock is expected to be held before calling * this function. */ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, @@ -348,7 +348,7 @@ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, * @sp: current sequence in the ECHO exchange * @fp: ECHO request frame * - * Locking Note: The lport lock is exected to be held before calling + * Locking Note: The lport lock is expected to be held before calling * this function. */ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, @@ -361,7 +361,7 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, void *dp; u32 f_ctl; - FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", + FC_LPORT_DBG(lport, "Received ECHO request while in state %s\n", fc_lport_state(lport)); len = fr_len(in_fp) - sizeof(struct fc_frame_header); @@ -374,7 +374,7 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, if (fp) { dp = fc_frame_payload_get(fp, len); memcpy(dp, pp, len); - *((u32 *)dp) = htonl(ELS_LS_ACC << 24); + *((__be32 *)dp) = htonl(ELS_LS_ACC << 24); sp = lport->tt.seq_start_next(sp); f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, @@ -385,12 +385,12 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_echo_req() - Handle received Request Node ID data request - * @lport: Fibre Channel local port recieving the RNID - * @sp: current sequence in the RNID exchange - * @fp: RNID request frame + * fc_lport_recv_rnid_req() - Handle received Request Node ID data request + * @sp: The sequence in the RNID exchange + * @fp: The RNID request frame + * @lport: The local port recieving the RNID * - * Locking Note: The lport lock is exected to be held before calling + * Locking Note: The lport lock is expected to be held before calling * this function. */ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, @@ -667,7 +667,7 @@ static void fc_lport_enter_ready(struct fc_lport *lport) * Accept it with the common service parameters indicating our N port. * Set up to do a PLOGI if we have the higher-number WWPN. * - * Locking Note: The lport lock is exected to be held before calling + * Locking Note: The lport lock is expected to be held before calling * this function. */ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, From 7c8a0dc2b096fb9acf7dea76cc7935da8aeb711d Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Wed, 21 Oct 2009 16:27:22 -0700 Subject: [PATCH 446/670] libfc: don't WARN_ON in lport_timeout for RESET state commit 22655ac22289d7b7def8ef2d72eafe5024bd57fe upstream. It's possible and harmless to get FLOGI timeouts while in RESET state. Don't do a WARN_ON in that case. Also, split out the other WARN_ONs in fc_lport_timeout, so we can tell which one is hit by its line number. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libfc/fc_lport.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index eefe87d8efb3..0d19ffa88716 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1237,10 +1237,13 @@ static void fc_lport_timeout(struct work_struct *work) switch (lport->state) { case LPORT_ST_DISABLED: - case LPORT_ST_READY: - case LPORT_ST_RESET: WARN_ON(1); break; + case LPORT_ST_READY: + WARN_ON(1); + break; + case LPORT_ST_RESET: + break; case LPORT_ST_FLOGI: fc_lport_enter_flogi(lport); break; From 88cc93a1148a8a2f56a556a4f511837056556c4e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 21 Oct 2009 16:27:44 -0700 Subject: [PATCH 447/670] fcoe: initialize return value in fcoe_destroy commit 8eca355fa8af660557fbdd5506bde1392eee9bfe upstream. When doing echo ethX > /sys..../destroy I am getting errors when the tear down succeeds. It looks like the reason for this is because the rc var is not getting set when the destruction works. This just sets it to zero. Signed-off-by: Mike Christie Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/fcoe/fcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 7c898875838f..8702c8d728dd 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1631,7 +1631,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) { struct fcoe_interface *fcoe; struct net_device *netdev; - int rc; + int rc = 0; mutex_lock(&fcoe_config_mutex); #ifdef CONFIG_FCOE_MODULE From 4c40dbe52412690b4a686e4e6c1625f19cb8c6c6 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Wed, 21 Oct 2009 16:27:58 -0700 Subject: [PATCH 448/670] libfc: Fix frags in frame exceeding SKB_MAX_FRAGS in fc_fcp_send_data commit d37322a43ebac79eef417149f5696390cf8872db upstream. In case of sequence offload, in fc_fcp_send_data(), the skb_fill_page_info() called may end up adding more frags to the skb_shinfo(fp_skb(fp))->frags[], exceeding SKB_MAX_FRAGS, this eventually corrupts the memory. I am adding the FR_FRAME_SG_LEN back, but as SKB_MAX_FRAGS -1, leaving 1 for our fcoe_eof_crc page. And send will be broken into multiple large sends if the frame already contains more frags than skb handle. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libfc/fc_fcp.c | 3 ++- include/scsi/fc_frame.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 15389dd013b1..0ed341653986 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -575,7 +575,8 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, tlen -= sg_bytes; remaining -= sg_bytes; - if (tlen) + if ((skb_shinfo(fp_skb(fp))->nr_frags < FC_FRAME_SG_LEN) && + (tlen)) continue; /* diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h index c35d2383cc26..148126dcf9e9 100644 --- a/include/scsi/fc_frame.h +++ b/include/scsi/fc_frame.h @@ -37,6 +37,9 @@ #define FC_FRAME_HEADROOM 32 /* headroom for VLAN + FCoE headers */ #define FC_FRAME_TAILROOM 8 /* trailer space for FCoE */ +/* Max number of skb frags allowed, reserving one for fcoe_crc_eof page */ +#define FC_FRAME_SG_LEN (MAX_SKB_FRAGS - 1) + #define fp_skb(fp) (&((fp)->skb)) #define fr_hdr(fp) ((fp)->skb.data) #define fr_len(fp) ((fp)->skb.len) From a3d46ca93e4625246a89e62c913ba60742d7bc70 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Wed, 21 Oct 2009 16:28:09 -0700 Subject: [PATCH 449/670] libfc: fix memory corruption caused by double frees and bad error handling commit 8f550f937e9fdafa5c37e348e214aecec851ef3f upstream. I was running into several different panics under stress, which I traced down to a few different possible slab corruption issues in error handling paths. I have not yet looked into why these exchange sends fail, but with these fixes my test system is much more stable under stress than before. fc_elsct_send() could fail and either leave the passed in frame intact (failure in fc_ct/els_fill) or the frame could have been freed if the failure was is fc_exch_seq_send(). The caller had no way of knowing, and there was a potential double free in the error handling in fc_fcp_rec(). Make fc_elsct_send() always free the frame before returning, and remove the fc_frame_free() call in fc_fcp_rec(). While fc_exch_seq_send() did always consume the frame, there were double free bugs in the error handling of fc_fcp_cmd_send() and fc_fcp_srr() as well. Numerous calls to error handling routines (fc_disc_error(), fc_lport_error(), fc_rport_error_retry() ) were passing in a frame pointer that had already been freed in the case of an error. I have changed the call sites to pass in a NULL pointer, but there may be more appropriate error codes to use. Question: Why do these error routines take a frame pointer anyway? I understand passing in a pointer encoded error to the response handlers, but the error routines take no action on a valid pointer and should never be called that way. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libfc/fc_disc.c | 2 +- drivers/scsi/libfc/fc_elsct.c | 4 +++- drivers/scsi/libfc/fc_fcp.c | 7 ++----- drivers/scsi/libfc/fc_lport.c | 8 ++++---- drivers/scsi/libfc/fc_rport.c | 10 +++++----- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index c48799e9dd8e..d4cb3f9b1a0d 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -371,7 +371,7 @@ static void fc_disc_gpn_ft_req(struct fc_disc *disc) disc, lport->e_d_tov)) return; err: - fc_disc_error(disc, fp); + fc_disc_error(disc, NULL); } /** diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index 5cfa68732e9d..92984587ff4d 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -53,8 +53,10 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport, did = FC_FID_DIR_SERV; } - if (rc) + if (rc) { + fc_frame_free(fp); return NULL; + } fc_fill_fc_hdr(fp, r_ctl, did, fc_host_port_id(lport->host), fh_type, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 0ed341653986..5f443d799642 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1052,7 +1052,6 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp, seq = lp->tt.exch_seq_send(lp, fp, resp, fc_fcp_pkt_destroy, fsp, 0); if (!seq) { - fc_frame_free(fp); rc = -1; goto unlock; } @@ -1317,7 +1316,6 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */ return; } - fc_frame_free(fp); retry: if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); @@ -1565,10 +1563,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) seq = lp->tt.exch_seq_send(lp, fp, fc_fcp_srr_resp, NULL, fsp, jiffies_to_msecs(FC_SCSI_REC_TOV)); - if (!seq) { - fc_frame_free(fp); + if (!seq) goto retry; - } + fsp->recov_seq = seq; fsp->xfer_len = offset; fsp->xfer_contig_end = offset; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 0d19ffa88716..536492ae6a88 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1115,7 +1115,7 @@ static void fc_lport_enter_scr(struct fc_lport *lport) if (!lport->tt.elsct_send(lport, FC_FID_FCTRL, fp, ELS_SCR, fc_lport_scr_resp, lport, lport->e_d_tov)) - fc_lport_error(lport, fp); + fc_lport_error(lport, NULL); } /** @@ -1186,7 +1186,7 @@ static void fc_lport_enter_rpn_id(struct fc_lport *lport) if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RPN_ID, fc_lport_rpn_id_resp, lport, lport->e_d_tov)) - fc_lport_error(lport, fp); + fc_lport_error(lport, NULL); } static struct fc_rport_operations fc_lport_rport_ops = { @@ -1340,7 +1340,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport) if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_LOGO, fc_lport_logo_resp, lport, lport->e_d_tov)) - fc_lport_error(lport, fp); + fc_lport_error(lport, NULL); } /** @@ -1456,7 +1456,7 @@ void fc_lport_enter_flogi(struct fc_lport *lport) if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_FLOGI, fc_lport_flogi_resp, lport, lport->e_d_tov)) - fc_lport_error(lport, fp); + fc_lport_error(lport, NULL); } /* Configure a fc_lport */ diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index bdc973278d8d..cfad856b1495 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -632,7 +632,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI, fc_rport_plogi_resp, rdata, lport->e_d_tov)) - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, NULL); else kref_get(&rdata->kref); } @@ -793,7 +793,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI, fc_rport_prli_resp, rdata, lport->e_d_tov)) - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, NULL); else kref_get(&rdata->kref); } @@ -889,7 +889,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, fc_rport_rtv_resp, rdata, lport->e_d_tov)) - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, NULL); else kref_get(&rdata->kref); } @@ -919,7 +919,7 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, fc_rport_logo_resp, rdata, lport->e_d_tov)) - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, NULL); else kref_get(&rdata->kref); } @@ -1006,7 +1006,7 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) } if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC, fc_rport_adisc_resp, rdata, lport->e_d_tov)) - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, NULL); else kref_get(&rdata->kref); } From 407590ad18fa9f3c6561bda1caa04cdcdec9fe1f Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Wed, 21 Oct 2009 16:28:30 -0700 Subject: [PATCH 450/670] libfc: fix free of fc_rport_priv with timer pending commit b4a9c7ede96e90f7b1ec009ce7256059295e76df upstream. Timer crashes were caused by freeing a struct fc_rport_priv with a timer pending, causing the timer facility list to be corrupted. This was during FC uplink flap tests with a lot of targets. After discovery, we were doing an PLOGI on an rdata that was in DELETE state but not yet removed from the lookup list. This moved the rdata from DELETE state to PLOGI state. If the PLOGI exchange allocation failed and needed to be retried, the timer scheduling could race with the free being done by fc_rport_work(). When fc_rport_login() is called on a rport in DELETE state, move it to a new state RESTART. In fc_rport_work, when handling a LOGO, STOPPED or FAILED event, look for restart state. In the RESTART case, don't take the rdata off the list and after the transport remote port is deleted and exchanges are reset, re-login to the remote port. Note that the new RESTART state also corrects a problem we had when re-discovering a port that had moved to DELETE state. In that case, a new rdata was created, but the old rdata would do an exchange manager reset affecting the FC_ID for both the new rdata and old rdata. With the new state, the new port isn't logged into until after any old exchanges are reset. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libfc/fc_rport.c | 69 +++++++++++++++++++++++++---------- include/scsi/libfc.h | 1 + 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index cfad856b1495..6784bef3acfa 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -86,6 +86,7 @@ static const char *fc_rport_state_names[] = { [RPORT_ST_LOGO] = "LOGO", [RPORT_ST_ADISC] = "ADISC", [RPORT_ST_DELETE] = "Delete", + [RPORT_ST_RESTART] = "Restart", }; /** @@ -99,8 +100,7 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, struct fc_rport_priv *rdata; list_for_each_entry(rdata, &lport->disc.rports, peers) - if (rdata->ids.port_id == port_id && - rdata->rp_state != RPORT_ST_DELETE) + if (rdata->ids.port_id == port_id) return rdata; return NULL; } @@ -235,6 +235,7 @@ static void fc_rport_work(struct work_struct *work) struct fc_rport_operations *rport_ops; struct fc_rport_identifiers ids; struct fc_rport *rport; + int restart = 0; mutex_lock(&rdata->rp_mutex); event = rdata->event; @@ -287,8 +288,19 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); if (port_id != FC_FID_DIR_SERV) { + /* + * We must drop rp_mutex before taking disc_mutex. + * Re-evaluate state to allow for restart. + * A transition to RESTART state must only happen + * while disc_mutex is held and rdata is on the list. + */ mutex_lock(&lport->disc.disc_mutex); - list_del(&rdata->peers); + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state == RPORT_ST_RESTART) + restart = 1; + else + list_del(&rdata->peers); + mutex_unlock(&rdata->rp_mutex); mutex_unlock(&lport->disc.disc_mutex); } @@ -312,7 +324,13 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); fc_remote_port_delete(rport); } - kref_put(&rdata->kref, lport->tt.rport_destroy); + if (restart) { + mutex_lock(&rdata->rp_mutex); + FC_RPORT_DBG(rdata, "work restart\n"); + fc_rport_enter_plogi(rdata); + mutex_unlock(&rdata->rp_mutex); + } else + kref_put(&rdata->kref, lport->tt.rport_destroy); break; default: @@ -342,6 +360,12 @@ int fc_rport_login(struct fc_rport_priv *rdata) FC_RPORT_DBG(rdata, "ADISC port\n"); fc_rport_enter_adisc(rdata); break; + case RPORT_ST_RESTART: + break; + case RPORT_ST_DELETE: + FC_RPORT_DBG(rdata, "Restart deleted port\n"); + fc_rport_state_enter(rdata, RPORT_ST_RESTART); + break; default: FC_RPORT_DBG(rdata, "Login to port\n"); fc_rport_enter_plogi(rdata); @@ -397,20 +421,21 @@ int fc_rport_logoff(struct fc_rport_priv *rdata) if (rdata->rp_state == RPORT_ST_DELETE) { FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); - mutex_unlock(&rdata->rp_mutex); goto out; } - fc_rport_enter_logo(rdata); + if (rdata->rp_state == RPORT_ST_RESTART) + FC_RPORT_DBG(rdata, "Port in Restart state, deleting\n"); + else + fc_rport_enter_logo(rdata); /* * Change the state to Delete so that we discard * the response. */ fc_rport_enter_delete(rdata, RPORT_EV_STOP); - mutex_unlock(&rdata->rp_mutex); - out: + mutex_unlock(&rdata->rp_mutex); return 0; } @@ -466,6 +491,7 @@ static void fc_rport_timeout(struct work_struct *work) case RPORT_ST_READY: case RPORT_ST_INIT: case RPORT_ST_DELETE: + case RPORT_ST_RESTART: break; } @@ -499,6 +525,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) fc_rport_enter_logo(rdata); break; case RPORT_ST_DELETE: + case RPORT_ST_RESTART: case RPORT_ST_READY: case RPORT_ST_INIT: break; @@ -1248,6 +1275,7 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, } break; case RPORT_ST_PRLI: + case RPORT_ST_RTV: case RPORT_ST_READY: case RPORT_ST_ADISC: FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d " @@ -1255,11 +1283,14 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, /* XXX TBD - should reset */ break; case RPORT_ST_DELETE: - default: - FC_RPORT_DBG(rdata, "Received PLOGI in unexpected state %d\n", - rdata->rp_state); - fc_frame_free(rx_fp); - goto out; + case RPORT_ST_LOGO: + case RPORT_ST_RESTART: + FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n", + fc_rport_state(rdata)); + mutex_unlock(&rdata->rp_mutex); + rjt_data.reason = ELS_RJT_BUSY; + rjt_data.explan = ELS_EXPL_NONE; + goto reject; } /* @@ -1510,14 +1541,14 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", fc_rport_state(rdata)); + fc_rport_enter_delete(rdata, RPORT_EV_LOGO); + /* - * If the remote port was created due to discovery, - * log back in. It may have seen a stale RSCN about us. + * If the remote port was created due to discovery, set state + * to log back in. It may have seen a stale RSCN about us. */ - if (rdata->rp_state != RPORT_ST_DELETE && rdata->disc_id) - fc_rport_enter_plogi(rdata); - else - fc_rport_enter_delete(rdata, RPORT_EV_LOGO); + if (rdata->disc_id) + fc_rport_state_enter(rdata, RPORT_ST_RESTART); mutex_unlock(&rdata->rp_mutex); } else FC_RPORT_ID_DBG(lport, sid, diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 65dc9aacbf70..09a124b9e465 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -145,6 +145,7 @@ enum fc_rport_state { RPORT_ST_LOGO, /* port logout sent */ RPORT_ST_ADISC, /* Discover Address sent */ RPORT_ST_DELETE, /* port being deleted */ + RPORT_ST_RESTART, /* remote port being deleted and will restart */ }; /** From 2792e0ceb2452e55269443158a6076a721d7556b Mon Sep 17 00:00:00 2001 From: Abhijeet Joglekar Date: Thu, 10 Dec 2009 09:59:20 -0800 Subject: [PATCH 451/670] libfc: remote port gets stuck in restart state without really restarting commit 5543c72e2bbb30e5ba5938b18ec26617b8b3fb04 upstream. We ran into a scenario where a remote port goes into RESTART state, but never gets added to scsi transport. The running vmcore showed the following: a) Port was in RESTART state b) rdata->event was STOP c) no work gets scheduled for the remote work to fc_rport_work After this point, shut/no-shut of the remote port did not cause the port to get re-discovered. The port would move betwen DELETE and RESTART states, but the event would always be STOP, no work would get scheduled to fc_rport_work and the port would not get added to scsi_transport. The problem is that rdata->event is not set to NONE after a port is restarted. After this point, no more work gets scheduled for the remote port since new work is scheduled only if rdata->event is non-NONE. So, the event and state keep changing, but fc_rport_work does not get scheduled to actually handle the event. Here's a transition of states that explains the above observation: ) Port is first in READY State, event is NONE 2) RSCN on shut, port goes to DELETED, event is stop 3) Before fc_rport_work runs, RSCN on no-shut, port goes to RESTART, event is still STOP 4) fc_rport_work gets scheduled, removes the port from transport, sees state as RESTART, begins the PLOGI state machine, event remains as STOP (event NOT changed to NONE, this is the bug) 5) Plogi state machine completes, port state goes to READY, event goes to READY, but no work is scheduled since event was STOP (non-NONE) before. Fc_rport_work is not scheduled, port remains in READY state, but is not added to transport. Things are broken at this point. Libfc rport is ready, but no transport rport created. 6) now a shut causes port state to change to DELETE, event to change to STOP, no work gets scheduled 7) no-shut causes port state to change to RESTART, event remains at STOP, no work gets scheduled (6) and (7) now get repeated everytime we do shut/no-shut. No way to get out of this state. Fcc reset does not help too. Only way to get out is to load/unload module. Fix is to set rdata->event to NONE while processing the STOP/LOGO/FAILED events, inside the discovery and rport locks. Signed-off-by: Abhijeet Joglekar Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/libfc/fc_rport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6784bef3acfa..ff558a631d17 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -300,6 +300,7 @@ static void fc_rport_work(struct work_struct *work) restart = 1; else list_del(&rdata->peers); + rdata->event = RPORT_EV_NONE; mutex_unlock(&rdata->rp_mutex); mutex_unlock(&lport->disc.disc_mutex); } From e166cb138dbfffc03d49ece03d27e9855db00f63 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Thu, 15 Oct 2009 17:46:55 -0700 Subject: [PATCH 452/670] fcoe, libfc: fix an libfc issue with queue ramp down in libfc commit 14caf44c69184ed72d46a2f883311daf27a4192f upstream. The cmd_per_lun value is used by scsi-ml as fall back lowest queue_depth value but in case of libfc cmd_per_lun is set to same value as max queue_depth = 32. So this patch reduces cmd_per_lun value to 3 and configures each lun with default max queue_depth 32 in fc_slave_alloc. Signed-off-by: Vasu Dev Acked-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/fcoe/fcoe.c | 2 +- drivers/scsi/libfc/fc_fcp.c | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 8702c8d728dd..5226fdac11f7 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -137,7 +137,7 @@ static struct scsi_host_template fcoe_shost_template = { .change_queue_depth = fc_change_queue_depth, .change_queue_type = fc_change_queue_type, .this_id = -1, - .cmd_per_lun = 32, + .cmd_per_lun = 3, .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS, .use_clustering = ENABLE_CLUSTERING, .sg_tablesize = SG_ALL, diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 5f443d799642..7a144026b49b 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -2049,18 +2049,16 @@ EXPORT_SYMBOL(fc_eh_host_reset); int fc_slave_alloc(struct scsi_device *sdev) { struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); - int queue_depth; if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; - if (sdev->tagged_supported) { - if (sdev->host->hostt->cmd_per_lun) - queue_depth = sdev->host->hostt->cmd_per_lun; - else - queue_depth = FC_FCP_DFLT_QUEUE_DEPTH; - scsi_activate_tcq(sdev, queue_depth); - } + if (sdev->tagged_supported) + scsi_activate_tcq(sdev, FC_FCP_DFLT_QUEUE_DEPTH); + else + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), + FC_FCP_DFLT_QUEUE_DEPTH); + return 0; } EXPORT_SYMBOL(fc_slave_alloc); From 1ce03481ed022f32b3912ec780388f40eff9cec2 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 3 Nov 2009 11:49:38 -0800 Subject: [PATCH 453/670] fcoe: Fix checking san mac address commit bf361707c81f8e8e43e332bfc8838bae76ae021a upstream. This was fixed before in 7a7f0c7 but it's introduced again recently. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/fcoe/fcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 5226fdac11f7..36f16a0bcf17 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -176,7 +176,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, rcu_read_lock(); for_each_dev_addr(netdev, ha) { if ((ha->type == NETDEV_HW_ADDR_T_SAN) && - (is_valid_ether_addr(fip->ctl_src_addr))) { + (is_valid_ether_addr(ha->addr))) { memcpy(fip->ctl_src_addr, ha->addr, ETH_ALEN); fip->spma = 1; break; From 7c0798e2892bd16487e19ac87300013e3f7ec9e6 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 3 Nov 2009 11:49:43 -0800 Subject: [PATCH 454/670] fcoe: Fix getting san mac for VLAN interface commit 5bab87e6d465d54a2b5899e0f583d42f00dbee2e upstream. Make sure we are get the SAN MAC address from the real netdev if the input netdev is a VLAN device. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/fcoe/fcoe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 36f16a0bcf17..70ab5d0c5a48 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -160,6 +160,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, { struct fcoe_ctlr *fip = &fcoe->ctlr; struct netdev_hw_addr *ha; + struct net_device *real_dev; u8 flogi_maddr[ETH_ALEN]; fcoe->netdev = netdev; @@ -173,8 +174,10 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, /* look for SAN MAC address, if multiple SAN MACs exist, only * use the first one for SPMA */ + real_dev = (netdev->priv_flags & IFF_802_1Q_VLAN) ? + vlan_dev_real_dev(netdev) : netdev; rcu_read_lock(); - for_each_dev_addr(netdev, ha) { + for_each_dev_addr(real_dev, ha) { if ((ha->type == NETDEV_HW_ADDR_T_SAN) && (is_valid_ether_addr(ha->addr))) { memcpy(fip->ctl_src_addr, ha->addr, ETH_ALEN); From ffd1fabc743060f589b1510f9b385d8c9bf0ffca Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 10 Oct 2009 09:35:03 +0000 Subject: [PATCH 455/670] qlge: Remove explicit setting of PCI Dev CTL reg. commit 1d1023d039d8295070b8dbb92c4d972237235304 upstream. Remove explicit setting of error reporting bits. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/qlge/qlge_main.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index a2fc70a0d0cc..1d8f195c3153 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3868,8 +3868,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, struct net_device *ndev, int cards_found) { struct ql_adapter *qdev = netdev_priv(ndev); - int pos, err = 0; - u16 val16; + int err = 0; memset((void *)qdev, 0, sizeof(*qdev)); err = pci_enable_device(pdev); @@ -3881,19 +3880,6 @@ static int __devinit ql_init_device(struct pci_dev *pdev, qdev->ndev = ndev; qdev->pdev = pdev; pci_set_drvdata(pdev, ndev); - pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (pos <= 0) { - dev_err(&pdev->dev, PFX "Cannot find PCI Express capability, " - "aborting.\n"); - return pos; - } else { - pci_read_config_word(pdev, pos + PCI_EXP_DEVCTL, &val16); - val16 &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; - val16 |= (PCI_EXP_DEVCTL_CERE | - PCI_EXP_DEVCTL_NFERE | - PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); - pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, val16); - } err = pci_request_regions(pdev, DRV_NAME); if (err) { From 836750ba4928d6af719bedcd338fe471fd440c6a Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 10 Oct 2009 09:35:04 +0000 Subject: [PATCH 456/670] qlge: Set PCIE max read request size. commit bc9167f39ff8cd428e8577eb72751a653008edb2 upstream. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/qlge/qlge_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 1d8f195c3153..0c6ceecfd547 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3881,6 +3881,13 @@ static int __devinit ql_init_device(struct pci_dev *pdev, qdev->pdev = pdev; pci_set_drvdata(pdev, ndev); + /* Set PCIe read request size */ + err = pcie_set_readrq(pdev, 4096); + if (err) { + dev_err(&pdev->dev, "Set readrq failed.\n"); + goto err_out; + } + err = pci_request_regions(pdev, DRV_NAME); if (err) { dev_err(&pdev->dev, "PCI region request failed.\n"); From 6055e7f7db45d4488608c47904d84b140eee8639 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 10 Oct 2009 09:35:09 +0000 Subject: [PATCH 457/670] qlge: Don't fail open when port is not initialized. commit 80928860941023bb37e9c61927395d0eb753bc3b upstream. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/qlge/qlge_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 0c6ceecfd547..f42ff310ce5d 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3310,10 +3310,8 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) /* Initialize the port and set the max framesize. */ status = qdev->nic_ops->port_initialize(qdev); - if (status) { - QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); - return status; - } + if (status) + QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); /* Set up the MAC address and frame routing filter. */ status = ql_cam_route_initialize(qdev); From 6b076176f9228c25cac5bdc17af8e4c4d2e687ab Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 10 Oct 2009 09:35:05 +0000 Subject: [PATCH 458/670] qlge: Add handler for DCBX firmware event. commit 91ced682f9de17ebab5fcb2a70b48e372eb43281 upstream. The driver has nothing to do, but this marker prevents the event from showing up 'not handled'. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller Signed-off-by: Brandon Philips Signed-off-by: Greg Kroah-Hartman --- drivers/net/qlge/qlge_mpi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index aec05f266107..32b1e1f41497 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -446,6 +446,9 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) ql_aen_lost(qdev, mbcp); break; + case AEN_DCBX_CHG: + /* Need to support AEN 8110 */ + break; default: QPRINTK(qdev, DRV, ERR, "Unsupported AE %.08x.\n", mbcp->mbox_out[0]); From bf9a88d93ee2cfa44b0cc1ada710e2ef37b5ce0d Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Tue, 17 Nov 2009 11:10:40 +0000 Subject: [PATCH 459/670] qlge: Bonding fix for mode 6. commit 63ae93a19094d88c8ca62543586b20e3a7ff7637 upstream. Allow MAC address to be changed even if device is not up. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller Signed-off-by: Brandon Philips Signed-off-by: Greg Kroah-Hartman --- drivers/net/qlge/qlge_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index f42ff310ce5d..35d896b049fa 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3712,9 +3712,6 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p) struct sockaddr *addr = p; int status; - if (netif_running(ndev)) - return -EBUSY; - if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); From 5172b4b0f1d06dd5cb27f335223131a2f08accb4 Mon Sep 17 00:00:00 2001 From: Song Youquan Date: Fri, 11 Dec 2009 18:42:35 -0500 Subject: [PATCH 460/670] PCI: AER: fix aer inject result in kernel oops commit 46256f83d0d066f99ffde547f27473dfd2a78009 upstream. If the BIOS does not export _OSC to allow OS take over the PCIe AER, the pcie aer driver will not initialize the aer service. However, the aer_inject driver does not check this scenario, which results in a kernel oops when injecting an aer error into OS. For example: BUG: unable to handle kernel NULL pointer dereference at 0000000000000350 IP: [] _spin_lock_irqsave+0xc/0x23 PGD 155c41067 PUD 157fe0067 PMD 0 Oops: 0002 [#1] SMP Pid: 5119, comm: aer-inject Not tainted 2.6.32-rc8-mce #2 RIP: 0010:[] [] _spin_lock_irqsave+0xc/0x23 RSP: 0018:ffff880157f81e28 EFLAGS: 00010096 RAX: 0000000000000296 RBX: 0000000000000000 RCX: 0000000000000100 RDX: 0000000000010000 RSI: 0000000000000246 RDI: 0000000000000350 RBP: ffff880157f81e28 R08: 0000000000000004 R09: ffff880157f81dac R10: ffff88015a666f60 R11: ffff88015a666f40 R12: ffff88015758cc00 R13: 0000000000000350 R14: 0000000000000000 R15: 0000000000000100 FS: 00007f4d4a66e6f0(0000) GS:ffff8800282e0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000350 CR3: 000000015661a000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process aer-inject (pid: 5119, threadinfo ffff880157f80000, task ffff8801585f4340) Stack: ffff880157f81e78 ffffffff811b1615 ffff880157f81e78 ffffffff81222823 Call Trace: [] aer_irq+0x38/0x117 [] ? device_for_each_child+0x5f/0x6f [] aer_inject_write+0x409/0x45e [aer_inject] [] vfs_write+0xae/0x16a [] sys_write+0x47/0x6e [] system_call_fastpath+0x16/0x1b RIP [] _spin_lock_irqsave+0xc/0x23 RSP CR2: 0000000000000350 So check the _OSC before assuming that AER is available to the OS. Signed-off-by: Song Youquan Acked-by: Huang Ying Signed-off-by: Jesse Barnes Signed-off-by: Thomas Renninger Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/aer/aer_inject.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 62d15f652bb6..0d91a8a4d278 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -392,8 +392,14 @@ static int aer_inject(struct aer_error_inj *einj) if (ret) goto out_put; - if (find_aer_device(rpdev, &edev)) + if (find_aer_device(rpdev, &edev)) { + if (!get_service_data(edev)) { + printk(KERN_WARNING "AER service is not initialized\n"); + ret = -EINVAL; + goto out_put; + } aer_irq(-1, edev); + } else ret = -EINVAL; out_put: From 44d13be6ecdafef19772d84a290c6c9d53787db8 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Dec 2009 10:24:19 -0800 Subject: [PATCH 461/670] DMI: allow omitting ident strings in DMI tables commit 75757507e014fa074d25d2883c4ab604999584bd upstream. The purpose of dmi->ident is twofold - it may be used by DMI callback functions when composing log messages; it is also used to determine end of DMI table in dmi_check_system() and dmi_first_match(). However, in case when callbacks are not interested in using ident at all it just wastes memory. Let's make entries with empty first match slot serve as end-of-table markers instead. [needed for DMI table changes that need to be done by later patches - gkh] Acked-by: Jean Delvare Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dmi_scan.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 938100f14b16..3a2ccb09e2f8 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -429,7 +429,7 @@ static bool dmi_matches(const struct dmi_system_id *dmi) for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) { int s = dmi->matches[i].slot; if (s == DMI_NONE) - continue; + break; if (dmi_ident[s] && strstr(dmi_ident[s], dmi->matches[i].substr)) continue; @@ -439,6 +439,15 @@ static bool dmi_matches(const struct dmi_system_id *dmi) return true; } +/** + * dmi_is_end_of_table - check for end-of-table marker + * @dmi: pointer to the dmi_system_id structure to check + */ +static bool dmi_is_end_of_table(const struct dmi_system_id *dmi) +{ + return dmi->matches[0].slot == DMI_NONE; +} + /** * dmi_check_system - check system DMI data * @list: array of dmi_system_id structures to match against @@ -457,7 +466,7 @@ int dmi_check_system(const struct dmi_system_id *list) int count = 0; const struct dmi_system_id *d; - for (d = list; d->ident; d++) + for (d = list; !dmi_is_end_of_table(d); d++) if (dmi_matches(d)) { count++; if (d->callback && d->callback(d)) @@ -484,7 +493,7 @@ const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list) { const struct dmi_system_id *d; - for (d = list; d->ident; d++) + for (d = list; !dmi_is_end_of_table(d); d++) if (dmi_matches(d)) return d; From f6278f11ca471e406868b636cbc2d9a65f6ee29f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Dec 2009 10:24:19 -0800 Subject: [PATCH 462/670] Input: i8042 - remove identification strings from DMI tables commit f909b1df0a068f30e252d8dc3e9d45ca25bf266f upstream. The driver does not reference identification strings in DMI tables and since these strings are no longer required by DMI core we can safely remove them and save some memory. Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/i8042-x86ia64io.h | 143 ++++++++++++-------------- 1 file changed, 66 insertions(+), 77 deletions(-) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2bcf1ace27c0..7fbffe431bc5 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -67,10 +67,12 @@ static inline void i8042_write_command(int val) #include -static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { +static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { { - /* AUX LOOP command does not raise AUX IRQ */ - .ident = "Arima-Rioworks HDAMB", + /* + * Arima-Rioworks HDAMB - + * AUX LOOP command does not raise AUX IRQ + */ .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"), DMI_MATCH(DMI_BOARD_NAME, "HDAMB"), @@ -78,7 +80,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - .ident = "ASUS G1S", + /* ASUS G1S */ .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), DMI_MATCH(DMI_BOARD_NAME, "G1S"), @@ -86,8 +88,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - /* AUX LOOP command does not raise AUX IRQ */ - .ident = "ASUS P65UP5", + /* ASUS P65UP5 - AUX LOOP command does not raise AUX IRQ */ .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), DMI_MATCH(DMI_BOARD_NAME, "P/I-P65UP5"), @@ -95,7 +96,6 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - .ident = "Compaq Proliant 8500", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), @@ -103,7 +103,6 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - .ident = "Compaq Proliant DL760", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), @@ -111,7 +110,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - .ident = "OQO Model 01", + /* OQO Model 01 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "OQO"), DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), @@ -119,8 +118,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - /* AUX LOOP does not work properly */ - .ident = "ULI EV4873", + /* ULI EV4873 - AUX LOOP does not work properly */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ULI"), DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"), @@ -128,7 +126,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - .ident = "Microsoft Virtual Machine", + /* Microsoft Virtual Machine */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), @@ -136,7 +134,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - .ident = "Medion MAM 2070", + /* Medion MAM 2070 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"), @@ -144,7 +142,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - .ident = "Blue FB5601", + /* Blue FB5601 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "blue"), DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"), @@ -152,7 +150,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - .ident = "Gigabyte M912", + /* Gigabyte M912 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), DMI_MATCH(DMI_PRODUCT_NAME, "M912"), @@ -160,7 +158,6 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { }, }, { - .ident = "HP DV9700", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), @@ -177,72 +174,72 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { * ... apparently some Toshibas don't like MUX mode either and * die horrible death on reboot. */ -static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { +static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { { - .ident = "Fujitsu Lifebook P7010/P7010D", + /* Fujitsu Lifebook P7010/P7010D */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), DMI_MATCH(DMI_PRODUCT_NAME, "P7010"), }, }, { - .ident = "Fujitsu Lifebook P7010", + /* Fujitsu Lifebook P7010 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"), }, }, { - .ident = "Fujitsu Lifebook P5020D", + /* Fujitsu Lifebook P5020D */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"), }, }, { - .ident = "Fujitsu Lifebook S2000", + /* Fujitsu Lifebook S2000 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"), }, }, { - .ident = "Fujitsu Lifebook S6230", + /* Fujitsu Lifebook S6230 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"), }, }, { - .ident = "Fujitsu T70H", + /* Fujitsu T70H */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"), }, }, { - .ident = "Fujitsu-Siemens Lifebook T3010", + /* Fujitsu-Siemens Lifebook T3010 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"), }, }, { - .ident = "Fujitsu-Siemens Lifebook E4010", + /* Fujitsu-Siemens Lifebook E4010 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"), }, }, { - .ident = "Fujitsu-Siemens Amilo Pro 2010", + /* Fujitsu-Siemens Amilo Pro 2010 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"), }, }, { - .ident = "Fujitsu-Siemens Amilo Pro 2030", + /* Fujitsu-Siemens Amilo Pro 2030 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"), @@ -253,7 +250,7 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { * No data is coming from the touchscreen unless KBC * is in legacy mode. */ - .ident = "Panasonic CF-29", + /* Panasonic CF-29 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), @@ -261,10 +258,10 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { }, { /* - * Errors on MUX ports are reported without raising AUXDATA + * HP Pavilion DV4017EA - + * errors on MUX ports are reported without raising AUXDATA * causing "spurious NAK" messages. */ - .ident = "HP Pavilion DV4017EA", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"), @@ -272,9 +269,9 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { }, { /* - * Like DV4017EA does not raise AUXERR for errors on MUX ports. + * HP Pavilion ZT1000 - + * like DV4017EA does not raise AUXERR for errors on MUX ports. */ - .ident = "HP Pavilion ZT1000", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), @@ -283,44 +280,41 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { }, { /* - * Like DV4017EA does not raise AUXERR for errors on MUX ports. + * HP Pavilion DV4270ca - + * like DV4017EA does not raise AUXERR for errors on MUX ports. */ - .ident = "HP Pavilion DV4270ca", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"), }, }, { - .ident = "Toshiba P10", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"), }, }, { - .ident = "Toshiba Equium A110", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), }, }, { - .ident = "Alienware Sentia", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"), }, }, { - .ident = "Sharp Actius MM20", + /* Sharp Actius MM20 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "SHARP"), DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), }, }, { - .ident = "Sony Vaio FS-115b", + /* Sony Vaio FS-115b */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), @@ -328,73 +322,72 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { }, { /* - * Reset and GET ID commands issued via KBD port are + * Sony Vaio FZ-240E - + * reset and GET ID commands issued via KBD port are * sometimes being delivered to AUX3. */ - .ident = "Sony Vaio FZ-240E", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"), }, }, { - .ident = "Amoi M636/A737", + /* Amoi M636/A737 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."), DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"), }, }, { - .ident = "Lenovo 3000 n100", + /* Lenovo 3000 n100 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_NAME, "076804U"), }, }, { - .ident = "Acer Aspire 1360", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"), }, }, { - .ident = "Gericom Bellagio", + /* Gericom Bellagio */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Gericom"), DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), }, }, { - .ident = "IBM 2656", + /* IBM 2656 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), DMI_MATCH(DMI_PRODUCT_NAME, "2656"), }, }, { - .ident = "Dell XPS M1530", + /* Dell XPS M1530 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"), }, }, { - .ident = "Compal HEL80I", + /* Compal HEL80I */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"), DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"), }, }, { - .ident = "Dell Vostro 1510", + /* Dell Vostro 1510 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"), }, }, { - .ident = "Acer Aspire 5536", + /* Acer Aspire 5536 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"), @@ -404,65 +397,65 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { { } }; -static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { +static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { { - .ident = "MSI Wind U-100", + /* MSI Wind U-100 */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "U-100"), DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), }, }, { - .ident = "LG Electronics X110", + /* LG Electronics X110 */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "X110"), DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), }, }, { - .ident = "Acer Aspire One 150", + /* Acer Aspire One 150 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), }, }, { - .ident = "Advent 4211", + /* Advent 4211 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"), DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"), }, }, { - .ident = "Medion Akoya Mini E1210", + /* Medion Akoya Mini E1210 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), DMI_MATCH(DMI_PRODUCT_NAME, "E1210"), }, }, { - .ident = "Mivvy M310", + /* Mivvy M310 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), DMI_MATCH(DMI_PRODUCT_NAME, "N10"), }, }, { - .ident = "Dell Vostro 1320", + /* Dell Vostro 1320 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"), }, }, { - .ident = "Dell Vostro 1520", + /* Dell Vostro 1520 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"), }, }, { - .ident = "Dell Vostro 1720", + /* Dell Vostro 1720 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"), @@ -472,16 +465,16 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { }; #ifdef CONFIG_PNP -static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { +static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = { { - .ident = "Intel MBO Desktop D845PESV", + /* Intel MBO Desktop D845PESV */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "D845PESV"), DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), }, }, { - .ident = "MSI Wind U-100", + /* MSI Wind U-100 */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "U-100"), DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), @@ -490,27 +483,23 @@ static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { { } }; -static struct dmi_system_id __initdata i8042_dmi_laptop_table[] = { +static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { { - .ident = "Portable", .matches = { DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ }, }, { - .ident = "Laptop", .matches = { DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */ }, }, { - .ident = "Notebook", .matches = { DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ }, }, { - .ident = "Sub-Notebook", .matches = { DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */ }, @@ -525,58 +514,58 @@ static struct dmi_system_id __initdata i8042_dmi_laptop_table[] = { * Originally, this was just confined to older laptops, but a few Acer laptops * have turned up in 2007 that also need this again. */ -static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { +static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { { - .ident = "Acer Aspire 5630", + /* Acer Aspire 5630 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"), }, }, { - .ident = "Acer Aspire 5650", + /* Acer Aspire 5650 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"), }, }, { - .ident = "Acer Aspire 5680", + /* Acer Aspire 5680 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"), }, }, { - .ident = "Acer Aspire 5720", + /* Acer Aspire 5720 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"), }, }, { - .ident = "Acer Aspire 9110", + /* Acer Aspire 9110 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"), }, }, { - .ident = "Acer TravelMate 660", + /* Acer TravelMate 660 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"), }, }, { - .ident = "Acer TravelMate 2490", + /* Acer TravelMate 2490 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"), }, }, { - .ident = "Acer TravelMate 4280", + /* Acer TravelMate 4280 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"), From 461eb3f6b31f67e16dfaf2e1827d746ebc76a9fc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 13 Dec 2009 00:34:06 -0800 Subject: [PATCH 463/670] Input: i8042 - add Gigabyte M1022M to the noloop list commit a61cd03827eceefcec19eefc6e1173703fdc5e5d upstream. Gigabyte netbook model M1022M requires i8042.noloop, otherwise AUX port will not detected and the touchpad will not work. Unfortunately chassis type in DMI set to "Other" and thus generic laptop entry does not fire on it. Reported-by: Darryl Bond Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/i8042-x86ia64io.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 7fbffe431bc5..64b688daf48a 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -157,6 +157,14 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "01"), }, }, + { + /* Gigabyte M1022M netbook */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "M1022E"), + DMI_MATCH(DMI_BOARD_VERSION, "1.02"), + }, + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), From d16061056a95ac864354c4c743f3ab77f027a287 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sun, 10 Jan 2010 23:59:05 -0800 Subject: [PATCH 464/670] Input: i8042 - add Dritek quirk for Acer Aspire 5610. commit e6edbdc52bc0755cbfe0721ca91d4fd87649bc13 upstream. Signed-off-by: Elliott Sales de Andrade Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 64b688daf48a..2a5982e532f8 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -523,6 +523,13 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { * have turned up in 2007 that also need this again. */ static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { + { + /* Acer Aspire 5610 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), + }, + }, { /* Acer Aspire 5630 */ .matches = { From a2c5952e122f124c273280ee9a7ad6db44874ee4 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 30 Oct 2009 11:34:19 +0100 Subject: [PATCH 465/670] ALSA: hda - select IbexPeak handler for Calpella commit 739b47f1e5aa3b36eadd7906cc6b41f0175c6ed1 upstream. An earlier patch merely adds id for 0x80862804. It has 2/3 cvt/pin nodes and shall be tied to the IbexPeak handler. Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_intelhdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 01a18ed475ac..7c23016fe8fa 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c @@ -684,7 +684,7 @@ static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi }, { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi }, { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi }, - { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi }, + { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi_ibexpeak }, { .id = 0x80860054, .name = "Q57 DEVIBX", .patch = patch_intel_hdmi_ibexpeak }, { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, {} /* terminator */ From 9049580626c076943f5f8b7e90c0a2fa4b8ca2f4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 18 Dec 2009 08:48:42 +0100 Subject: [PATCH 466/670] ALSA: hda - Fix quirk for Maxdata obook4-1 commit 2fef62c825f09e29d2f52dc187ddf6f99e28c7f1 upstream. Works fine with the auto-parser. Reference: Novell bnc#564940 https://bugzilla.novell.com/show_bug.cgi?id=564940 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 075c3a678e2e..f50d1b1f7ec9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -8839,7 +8839,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ - SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG), + SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO), SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG), From 4220098f176347efd6916bf73112975e092bbef3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 8 Dec 2009 12:36:52 +0100 Subject: [PATCH 467/670] ALSA: hda - Add missing Line-Out and PCM switches as slave commit 23033b2bce4361f2859ee0331f97c9056dae7091 upstream. Realtek codecs may have "PCM" and "Line-Out" playback switches, and they can be slaves for vmaster. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f50d1b1f7ec9..cdada8695fb3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2401,6 +2401,8 @@ static const char *alc_slave_sws[] = { "Speaker Playback Switch", "Mono Playback Switch", "IEC958 Playback Switch", + "Line-Out Playback Switch", + "PCM Playback Switch", NULL, }; From 53691f222670765b843035aff24952d471d68d00 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sun, 15 Nov 2009 13:44:54 +0000 Subject: [PATCH 468/670] iTCO_wdt.c - cleanup chipset documentation commit cb711a1931363b8ad4dc98df4a92c262ced8eeb4 upstream. Cleanup the documentation about the supported chipsets. [needed for further device ids to add to this driver - gkh] Signed-off-by: Wim Van Sebroeck Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/iTCO_wdt.c | 61 +++++++++++-------------------------- 1 file changed, 17 insertions(+), 44 deletions(-) diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 4bd3877ad895..e44fbb31bc6f 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -1,5 +1,5 @@ /* - * intel TCO Watchdog Driver (Used in i82801 and i63xxESB chipsets) + * intel TCO Watchdog Driver * * (c) Copyright 2006-2009 Wim Van Sebroeck . * @@ -14,49 +14,22 @@ * * The TCO watchdog is implemented in the following I/O controller hubs: * (See the intel documentation on http://developer.intel.com.) - * 82801AA (ICH) : document number 290655-003, 290677-014, - * 82801AB (ICHO) : document number 290655-003, 290677-014, - * 82801BA (ICH2) : document number 290687-002, 298242-027, - * 82801BAM (ICH2-M) : document number 290687-002, 298242-027, - * 82801CA (ICH3-S) : document number 290733-003, 290739-013, - * 82801CAM (ICH3-M) : document number 290716-001, 290718-007, - * 82801DB (ICH4) : document number 290744-001, 290745-025, - * 82801DBM (ICH4-M) : document number 252337-001, 252663-008, - * 82801E (C-ICH) : document number 273599-001, 273645-002, - * 82801EB (ICH5) : document number 252516-001, 252517-028, - * 82801ER (ICH5R) : document number 252516-001, 252517-028, - * 6300ESB (6300ESB) : document number 300641-004, 300884-013, - * 82801FB (ICH6) : document number 301473-002, 301474-026, - * 82801FR (ICH6R) : document number 301473-002, 301474-026, - * 82801FBM (ICH6-M) : document number 301473-002, 301474-026, - * 82801FW (ICH6W) : document number 301473-001, 301474-026, - * 82801FRW (ICH6RW) : document number 301473-001, 301474-026, - * 631xESB (631xESB) : document number 313082-001, 313075-006, - * 632xESB (632xESB) : document number 313082-001, 313075-006, - * 82801GB (ICH7) : document number 307013-003, 307014-024, - * 82801GR (ICH7R) : document number 307013-003, 307014-024, - * 82801GDH (ICH7DH) : document number 307013-003, 307014-024, - * 82801GBM (ICH7-M) : document number 307013-003, 307014-024, - * 82801GHM (ICH7-M DH) : document number 307013-003, 307014-024, - * 82801GU (ICH7-U) : document number 307013-003, 307014-024, - * 82801HB (ICH8) : document number 313056-003, 313057-017, - * 82801HR (ICH8R) : document number 313056-003, 313057-017, - * 82801HBM (ICH8M) : document number 313056-003, 313057-017, - * 82801HH (ICH8DH) : document number 313056-003, 313057-017, - * 82801HO (ICH8DO) : document number 313056-003, 313057-017, - * 82801HEM (ICH8M-E) : document number 313056-003, 313057-017, - * 82801IB (ICH9) : document number 316972-004, 316973-012, - * 82801IR (ICH9R) : document number 316972-004, 316973-012, - * 82801IH (ICH9DH) : document number 316972-004, 316973-012, - * 82801IO (ICH9DO) : document number 316972-004, 316973-012, - * 82801IBM (ICH9M) : document number 316972-004, 316973-012, - * 82801IEM (ICH9M-E) : document number 316972-004, 316973-012, - * 82801JIB (ICH10) : document number 319973-002, 319974-002, - * 82801JIR (ICH10R) : document number 319973-002, 319974-002, - * 82801JD (ICH10D) : document number 319973-002, 319974-002, - * 82801JDO (ICH10DO) : document number 319973-002, 319974-002, - * 5 Series (PCH) : document number 322169-001, 322170-001, - * 3400 Series (PCH) : document number 322169-001, 322170-001 + * document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO) + * document number 290687-002, 298242-027: 82801BA (ICH2) + * document number 290733-003, 290739-013: 82801CA (ICH3-S) + * document number 290716-001, 290718-007: 82801CAM (ICH3-M) + * document number 290744-001, 290745-025: 82801DB (ICH4) + * document number 252337-001, 252663-008: 82801DBM (ICH4-M) + * document number 273599-001, 273645-002: 82801E (C-ICH) + * document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R) + * document number 300641-004, 300884-013: 6300ESB + * document number 301473-002, 301474-026: 82801F (ICH6) + * document number 313082-001, 313075-006: 631xESB, 632xESB + * document number 307013-003, 307014-024: 82801G (ICH7) + * document number 313056-003, 313057-017: 82801H (ICH8) + * document number 316972-004, 316973-012: 82801I (ICH9) + * document number 319973-002, 319974-002: 82801J (ICH10) + * document number 322169-001, 322170-001: 5 Series, 3400 Series (PCH) */ /* From 42b4505ad420b9788d25ff02c4182a6754eef050 Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Mon, 7 Dec 2009 20:42:26 +0100 Subject: [PATCH 469/670] iTCO_wdt: add PCI ID for the Intel EP80579 (Tolapai) SoC commit 4946f8353da9d3038e2a9d0295d5dfeee4cee5c5 upstream. add PCI ID for the Intel EP80579 (Tolapai) SoC Signed-off-by: Imre Kaloz Signed-off-by: Wim Van Sebroeck Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/iTCO_wdt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index e44fbb31bc6f..c8a3bec26830 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -30,6 +30,7 @@ * document number 316972-004, 316973-012: 82801I (ICH9) * document number 319973-002, 319974-002: 82801J (ICH10) * document number 322169-001, 322170-001: 5 Series, 3400 Series (PCH) + * document number 320066-003, 320257-008: EP80597 (IICH) */ /* @@ -100,6 +101,7 @@ enum iTCO_chipsets { TCO_PCH, /* PCH Desktop Full Featured */ TCO_PCHM, /* PCH Mobile Full Featured */ TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ + TCO_EP80579, /* EP80579 */ }; static struct { @@ -143,6 +145,7 @@ static struct { {"PCH Desktop Full Featured", 2}, {"PCH Mobile Full Featured", 2}, {"PCH Mobile SFF Full Featured", 2}, + {"EP80579", 2}, {NULL, 0} }; @@ -214,6 +217,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x3b00, TCO_PCH)}, { ITCO_PCI_DEVICE(0x3b01, TCO_PCHM)}, { ITCO_PCI_DEVICE(0x3b0d, TCO_PCHMSFF)}, + { ITCO_PCI_DEVICE(0x5031, TCO_EP80579)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); From c817c1975bd7d46bc8af3ccacde8d86353bed02a Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Thu, 14 Jan 2010 20:58:05 +0000 Subject: [PATCH 470/670] iTCO_wdt: Add Intel Cougar Point and PCH DeviceIDs commit 3c9d8eccd8687f0e770e4d89fd0d73d4f81a985a upstream. This patch adds the Intel Cougar Point and PCH DeviceIDs for iTCO Watchdog. Signed-off-by: Seth Heasley Signed-off-by: Wim Van Sebroeck Acked-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/iTCO_wdt.c | 45 ++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index c8a3bec26830..4bdb7f1a9077 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -29,8 +29,9 @@ * document number 313056-003, 313057-017: 82801H (ICH8) * document number 316972-004, 316973-012: 82801I (ICH9) * document number 319973-002, 319974-002: 82801J (ICH10) - * document number 322169-001, 322170-001: 5 Series, 3400 Series (PCH) + * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) * document number 320066-003, 320257-008: EP80597 (IICH) + * document number TBD : Cougar Point (CPT) */ /* @@ -100,8 +101,22 @@ enum iTCO_chipsets { TCO_ICH10DO, /* ICH10DO */ TCO_PCH, /* PCH Desktop Full Featured */ TCO_PCHM, /* PCH Mobile Full Featured */ + TCO_P55, /* P55 */ + TCO_PM55, /* PM55 */ + TCO_H55, /* H55 */ + TCO_QM57, /* QM57 */ + TCO_H57, /* H57 */ + TCO_HM55, /* HM55 */ + TCO_Q57, /* Q57 */ + TCO_HM57, /* HM57 */ TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ + TCO_QS57, /* QS57 */ + TCO_3400, /* 3400 */ + TCO_3420, /* 3420 */ + TCO_3450, /* 3450 */ TCO_EP80579, /* EP80579 */ + TCO_CPTD, /* CPT Desktop */ + TCO_CPTM, /* CPT Mobile */ }; static struct { @@ -144,8 +159,22 @@ static struct { {"ICH10DO", 2}, {"PCH Desktop Full Featured", 2}, {"PCH Mobile Full Featured", 2}, + {"P55", 2}, + {"PM55", 2}, + {"H55", 2}, + {"QM57", 2}, + {"H57", 2}, + {"HM55", 2}, + {"Q57", 2}, + {"HM57", 2}, {"PCH Mobile SFF Full Featured", 2}, + {"QS57", 2}, + {"3400", 2}, + {"3420", 2}, + {"3450", 2}, {"EP80579", 2}, + {"CPT Desktop", 2}, + {"CPT Mobile", 2}, {NULL, 0} }; @@ -216,8 +245,22 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x3a14, TCO_ICH10DO)}, { ITCO_PCI_DEVICE(0x3b00, TCO_PCH)}, { ITCO_PCI_DEVICE(0x3b01, TCO_PCHM)}, + { ITCO_PCI_DEVICE(0x3b02, TCO_P55)}, + { ITCO_PCI_DEVICE(0x3b03, TCO_PM55)}, + { ITCO_PCI_DEVICE(0x3b06, TCO_H55)}, + { ITCO_PCI_DEVICE(0x3b07, TCO_QM57)}, + { ITCO_PCI_DEVICE(0x3b08, TCO_H57)}, + { ITCO_PCI_DEVICE(0x3b09, TCO_HM55)}, + { ITCO_PCI_DEVICE(0x3b0a, TCO_Q57)}, + { ITCO_PCI_DEVICE(0x3b0b, TCO_HM57)}, { ITCO_PCI_DEVICE(0x3b0d, TCO_PCHMSFF)}, + { ITCO_PCI_DEVICE(0x3b0f, TCO_QS57)}, + { ITCO_PCI_DEVICE(0x3b12, TCO_3400)}, + { ITCO_PCI_DEVICE(0x3b14, TCO_3420)}, + { ITCO_PCI_DEVICE(0x3b16, TCO_3450)}, { ITCO_PCI_DEVICE(0x5031, TCO_EP80579)}, + { ITCO_PCI_DEVICE(0x1c42, TCO_CPTD)}, + { ITCO_PCI_DEVICE(0x1c43, TCO_CPTM)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); From 3de08a120ab3ac85bfc31e03b5d2dc2758a3bd21 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 16 Nov 2009 09:56:05 +0800 Subject: [PATCH 471/670] ahci: disable SNotification capability for ich8 commit 1b677afda44f7882b7e257d6f025d006ec5d14f9 upstream. I obseved there is a sata_async_notification() for every ahci interrupt. But the async notification does nothing (this is hard disk drive and no pmp). This cause cpu wastes some time on sntf register access. It appears ICH AHCI doesn't support SNotification register, but the controller reports it does. After quirking it, the async notification disappears. PS. it appears all ICH don't support SNotification register from ICH manual, don't know if we need quirk all ICH. I don't have machines with all kinds of ICH. Signed-off-by: Shaohua Li Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a3241a1a710b..9519c777af83 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -113,6 +113,7 @@ enum { board_ahci_mcp65 = 6, board_ahci_nopmp = 7, board_ahci_yesncq = 8, + board_ahci_nosntf = 9, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -235,6 +236,7 @@ enum { AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */ AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as link offline */ + AHCI_HFLAG_NO_SNTF = (1 << 12), /* no sntf */ /* ap->flags bits */ @@ -508,7 +510,7 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, - /* board_ahci_yesncq */ + [board_ahci_yesncq] = { AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), .flags = AHCI_FLAG_COMMON, @@ -516,6 +518,14 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, + [board_ahci_nosntf] = + { + AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, }; static const struct pci_device_id ahci_pci_tbl[] = { @@ -531,7 +541,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ - { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */ + { PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */ { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ @@ -849,6 +859,12 @@ static void ahci_save_initial_config(struct pci_dev *pdev, cap &= ~HOST_CAP_PMP; } + if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) { + dev_printk(KERN_INFO, &pdev->dev, + "controller can't do SNTF, turning off CAP_SNTF\n"); + cap &= ~HOST_CAP_SNTF; + } + if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 && port_map != 1) { dev_printk(KERN_INFO, &pdev->dev, From 31cf6d8a86469e96cf4ea0a0a89b87ddef1a65cc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 3 Dec 2009 20:32:08 +0100 Subject: [PATCH 472/670] ata_piix: fix MWDMA handling on PIIX3 commit 6938594374ee506e91a4c03117a034ea0ed66783 upstream. Fix erroneous check for ap->udma_mask in do_pata_set_dmamode() resulting in controller not being programmed properly for MWDMA. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ata_piix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 9ac4e378992e..0c6155f51173 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -869,10 +869,10 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in (timings[pio][1] << 8); } - if (ap->udma_mask) { + if (ap->udma_mask) udma_enable &= ~(1 << devid); - pci_write_config_word(dev, master_port, master_data); - } + + pci_write_config_word(dev, master_port, master_data); } /* Don't scribble on 0x48 if the controller does not support UDMA */ if (ap->udma_mask) From 2928b68f6294139ffbd2138440ce08efeaf23d15 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 30 Dec 2009 12:08:50 +1100 Subject: [PATCH 473/670] md: fix small irregularity with start_ro module parameter commit 0f9552b5dc4fe10da37fa3f4a4ca185d90fa41c9 upstream. The start_ro modules parameter can be used to force arrays to be started in 'auto-readonly' in which they are read-only until the first write. This ensures that no resync/recovery happens until something else writes to the device. This is important for resume-from-disk off an md array. However if an array is started 'readonly' (by writing 'readonly' to the 'array_state' sysfs attribute) we want it to be really 'readonly', not 'auto-readonly'. So strengthen the condition to only set auto-readonly if the array is not already read-only. Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index c6a6685b0806..08f7471d0150 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4173,7 +4173,7 @@ static int do_md_run(mddev_t * mddev) mddev->barriers_work = 1; mddev->ok_start_degraded = start_dirty_degraded; - if (start_readonly) + if (start_readonly && mddev->ro == 0) mddev->ro = 2; /* read-only, but switch on first write */ err = mddev->pers->run(mddev); From da0297498ee0e4a73ac74beae564dc72abbe6f48 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 22:31:21 -0300 Subject: [PATCH 474/670] V4L/DVB (13826): uvcvideo: Fix controls blacklisting commit 385097e08b9c24655626ed760bc67eb7e50115a0 upstream. The control blacklisting code erroneously used usb_match_id() by passing a pointer to a usb_device_id structure instead of an array of such structures. Replace the usb_match_id() call by usb_match_id_one(). Thanks to Paulo Assis for diagnosing the bug and providing an initial fix. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/uvc/uvc_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 1b89735e62fd..4a293b444459 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -1405,7 +1405,7 @@ uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity) size = entity->processing.bControlSize; for (i = 0; i < ARRAY_SIZE(blacklist); ++i) { - if (!usb_match_id(dev->intf, &blacklist[i].id)) + if (!usb_match_one_id(dev->intf, &blacklist[i].id)) continue; if (blacklist[i].index >= 8 * size || From f5b1bc5470c2871fda157d55bc27746422b7112c Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 7 Dec 2009 12:51:15 +0100 Subject: [PATCH 475/670] cio: fix double free in case of probe failure commit 48e4c385c5f54626651cca027afe242439281899 upstream. io_subchannel_probe() frees memory for sch->private which is later freed again when io_subchannel_remove() is called. Fix this problem by removing the cleanup in io_subchannel_probe(). Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- drivers/s390/cio/device.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 2490b741e16a..55f997308e42 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1292,7 +1292,7 @@ static int io_subchannel_probe(struct subchannel *sch) sch->private = kzalloc(sizeof(struct io_subchannel_private), GFP_KERNEL | GFP_DMA); if (!sch->private) - goto out_err; + goto out_schedule; /* * First check if a fitting device may be found amongst the * disconnected devices or in the orphanage. @@ -1317,7 +1317,7 @@ static int io_subchannel_probe(struct subchannel *sch) } cdev = io_subchannel_create_ccwdev(sch); if (IS_ERR(cdev)) - goto out_err; + goto out_schedule; rc = io_subchannel_recog(cdev, sch); if (rc) { spin_lock_irqsave(sch->lock, flags); @@ -1325,9 +1325,7 @@ static int io_subchannel_probe(struct subchannel *sch) spin_unlock_irqrestore(sch->lock, flags); } return 0; -out_err: - kfree(sch->private); - sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); + out_schedule: io_subchannel_schedule_removal(sch); return 0; @@ -1341,13 +1339,14 @@ io_subchannel_remove (struct subchannel *sch) cdev = sch_get_cdev(sch); if (!cdev) - return 0; + goto out_free; /* Set ccw device to not operational and drop reference. */ spin_lock_irqsave(cdev->ccwlock, flags); sch_set_cdev(sch, NULL); cdev->private->state = DEV_STATE_NOT_OPER; spin_unlock_irqrestore(cdev->ccwlock, flags); ccw_device_unregister(cdev); +out_free: kfree(sch->private); sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); return 0; From 27aeefb33617d3307a6627483f67d07ebda8b184 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 7 Dec 2009 12:51:24 +0100 Subject: [PATCH 476/670] cio: dont panic in non-fatal conditions commit 16b9a0571da4ee5cd15ca75e871722b0b5aee64d upstream. Remove the call to BUG() for situations which are unexpected but do not cause actual problems. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- drivers/s390/cio/device_fsm.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index b9613d7df9ef..13b703a9d63f 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -1080,14 +1080,14 @@ void ccw_device_trigger_reprobe(struct ccw_device *cdev) ccw_device_start_id(cdev, 0); } -static void -ccw_device_offline_irq(struct ccw_device *cdev, enum dev_event dev_event) +static void ccw_device_disabled_irq(struct ccw_device *cdev, + enum dev_event dev_event) { struct subchannel *sch; sch = to_subchannel(cdev->dev.parent); /* - * An interrupt in state offline means a previous disable was not + * An interrupt in a disabled state means a previous disable was not * successful - should not happen, but we try to disable again. */ cio_disable_subchannel(sch); @@ -1149,26 +1149,13 @@ ccw_device_nop(struct ccw_device *cdev, enum dev_event dev_event) { } -/* - * Bug operation action. - */ -static void -ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event) -{ - CIO_MSG_EVENT(0, "Internal state [%i][%i] not handled for device " - "0.%x.%04x\n", cdev->private->state, dev_event, - cdev->private->dev_id.ssid, - cdev->private->dev_id.devno); - BUG(); -} - /* * device statemachine */ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { [DEV_STATE_NOT_OPER] = { [DEV_EVENT_NOTOPER] = ccw_device_nop, - [DEV_EVENT_INTERRUPT] = ccw_device_bug, + [DEV_EVENT_INTERRUPT] = ccw_device_disabled_irq, [DEV_EVENT_TIMEOUT] = ccw_device_nop, [DEV_EVENT_VERIFY] = ccw_device_nop, }, @@ -1186,7 +1173,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { }, [DEV_STATE_OFFLINE] = { [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, - [DEV_EVENT_INTERRUPT] = ccw_device_offline_irq, + [DEV_EVENT_INTERRUPT] = ccw_device_disabled_irq, [DEV_EVENT_TIMEOUT] = ccw_device_nop, [DEV_EVENT_VERIFY] = ccw_device_offline_verify, }, @@ -1243,7 +1230,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { [DEV_STATE_DISCONNECTED] = { [DEV_EVENT_NOTOPER] = ccw_device_nop, [DEV_EVENT_INTERRUPT] = ccw_device_start_id, - [DEV_EVENT_TIMEOUT] = ccw_device_bug, + [DEV_EVENT_TIMEOUT] = ccw_device_nop, [DEV_EVENT_VERIFY] = ccw_device_start_id, }, [DEV_STATE_DISCONNECTED_SENSE_ID] = { From a5981dfb82297858395742530509c7f80a41e3bd Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Thu, 12 Nov 2009 21:46:30 +0000 Subject: [PATCH 477/670] netiucv: displayed TX bytes value much too high commit 998221c26b86a7edd621e66b437628c5ec0f8e9b upstream. tx_bytes value must be updated by skb length before skb is freed. Signed-off-by: Ursula Braun Signed-off-by: David S. Miller Acked-by: John Jolly Signed-off-by: Greg Kroah-Hartman --- drivers/s390/net/netiucv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index c84eadd3602a..395c04c2b00f 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -741,13 +741,13 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg) if (single_flag) { if ((skb = skb_dequeue(&conn->commit_queue))) { atomic_dec(&skb->users); - dev_kfree_skb_any(skb); if (privptr) { privptr->stats.tx_packets++; privptr->stats.tx_bytes += (skb->len - NETIUCV_HDRLEN - - NETIUCV_HDRLEN); + - NETIUCV_HDRLEN); } + dev_kfree_skb_any(skb); } } conn->tx_buff->data = conn->tx_buff->head; From a0dffef3213a314d3a53e4fffe7d325edbe1d05c Mon Sep 17 00:00:00 2001 From: "Serge E. Hallyn" Date: Tue, 15 Dec 2009 16:47:27 -0800 Subject: [PATCH 478/670] ipc ns: fix memory leak (idr) commit 7d6feeb287c61aafa88f06345387b1188edf4b86 upstream. We have apparently had a memory leak since 7ca7e564e049d8b350ec9d958ff25eaa24226352 "ipc: store ipcs into IDRs" in 2007. The idr of which 3 exist for each ipc namespace is never freed. This patch simply frees them when the ipcns is freed. I don't believe any idr_remove() are done from rcu (and could therefore be delayed until after this idr_destroy()), so the patch should be safe. Some quick testing showed no harm, and the memory leak fixed. Caught by kmemleak. Signed-off-by: Serge E. Hallyn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Acked-by: Nick Piggin Signed-off-by: Greg Kroah-Hartman --- ipc/msg.c | 1 + ipc/sem.c | 1 + ipc/shm.c | 1 + 3 files changed, 3 insertions(+) diff --git a/ipc/msg.c b/ipc/msg.c index 2ceab7f12fcb..779f7622ebcb 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -125,6 +125,7 @@ void msg_init_ns(struct ipc_namespace *ns) void msg_exit_ns(struct ipc_namespace *ns) { free_ipcs(ns, &msg_ids(ns), freeque); + idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr); } #endif diff --git a/ipc/sem.c b/ipc/sem.c index 87c2b641fd7b..2f2a47959576 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -129,6 +129,7 @@ void sem_init_ns(struct ipc_namespace *ns) void sem_exit_ns(struct ipc_namespace *ns) { free_ipcs(ns, &sem_ids(ns), freeary); + idr_destroy(&ns->ids[IPC_SEM_IDS].ipcs_idr); } #endif diff --git a/ipc/shm.c b/ipc/shm.c index 11bec626c228..e9b039f74129 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -101,6 +101,7 @@ static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) void shm_exit_ns(struct ipc_namespace *ns) { free_ipcs(ns, &shm_ids(ns), do_shm_rmid); + idr_destroy(&ns->ids[IPC_SHM_IDS].ipcs_idr); } #endif From 00bd133151947ffd56beef6159c5d2a2b7d02def Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Jan 2010 08:35:06 +0100 Subject: [PATCH 479/670] ALSA: hda - Fix HP T5735 automute commit dc99be47667c56046555e89e62f1ac17fa06329a upstream. This patch fixes the aut-mute setup on HP T5735 with ALC262 codec. Instead of wrong amp, use pin control toggling for muting the speaker now. Tested-by: Lee Trager Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cdada8695fb3..c2e937038412 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10154,7 +10154,7 @@ static void alc262_hp_t5735_setup(struct hda_codec *codec) struct alc_spec *spec = codec->spec; spec->autocfg.hp_pins[0] = 0x15; - spec->autocfg.speaker_pins[0] = 0x0c; /* HACK: not actually a pin */ + spec->autocfg.speaker_pins[0] = 0x14; } static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = { @@ -11588,9 +11588,9 @@ static struct alc_config_preset alc262_presets[] = { .num_channel_mode = ARRAY_SIZE(alc262_modes), .channel_mode = alc262_modes, .input_mux = &alc262_capture_source, - .unsol_event = alc_automute_amp_unsol_event, + .unsol_event = alc_sku_unsol_event, .setup = alc262_hp_t5735_setup, - .init_hook = alc_automute_amp, + .init_hook = alc_inithook, }, [ALC262_HP_RP5700] = { .mixers = { alc262_hp_rp5700_mixer }, From 4d845d60ad3d385c43716c50fc7c87dd5d3466fe Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 25 Jan 2010 15:00:50 +0100 Subject: [PATCH 480/670] hwmon: (fschmd) Fix a memleak on multiple opens of /dev/watchdog commit c453615f77aa51593c1c9c9031b4278797d3fd19 upstream. When /dev/watchdog gets opened a second time we return -EBUSY, but we already have got a kref then, so we end up leaking our data struct. Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/fschmd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index da1b1f9488af..f600813e2b65 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -767,6 +767,7 @@ static int watchdog_stop(struct fschmd_data *data) static int watchdog_open(struct inode *inode, struct file *filp) { struct fschmd_data *pos, *data = NULL; + int watchdog_is_open; /* We get called from drivers/char/misc.c with misc_mtx hold, and we call misc_register() from fschmd_probe() with watchdog_data_mutex @@ -781,10 +782,12 @@ static int watchdog_open(struct inode *inode, struct file *filp) } } /* Note we can never not have found data, so we don't check for this */ - kref_get(&data->kref); + watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open); + if (!watchdog_is_open) + kref_get(&data->kref); mutex_unlock(&watchdog_data_mutex); - if (test_and_set_bit(0, &data->watchdog_is_open)) + if (watchdog_is_open) return -EBUSY; /* Start the watchdog */ From f6fbe0baa35fd65a4344a48ebc60c08f18a0fc20 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 18 Jan 2010 16:43:44 +0200 Subject: [PATCH 481/670] UBI: fix memory leak in update path commit ebddd63b74dcf1cb676d14328d5852f1fee19a8a upstream. When truncating an UBI volume, UBI should allocates a PEB-sized buffer but does not release it, which leads to memory leaks. This patch fixes the issue. Reported-by: Marek Skuczynski Signed-off-by: Artem Bityutskiy Tested-by: Marek Skuczynski Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/upd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index c1d7b880c795..425bf5a3edd4 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -155,6 +155,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, if (err) return err; vol->updating = 0; + return 0; } vol->upd_buf = vmalloc(ubi->leb_size); From 2cdc2dc3bdf8948ddf5a11d2907ac9d98d1c2794 Mon Sep 17 00:00:00 2001 From: Peter Horton Date: Tue, 5 Jan 2010 11:14:36 +0000 Subject: [PATCH 482/670] UBI: initialise update marker commit ff998793288b49a3b22d929bf8e56362320905ff upstream. The in kernel copy of a volume's update marker is not initialised from the volume table. This means that volumes where an update was unfinnished will not be treated as "forbidden to use". This is basically that the update functionality was broken. Signed-off-by: Peter Horton Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/vtbl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 1afc61e7455d..40044028d682 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -566,6 +566,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs); vol->alignment = be32_to_cpu(vtbl[i].alignment); vol->data_pad = be32_to_cpu(vtbl[i].data_pad); + vol->upd_marker = vtbl[i].upd_marker; vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME; vol->name_len = be16_to_cpu(vtbl[i].name_len); From 09e4d0f1f69726615a2c9c5246410ec72b60b09f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 22 Jan 2010 18:00:03 +0100 Subject: [PATCH 483/670] ASoC: fix a memory-leak in wm8903 commit 40aa7030e5213a43e9e0554fd7f95534ea310bf3 upstream. Remember to free the temporary register-cache. Signed-off-by: Guennadi Liakhovetski Acked-by: Liam Girdwood Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wm8903.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index fe1307b500cf..eedf33c085f3 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1506,7 +1506,7 @@ static int wm8903_resume(struct platform_device *pdev) struct i2c_client *i2c = codec->control_data; int i; u16 *reg_cache = codec->reg_cache; - u16 *tmp_cache = kmemdup(codec->reg_cache, sizeof(wm8903_reg_defaults), + u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), GFP_KERNEL); /* Bring the codec back up to standby first to minimise pop/clicks */ @@ -1518,6 +1518,7 @@ static int wm8903_resume(struct platform_device *pdev) for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++) if (tmp_cache[i] != reg_cache[i]) snd_soc_write(codec, i, tmp_cache[i]); + kfree(tmp_cache); } else { dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); } From 304cd19e41f6c77c3d307869f15a8bfe2a7408cd Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Fri, 15 Jan 2010 12:21:37 +0100 Subject: [PATCH 484/670] mac80211: check that ieee80211_set_power_mgmt only handles STA interfaces. commit e5de30c9bf4a39db9f54c4a373470ce65881ade0 upstream. ieee80211_set_power_mgmt is meant for STA interfaces only. Moreover, since sdata->u.mgd.mtx is only initialized for STA interfaces, using this code for any other type of interface (like creating a monitor interface) will result in a oops. Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/cfg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index cca675e25363..fe2d3f8c5ae7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1306,6 +1306,9 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_conf *conf = &local->hw.conf; + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) return -EOPNOTSUPP; From eb6002526b1c5cb3e7f9e42004ba395f5d57beaf Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 13 Jan 2010 13:23:14 -0800 Subject: [PATCH 485/670] cfg80211: fix channel setting for wext commit 5f6120335c701ba07d5151206071f4d6ccaa684f upstream. Patch fixes the bug at http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2139 Currently we cannot set the channel using wext extension if we have already associated and disconnected. As cfg80211_mgd_wext_siwfreq will not switch the channel if ssid is set. This fixes it by clearing the ssid. Following is the sequence which it tries to fix. modprobe iwlagn iwconfig wlan0 essid "" ifconfig wlan0 down iwconfig wlan0 chan X wext is marked as deprecate.If we use nl80211 we can easily play with setting the channel. Signed-off-by: Abhijeet Kolekar Acked-by: Samuel Ortiz Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/sme.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 9f0b2800a9d7..b2930e32ebad 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -655,6 +655,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, memset(&wrqu, 0, sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + wdev->wext.connect.ssid_len = 0; #endif } From 70be4d76c0e5d426067601a79be0b33ea673f3ff Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 21 Jan 2010 12:19:07 +0100 Subject: [PATCH 486/670] KVM: S390: fix potential array overrun in intercept handling commit 062d5e9b0d714f449b261bb522eadaaf6f00f438 upstream. kvm_handle_sie_intercept uses a jump table to get the intercept handler for a SIE intercept. Static code analysis revealed a potential problem: the intercept_funcs jump table was defined to contain (0x48 >> 2) entries, but we only checked for code > 0x48 which would cause an off-by-one array overflow if code == 0x48. Use the compiler and ARRAY_SIZE to automatically set the limits. Signed-off-by: Christian Borntraeger Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/s390/kvm/intercept.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index ba9d8a7bc1ac..b40096494e46 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -213,7 +213,7 @@ static int handle_instruction_and_prog(struct kvm_vcpu *vcpu) return rc2; } -static const intercept_handler_t intercept_funcs[0x48 >> 2] = { +static const intercept_handler_t intercept_funcs[] = { [0x00 >> 2] = handle_noop, [0x04 >> 2] = handle_instruction, [0x08 >> 2] = handle_prog, @@ -230,7 +230,7 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) intercept_handler_t func; u8 code = vcpu->arch.sie_block->icptcode; - if (code & 3 || code > 0x48) + if (code & 3 || (code >> 2) >= ARRAY_SIZE(intercept_funcs)) return -ENOTSUPP; func = intercept_funcs[code >> 2]; if (func) From f0d13b89d4b12f331a0dd1d646a69060e49b1951 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 13 Jan 2010 18:58:09 +0200 Subject: [PATCH 487/670] KVM: only allow one gsi per fd commit f1d1c309f35e9b0fb961cffd70fbd04f450ec47c upstream. Looks like repeatedly binding same fd to multiple gsi's with irqfd can use up a ton of kernel memory for irqfd structures. A simple fix is to allow each fd to only trigger one gsi: triggering a storm of interrupts in guest is likely useless anyway, and we can do it by binding a single gsi to many interrupts if we really want to. Signed-off-by: Michael S. Tsirkin Acked-by: Acked-by: Gregory Haskins Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- virt/kvm/eventfd.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index bb4ebd89b9ff..251282c43ac8 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -168,7 +168,7 @@ irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh, static int kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi) { - struct _irqfd *irqfd; + struct _irqfd *irqfd, *tmp; struct file *file = NULL; struct eventfd_ctx *eventfd = NULL; int ret; @@ -205,9 +205,20 @@ kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi) init_waitqueue_func_entry(&irqfd->wait, irqfd_wakeup); init_poll_funcptr(&irqfd->pt, irqfd_ptable_queue_proc); + spin_lock_irq(&kvm->irqfds.lock); + + ret = 0; + list_for_each_entry(tmp, &kvm->irqfds.items, list) { + if (irqfd->eventfd != tmp->eventfd) + continue; + /* This fd is used for another irq already. */ + ret = -EBUSY; + spin_unlock_irq(&kvm->irqfds.lock); + goto fail; + } + events = file->f_op->poll(file, &irqfd->pt); - spin_lock_irq(&kvm->irqfds.lock); list_add_tail(&irqfd->list, &kvm->irqfds.items); spin_unlock_irq(&kvm->irqfds.lock); From 59cf8545b9b307b15441f07dec587b7774484789 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 29 Dec 2009 12:42:16 +0200 Subject: [PATCH 488/670] KVM: Fix race between APIC TMR and IRR commit a5d36f82c4f3e852b61fdf1fee13463c8aa91b90 upstream. When we queue an interrupt to the local apic, we set the IRR before the TMR. The vcpu can pick up the IRR and inject the interrupt before setting the TMR, and perhaps even EOI it, causing incorrect behaviour. The race is really insignificant since it can only occur on the first interrupt (usually following interrupts will not change TMR), but it's better closed than open. Fixed by reordering setting the TMR vs IRR. Signed-off-by: Avi Kivity Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/lapic.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 41659fb080ba..8dfeaaa70795 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -374,6 +374,12 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, if (unlikely(!apic_enabled(apic))) break; + if (trig_mode) { + apic_debug("level trig mode for vector %d", vector); + apic_set_vector(vector, apic->regs + APIC_TMR); + } else + apic_clear_vector(vector, apic->regs + APIC_TMR); + result = !apic_test_and_set_irr(vector, apic); trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode, trig_mode, vector, !result); @@ -384,11 +390,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, break; } - if (trig_mode) { - apic_debug("level trig mode for vector %d", vector); - apic_set_vector(vector, apic->regs + APIC_TMR); - } else - apic_clear_vector(vector, apic->regs + APIC_TMR); kvm_vcpu_kick(vcpu); break; From 493821093f18655d39f16e31264c00b022640701 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 14 Jan 2010 17:41:27 -0200 Subject: [PATCH 489/670] KVM: MMU: bail out pagewalk on kvm_read_guest error commit a6085fbaf65ab09bfb5ec8d902d6d21680fe1895 upstream. Exit the guest pagetable walk loop if reading gpte failed. Otherwise its possible to enter an endless loop processing the previous present pte. Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/paging_tmpl.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 85e12cd6fb48..5fa33255348c 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -150,7 +150,9 @@ static int FNAME(walk_addr)(struct guest_walker *walker, walker->table_gfn[walker->level - 1] = table_gfn; walker->pte_gpa[walker->level - 1] = pte_gpa; - kvm_read_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte)); + if (kvm_read_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte))) + goto not_present; + trace_kvm_mmu_paging_element(pte, walker->level); if (!is_present_gpte(pte)) From 0118bac21740345d8b4754da24f6ce1aab4a91bf Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 5 Jan 2010 19:02:28 +0800 Subject: [PATCH 490/670] KVM: x86: Fix host_mapping_level() commit 82b7005f0e72d8d1a8226e4c192cbb0850d10b3f upstream. When found a error hva, should not return PAGE_SIZE but the level... Also clean up the coding style of the following loop. Signed-off-by: Sheng Yang Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/mmu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 818b92ad82cf..3a01519a49f2 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -477,7 +477,7 @@ static int host_mapping_level(struct kvm *kvm, gfn_t gfn) addr = gfn_to_hva(kvm, gfn); if (kvm_is_error_hva(addr)) - return page_size; + return PT_PAGE_TABLE_LEVEL; down_read(¤t->mm->mmap_sem); vma = find_vma(current->mm, addr); @@ -515,11 +515,9 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) if (host_level == PT_PAGE_TABLE_LEVEL) return host_level; - for (level = PT_DIRECTORY_LEVEL; level <= host_level; ++level) { - + for (level = PT_DIRECTORY_LEVEL; level <= host_level; ++level) if (has_wrprotected_page(vcpu->kvm, large_gfn, level)) break; - } return level - 1; } From 8e5c20d09b0003c91a96e35f7117633eefe2545a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 22 Jan 2010 14:18:47 +0800 Subject: [PATCH 491/670] KVM: x86: Fix probable memory leak of vcpu->arch.mce_banks commit 36cb93fd6b6bf7e9163a69a8bf20207aed5fea44 upstream. vcpu->arch.mce_banks is malloc in kvm_arch_vcpu_init(), but never free in any place, this may cause memory leak. So this patch fixed to free it in kvm_arch_vcpu_uninit(). Signed-off-by: Wei Yongjun Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 97b31fa63088..1bd161ed168a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4782,6 +4782,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) { + kfree(vcpu->arch.mce_banks); kvm_free_lapic(vcpu); down_read(&vcpu->kvm->slots_lock); kvm_mmu_destroy(vcpu); From 9801911326462a332d83eb508f1120bd45178426 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 22 Jan 2010 14:21:29 +0800 Subject: [PATCH 492/670] KVM: x86: Fix leak of free lapic date in kvm_arch_vcpu_init() commit 443c39bc9ef7d8f648408d74c97e943f3bb3f48a upstream. In function kvm_arch_vcpu_init(), if the memory malloc for vcpu->arch.mce_banks is fail, it does not free the memory of lapic date. This patch fixed it. Signed-off-by: Wei Yongjun Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1bd161ed168a..6378e0742691 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4766,12 +4766,13 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) GFP_KERNEL); if (!vcpu->arch.mce_banks) { r = -ENOMEM; - goto fail_mmu_destroy; + goto fail_free_lapic; } vcpu->arch.mcg_cap = KVM_MAX_MCE_BANKS; return 0; - +fail_free_lapic: + kvm_free_lapic(vcpu); fail_mmu_destroy: kvm_mmu_destroy(vcpu); fail_free_pio_data: From eaccd490b0128d11ce2ea4d9d89e092661ae90b5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 25 Sep 2009 09:33:38 +0200 Subject: [PATCH 493/670] KVM: fix lock imbalance in kvm_*_irq_source_id() commit 0c6ddcebd8303ada6faefa6f72ac18b6230320c4 upstream. Stanse found 2 lock imbalances in kvm_request_irq_source_id and kvm_free_irq_source_id. They omit to unlock kvm->irq_lock on fail paths. Fix that by adding unlock labels at the end of the functions and jump there from the fail paths. Signed-off-by: Jiri Slaby Cc: Marcelo Tosatti Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- virt/kvm/irq_comm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index 03e5b217e88b..ddc388e565fc 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -209,11 +209,13 @@ int kvm_request_irq_source_id(struct kvm *kvm) if (irq_source_id >= BITS_PER_LONG) { printk(KERN_WARNING "kvm: exhaust allocatable IRQ sources!\n"); - return -EFAULT; + irq_source_id = -EFAULT; + goto unlock; } ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); set_bit(irq_source_id, bitmap); +unlock: mutex_unlock(&kvm->irq_lock); return irq_source_id; @@ -229,11 +231,12 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) if (irq_source_id < 0 || irq_source_id >= BITS_PER_LONG) { printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); - return; + goto unlock; } for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) clear_bit(irq_source_id, &kvm->arch.irq_states[i]); clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); +unlock: mutex_unlock(&kvm->irq_lock); } From 454f8b167c06886ab7d469c889d9cca613398431 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 29 Oct 2009 13:44:17 -0200 Subject: [PATCH 494/670] KVM: only clear irq_source_id if irqchip is present commit e50212bb51356f0df48d6cce0aae5acf41df336d upstream. Otherwise kvm might attempt to dereference a NULL pointer. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- virt/kvm/irq_comm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index ddc388e565fc..5288885637b1 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -233,9 +233,12 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); goto unlock; } + clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); + if (!irqchip_in_kernel(kvm)) + goto unlock; + for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) clear_bit(irq_source_id, &kvm->arch.irq_states[i]); - clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); unlock: mutex_unlock(&kvm->irq_lock); } From 194223f3a9d72ad95eeb85cf15c0bb2262421186 Mon Sep 17 00:00:00 2001 From: "David J. Wilder" Date: Wed, 9 Dec 2009 10:03:00 -0800 Subject: [PATCH 495/670] IPoIB: Clear ipoib_neigh.dgid in ipoib_neigh_alloc() commit 0cd4d0fd9b0a4e10c091fc6316d1bf92885dcd9c upstream. IPoIB can miss a change in destination GID under some conditions. The problem is caused when ipoib_neigh->dgid contains a stale address. The fix is to set ipoib_neigh->dgid to zero in ipoib_neigh_alloc(). This can happen when a system using bonding on its IPoIB interfaces has switched its active interface from interface A to B and back to A. The system that fails over will not correctly processes the 2nd address change, as described below. When an address has changed neighbor->ha is updated with the new address. Each neighbor has an associated ipoib_neigh. ipoib_neigh->dgid also holds a copy of the remote node's hardware address. When an address changes neighbor->ha is updated by the network layer (arp code) with the new address. IPoIB detects this change in ipoib_start_xmit() by comparing neighbor->ha with ipoib_neigh->dgid. The bug is that ipoib_neigh->dgid may already contain the new address (A) thus the change from B to A is missed by ipoib. Here is the sequence of events: ipoib_neigh->dgid = A and neighbor->ha = A The address is switched to B (the first switch) neighbor->ha = B The change is seen in ipoib_start_xmit() -- neighbor->ha != ipoib_neigh->dgid so ipoib_neigh is released, and a new one is allocated. The allocator may return the same chunk of memory that was just released, therefore ipoib_neigh->dgid still contains A at this point. ipoib_neigh->dgid should be updated in neigh_add_path(), but if the following conditions are true dgid is not updated: 1) __path_find() returns a path 2) path->ah is NULL The remote system now switches from address B to A, neighbor->ha is updated to A. Now we have again : ipoib_neigh->dgid = A and neighbor->ha = A Since the addresses are the same ipoib won't process the change in address. Fix this by zeroing out the dgid field when allocating a new struct ipoib_neigh. Signed-off-by: David Wilder Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 2bf5116deec4..df3eb8c9fd96 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -884,6 +884,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour, neigh->neighbour = neighbour; neigh->dev = dev; + memset(&neigh->dgid.raw, 0, sizeof (union ib_gid)); *to_ipoib_neigh(neighbour) = neigh; skb_queue_head_init(&neigh->queue); ipoib_cm_set(neigh, NULL); From 59568be10aaa60db63576671d2b4064428ff2345 Mon Sep 17 00:00:00 2001 From: "Pallipadi, Venkatesh" Date: Thu, 17 Dec 2009 12:27:02 -0800 Subject: [PATCH 496/670] x86: Reenable TSC sync check at boot, even with NONSTOP_TSC commit 6c56ccecf05fafe100ab4ea94f6fccbf5ff00db7 upstream. Commit 83ce4009 did the following change If the TSC is constant and non-stop, also set it reliable. But, there seems to be few systems that will end up with TSC warp across sockets, depending on how the cpus come out of reset. Skipping TSC sync test on such systems may result in time inconsistency later. So, reenable TSC sync test even on constant and non-stop TSC systems. Set, sched_clock_stable to 1 by default and reset it in mark_tsc_unstable, if TSC sync fails. This change still gives perf benefit mentioned in 83ce4009 for systems where TSC is reliable. Signed-off-by: Venkatesh Pallipadi Acked-by: Suresh Siddha LKML-Reference: <20091217202702.GA18015@linux-os.sc.intel.com> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/intel.c | 1 - arch/x86/kernel/tsc.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 40e1835b35e8..a2a03cf4a489 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -70,7 +70,6 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) if (c->x86_power & (1 << 8)) { set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); - set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE); sched_clock_stable = 1; } diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index cd982f48e23e..597683aa5ba0 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -763,6 +763,7 @@ void mark_tsc_unstable(char *reason) { if (!tsc_unstable) { tsc_unstable = 1; + sched_clock_stable = 0; printk(KERN_INFO "Marking TSC unstable due to %s\n", reason); /* Change only the rating, when not registered */ if (clocksource_tsc.mult) From d274df694b319a87405e35553bd2c45ab75f4554 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 26 Jan 2010 16:15:28 -0500 Subject: [PATCH 497/670] ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C upstream in 2.6.33-rc: 5d76b6f6c17572e662f5c99c2023adae92100855 Refreshed here for 2.6.32.y, applies w/ offset back to 2.6.29.y. Linux has always ignored ACPI BIOS C2 with exit latency > 100 usec, and the ACPI spec is clear that is correct FADT-supplied C2. However, the ACPI spec explicitly states that _CST-supplied C-states have no latency limits. So move the 100usec C2 test out of the code shared by FADT and _CST code-paths, and into the FADT-specific path. This bug has not been visible until Nehalem, which advertises a CPU-C2 worst case exit latency on servers of 205usec. That (incorrect) figure is being used by BIOS writers on mobile Nehalem systems for the AC configuration. Thus, Linux ignores C2 leaving just C1, which is saves less power, and also impacts performance by preventing the use of turbo mode. http://bugzilla.kernel.org/show_bug.cgi?id=15064 Tested-by: Alex Chiang Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/processor_idle.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index bbd066e7f854..a8f3ca6f2e1f 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -299,6 +299,17 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; + /* + * FADT specified C2 latency must be less than or equal to + * 100 microseconds. + */ + if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); + /* invalidate C2 */ + pr->power.states[ACPI_STATE_C2].address = 0; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, @@ -494,16 +505,6 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) if (!cx->address) return; - /* - * C2 latency must be less than or equal to 100 - * microseconds. - */ - else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "latency too large [%d]\n", cx->latency)); - return; - } - /* * Otherwise we've met all of our C2 requirements. * Normalize the C2 latency to expidite policy From 01e991b8eb2cc28f41ed3f96ec33ae3dd6b860a3 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 26 Jan 2010 12:00:43 -0800 Subject: [PATCH 498/670] iwlwifi: Fix throughput stall issue in HT mode for 5000 commit 1152dcc28c66a74b5b3f1a3ede0aa6729bfd48e4 upstream Similar to 6000 and 1000 series, RTS/CTS is the recommended protection mechanism for 5000 series in HT mode based on the HW design. Using RTS/CTS will better protect the inner exchange from interference, especially in highly-congested environment, it also prevent uCode encounter TX FIFO underrun and other HT mode related performance issues. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 94a1225f9872..133df70bc609 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1666,6 +1666,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .valid_rx_ant = ANT_ABC, .need_pll_cfg = true, .ht_greenfield_support = true, + .use_rts_for_ht = true, /* use rts/cts protection */ }; struct iwl_cfg iwl5100_bg_cfg = { @@ -1717,6 +1718,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .valid_rx_ant = ANT_AB, .need_pll_cfg = true, .ht_greenfield_support = true, + .use_rts_for_ht = true, /* use rts/cts protection */ }; struct iwl_cfg iwl5350_agn_cfg = { @@ -1734,6 +1736,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .valid_rx_ant = ANT_ABC, .need_pll_cfg = true, .ht_greenfield_support = true, + .use_rts_for_ht = true, /* use rts/cts protection */ }; struct iwl_cfg iwl5150_agn_cfg = { @@ -1751,6 +1754,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .valid_rx_ant = ANT_AB, .need_pll_cfg = true, .ht_greenfield_support = true, + .use_rts_for_ht = true, /* use rts/cts protection */ }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); From 0a1c275a44db55b2624652b04d4ed9430e82957b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 26 Jan 2010 15:04:02 -0800 Subject: [PATCH 499/670] fnctl: f_modown should call write_lock_irqsave/restore commit b04da8bfdfbbd79544cab2fadfdc12e87eb01600 upstream. Commit 703625118069f9f8960d356676662d3db5a9d116 exposed that f_modown() should call write_lock_irqsave instead of just write_lock_irq so that because a caller could have a spinlock held and it would not be good to renable interrupts. Cc: Eric W. Biederman Cc: Al Viro Cc: Alan Cox Cc: Tavis Ormandy Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- fs/fcntl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/fcntl.c b/fs/fcntl.c index 97e01dc0d95f..5ef953e6f908 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -199,7 +199,9 @@ static int setfl(int fd, struct file * filp, unsigned long arg) static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, int force) { - write_lock_irq(&filp->f_owner.lock); + unsigned long flags; + + write_lock_irqsave(&filp->f_owner.lock, flags); if (force || !filp->f_owner.pid) { put_pid(filp->f_owner.pid); filp->f_owner.pid = get_pid(pid); @@ -211,7 +213,7 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, filp->f_owner.euid = cred->euid; } } - write_unlock_irq(&filp->f_owner.lock); + write_unlock_irqrestore(&filp->f_owner.lock, flags); } int __f_setown(struct file *filp, struct pid *pid, enum pid_type type, From a8e96d6f81c39a86449f6a8404450b0cfb1d42fe Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Tue, 26 Jan 2010 20:37:22 -0600 Subject: [PATCH 500/670] x86, msr/cpuid: Pass the number of minors when unregistering MSR and CPUID drivers. commit da482474b8396e1a099c37ffc6541b78775aedb4 upstream. Pass the number of minors when unregistering MSR and CPUID drivers. Reported-by: Dean Nelson Signed-off-by: Dean Nelson LKML-Reference: <20100127023722.GA22305@sgi.com> Signed-off-by: Russ Anderson Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpuid.c | 2 +- arch/x86/kernel/msr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index f8590c509423..0c91110219c0 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -234,7 +234,7 @@ static void __exit cpuid_exit(void) for_each_online_cpu(cpu) cpuid_device_destroy(cpu); class_destroy(cpuid_class); - unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); + __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid"); unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); } diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index b42e63baa8e4..5eaeb5e35c49 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -290,7 +290,7 @@ static void __exit msr_exit(void) for_each_online_cpu(cpu) msr_device_destroy(cpu); class_destroy(msr_class); - unregister_chrdev(MSR_MAJOR, "cpu/msr"); + __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); unregister_hotcpu_notifier(&msr_class_cpu_notifier); } From b4bdd73ce865213a5653dc424873e8da37e858cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 28 Jan 2010 15:06:20 -0800 Subject: [PATCH 501/670] Linux 2.6.32.7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 20da31216f50..07d3c6ac5502 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = .6 +EXTRAVERSION = .7 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* From e15fca01ba2678b5db6c29b79d142d73272cfb7b Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Tue, 15 Dec 2009 17:25:43 +0200 Subject: [PATCH 502/670] scsi_lib: Fix bug in completion of bidi commands commit 63c43b0ec1765b74c734d465ba6345ef4f434df8 upstream. Because of the terrible structuring of scsi-bidi-commands it breaks some of the life time rules of a scsi-command. It is now not allowed to free up the block-request before cleanup and partial deallocation of the scsi-command. (Which is not so for none bidi commands) The right fix to this problem would be to make bidi command a first citizen by allocating a scsi_sdb pointer at scsi command just like cmd->prot_sdb. The bidi sdb should be allocated/deallocated as part of the get/put_command (Again like the prot_sdb) and the current decoupling of scsi_cmnd and blk-request should be kept. For now make sure scsi_release_buffers() is called before the call to blk_end_request_all() which might cause the suicide of the block requests. At best the leak of bidi buffers, at worse a crash, as there is a race between the existence of the bidi_request and the free of the associated bidi_sdb. The reason this was never hit before is because only OSD has the potential of doing asynchronous bidi commands. (So does bsg but it is never used) And OSD clients just happen to do all their bidi commands synchronously, up until recently. Signed-off-by: Boaz Harrosh Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5987da857103..bc9a88145a71 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -749,9 +749,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) */ req->next_rq->resid_len = scsi_in(cmd)->resid; + scsi_release_buffers(cmd); blk_end_request_all(req, 0); - scsi_release_buffers(cmd); scsi_next_command(cmd); return; } From b7a9d922a59d221ec2cfd15fb2fc317f2c742bdc Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Sat, 12 Dec 2009 14:52:21 +0100 Subject: [PATCH 503/670] mptsas: Fix issue with chain pools allocation on katmai commit f1053a7ca9ce095d95bcc1cf41684c5e4f3e7751 upstream. Since commit 9d2e9d66a3f032667934144cd61c396ba49f090d mptsas driver fails to allocate memory for the MPT chain buffers for second LSI adapter on PPC440SPe Katmai platform: ... ioc1: LSISAS1068E B3: Capabilities={Initiator} mptbase: ioc1: ERROR - Unable to allocate Reply, Request, Chain Buffers! mptbase: ioc1: ERROR - didn't initialize properly! (-3) mptsas: probe of 0002:31:00.0 failed with error -3 This commit increased MPT_FC_CAN_QUEUE value but initChainBuffers() doesn't differentiate between SAS and FC causing increased allocation for SAS case, too. Later pci_alloc_consistent() fails to allocate increased chain buffer pool size for SAS case. Provide a fix by looking at the bus type and using appropriate MPT_SAS_CAN_QUEUE value while calculation of the number of chain buffers. Signed-off-by: Anatolij Gustschin Acked-by: Kashyap Desai Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/message/fusion/mptbase.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 610e914abe6c..b6992b7b0d92 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -4330,6 +4330,8 @@ initChainBuffers(MPT_ADAPTER *ioc) if (ioc->bus_type == SPI) num_chain *= MPT_SCSI_CAN_QUEUE; + else if (ioc->bus_type == SAS) + num_chain *= MPT_SAS_CAN_QUEUE; else num_chain *= MPT_FC_CAN_QUEUE; From 8268c0bce9f4df836265ac5c7982ff8f8808f199 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 27 Jan 2010 09:20:03 -0800 Subject: [PATCH 504/670] mm: add new 'read_cache_page_gfp()' helper function commit 0531b2aac59c2296570ac52bfc032ef2ace7d5e1 upstream. It's a simplified 'read_cache_page()' which takes a page allocation flag, so that different paths can control how aggressive the memory allocations are that populate a address space. In particular, the intel GPU object mapping code wants to be able to do a certain amount of own internal memory management by automatically shrinking the address space when memory starts getting tight. This allows it to dynamically use different memory allocation policies on a per-allocation basis, rather than depend on the (static) address space gfp policy. The actual new function is a one-liner, but re-organizing the helper functions to the point where you can do this with a single line of code is what most of the patch is all about. Tested-by: Chris Wilson Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- include/linux/pagemap.h | 2 + mm/filemap.c | 100 +++++++++++++++++++++++++++------------- 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index ed5d7501e181..3c62ed408492 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -253,6 +253,8 @@ extern struct page * read_cache_page_async(struct address_space *mapping, extern struct page * read_cache_page(struct address_space *mapping, pgoff_t index, filler_t *filler, void *data); +extern struct page * read_cache_page_gfp(struct address_space *mapping, + pgoff_t index, gfp_t gfp_mask); extern int read_cache_pages(struct address_space *mapping, struct list_head *pages, filler_t *filler, void *data); diff --git a/mm/filemap.c b/mm/filemap.c index ef169f37156d..fbdacb717ae9 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1655,14 +1655,15 @@ EXPORT_SYMBOL(generic_file_readonly_mmap); static struct page *__read_cache_page(struct address_space *mapping, pgoff_t index, int (*filler)(void *,struct page*), - void *data) + void *data, + gfp_t gfp) { struct page *page; int err; repeat: page = find_get_page(mapping, index); if (!page) { - page = page_cache_alloc_cold(mapping); + page = __page_cache_alloc(gfp | __GFP_COLD); if (!page) return ERR_PTR(-ENOMEM); err = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL); @@ -1682,31 +1683,18 @@ static struct page *__read_cache_page(struct address_space *mapping, return page; } -/** - * read_cache_page_async - read into page cache, fill it if needed - * @mapping: the page's address_space - * @index: the page index - * @filler: function to perform the read - * @data: destination for read data - * - * Same as read_cache_page, but don't wait for page to become unlocked - * after submitting it to the filler. - * - * Read into the page cache. If a page already exists, and PageUptodate() is - * not set, try to fill the page but don't wait for it to become unlocked. - * - * If the page does not get brought uptodate, return -EIO. - */ -struct page *read_cache_page_async(struct address_space *mapping, +static struct page *do_read_cache_page(struct address_space *mapping, pgoff_t index, int (*filler)(void *,struct page*), - void *data) + void *data, + gfp_t gfp) + { struct page *page; int err; retry: - page = __read_cache_page(mapping, index, filler, data); + page = __read_cache_page(mapping, index, filler, data, gfp); if (IS_ERR(page)) return page; if (PageUptodate(page)) @@ -1731,8 +1719,67 @@ struct page *read_cache_page_async(struct address_space *mapping, mark_page_accessed(page); return page; } + +/** + * read_cache_page_async - read into page cache, fill it if needed + * @mapping: the page's address_space + * @index: the page index + * @filler: function to perform the read + * @data: destination for read data + * + * Same as read_cache_page, but don't wait for page to become unlocked + * after submitting it to the filler. + * + * Read into the page cache. If a page already exists, and PageUptodate() is + * not set, try to fill the page but don't wait for it to become unlocked. + * + * If the page does not get brought uptodate, return -EIO. + */ +struct page *read_cache_page_async(struct address_space *mapping, + pgoff_t index, + int (*filler)(void *,struct page*), + void *data) +{ + return do_read_cache_page(mapping, index, filler, data, mapping_gfp_mask(mapping)); +} EXPORT_SYMBOL(read_cache_page_async); +static struct page *wait_on_page_read(struct page *page) +{ + if (!IS_ERR(page)) { + wait_on_page_locked(page); + if (!PageUptodate(page)) { + page_cache_release(page); + page = ERR_PTR(-EIO); + } + } + return page; +} + +/** + * read_cache_page_gfp - read into page cache, using specified page allocation flags. + * @mapping: the page's address_space + * @index: the page index + * @gfp: the page allocator flags to use if allocating + * + * This is the same as "read_mapping_page(mapping, index, NULL)", but with + * any new page allocations done using the specified allocation flags. Note + * that the Radix tree operations will still use GFP_KERNEL, so you can't + * expect to do this atomically or anything like that - but you can pass in + * other page requirements. + * + * If the page does not get brought uptodate, return -EIO. + */ +struct page *read_cache_page_gfp(struct address_space *mapping, + pgoff_t index, + gfp_t gfp) +{ + filler_t *filler = (filler_t *)mapping->a_ops->readpage; + + return wait_on_page_read(do_read_cache_page(mapping, index, filler, NULL, gfp)); +} +EXPORT_SYMBOL(read_cache_page_gfp); + /** * read_cache_page - read into page cache, fill it if needed * @mapping: the page's address_space @@ -1750,18 +1797,7 @@ struct page *read_cache_page(struct address_space *mapping, int (*filler)(void *,struct page*), void *data) { - struct page *page; - - page = read_cache_page_async(mapping, index, filler, data); - if (IS_ERR(page)) - goto out; - wait_on_page_locked(page); - if (!PageUptodate(page)) { - page_cache_release(page); - page = ERR_PTR(-EIO); - } - out: - return page; + return wait_on_page_read(read_cache_page_async(mapping, index, filler, data)); } EXPORT_SYMBOL(read_cache_page); From d8e0902806c0bd2ccc4f6a267ff52565a3ec933b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Jan 2010 13:36:32 +0000 Subject: [PATCH 505/670] drm/i915: Selectively enable self-reclaim commit 4bdadb9785696439c6e2b3efe34aa76df1149c83 upstream. Having missed the ENOMEM return via i915_gem_fault(), there are probably other paths that I also missed. By not enabling NORETRY by default these paths can run the shrinker and take memory from the system (but not from our own inactive lists because our shrinker can not run whilst we hold the struct mutex) and this may allow the system to survive a little longer whilst our drivers consume all available memory. References: OOM killer unexpectedly called with kernel 2.6.32 http://bugzilla.kernel.org/show_bug.cgi?id=14933 v2: Pass gfp into page mapping. v3: Use new read_cache_page_gfp() instead of open-coding. Signed-off-by: Chris Wilson Cc: KOSAKI Motohiro Cc: Hugh Dickins Cc: Jesse Barnes Cc: Eric Anholt Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_gem.c | 13 ------- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 54 +++++++++-------------------- 4 files changed, 19 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index e9dbb481c469..8bf3770f294e 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -142,19 +142,6 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size) if (IS_ERR(obj->filp)) goto free; - /* Basically we want to disable the OOM killer and handle ENOMEM - * ourselves by sacrificing pages from cached buffers. - * XXX shmem_file_[gs]et_gfp_mask() - */ - mapping_set_gfp_mask(obj->filp->f_path.dentry->d_inode->i_mapping, - GFP_HIGHUSER | - __GFP_COLD | - __GFP_FS | - __GFP_RECLAIMABLE | - __GFP_NORETRY | - __GFP_NOWARN | - __GFP_NOMEMALLOC); - kref_init(&obj->refcount); kref_init(&obj->handlecount); obj->size = size; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 26bf0552b3cb..af655e886c6d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -288,7 +288,7 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data) list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { obj = obj_priv->obj; if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_get_pages(obj, 0); if (ret) { DRM_ERROR("Failed to get pages: %d\n", ret); spin_unlock(&dev_priv->mm.active_list_lock); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 791fded1378d..727724603c48 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -822,7 +822,7 @@ int i915_gem_attach_phys_object(struct drm_device *dev, void i915_gem_detach_phys_object(struct drm_device *dev, struct drm_gem_object *obj); void i915_gem_free_all_phys_object(struct drm_device *dev); -int i915_gem_object_get_pages(struct drm_gem_object *obj); +int i915_gem_object_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); void i915_gem_object_put_pages(struct drm_gem_object *obj); void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index df2c625b1fa0..8ad244ae7fa3 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -277,7 +277,7 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, mutex_lock(&dev->struct_mutex); - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_get_pages(obj, 0); if (ret != 0) goto fail_unlock; @@ -321,40 +321,24 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, return ret; } -static inline gfp_t -i915_gem_object_get_page_gfp_mask (struct drm_gem_object *obj) -{ - return mapping_gfp_mask(obj->filp->f_path.dentry->d_inode->i_mapping); -} - -static inline void -i915_gem_object_set_page_gfp_mask (struct drm_gem_object *obj, gfp_t gfp) -{ - mapping_set_gfp_mask(obj->filp->f_path.dentry->d_inode->i_mapping, gfp); -} - static int i915_gem_object_get_pages_or_evict(struct drm_gem_object *obj) { int ret; - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_get_pages(obj, __GFP_NORETRY | __GFP_NOWARN); /* If we've insufficient memory to map in the pages, attempt * to make some space by throwing out some old buffers. */ if (ret == -ENOMEM) { struct drm_device *dev = obj->dev; - gfp_t gfp; ret = i915_gem_evict_something(dev, obj->size); if (ret) return ret; - gfp = i915_gem_object_get_page_gfp_mask(obj); - i915_gem_object_set_page_gfp_mask(obj, gfp & ~__GFP_NORETRY); - ret = i915_gem_object_get_pages(obj); - i915_gem_object_set_page_gfp_mask (obj, gfp); + ret = i915_gem_object_get_pages(obj, 0); } return ret; @@ -790,7 +774,7 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, mutex_lock(&dev->struct_mutex); - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_get_pages(obj, 0); if (ret != 0) goto fail_unlock; @@ -2219,7 +2203,8 @@ i915_gem_evict_something(struct drm_device *dev, int min_size) } int -i915_gem_object_get_pages(struct drm_gem_object *obj) +i915_gem_object_get_pages(struct drm_gem_object *obj, + gfp_t gfpmask) { struct drm_i915_gem_object *obj_priv = obj->driver_private; int page_count, i; @@ -2245,7 +2230,10 @@ i915_gem_object_get_pages(struct drm_gem_object *obj) inode = obj->filp->f_path.dentry->d_inode; mapping = inode->i_mapping; for (i = 0; i < page_count; i++) { - page = read_mapping_page(mapping, i, NULL); + page = read_cache_page_gfp(mapping, i, + mapping_gfp_mask (mapping) | + __GFP_COLD | + gfpmask); if (IS_ERR(page)) { ret = PTR_ERR(page); i915_gem_object_put_pages(obj); @@ -2568,7 +2556,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj_priv = obj->driver_private; struct drm_mm_node *free_space; - bool retry_alloc = false; + gfp_t gfpmask = __GFP_NORETRY | __GFP_NOWARN; int ret; if (obj_priv->madv != I915_MADV_WILLNEED) { @@ -2612,15 +2600,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) DRM_INFO("Binding object of size %zd at 0x%08x\n", obj->size, obj_priv->gtt_offset); #endif - if (retry_alloc) { - i915_gem_object_set_page_gfp_mask (obj, - i915_gem_object_get_page_gfp_mask (obj) & ~__GFP_NORETRY); - } - ret = i915_gem_object_get_pages(obj); - if (retry_alloc) { - i915_gem_object_set_page_gfp_mask (obj, - i915_gem_object_get_page_gfp_mask (obj) | __GFP_NORETRY); - } + ret = i915_gem_object_get_pages(obj, gfpmask); if (ret) { drm_mm_put_block(obj_priv->gtt_space); obj_priv->gtt_space = NULL; @@ -2630,9 +2610,9 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) ret = i915_gem_evict_something(dev, obj->size); if (ret) { /* now try to shrink everyone else */ - if (! retry_alloc) { - retry_alloc = true; - goto search_free; + if (gfpmask) { + gfpmask = 0; + goto search_free; } return ret; @@ -4695,7 +4675,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev, if (!obj_priv->phys_obj) return; - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_get_pages(obj, 0); if (ret) goto out; @@ -4753,7 +4733,7 @@ i915_gem_attach_phys_object(struct drm_device *dev, obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1]; obj_priv->phys_obj->cur_obj = obj; - ret = i915_gem_object_get_pages(obj); + ret = i915_gem_object_get_pages(obj, 0); if (ret) { DRM_ERROR("failed to get page list\n"); goto out; From 16a2ae6eb112b506ca1e464d848e684f6f90dadc Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 26 Jan 2010 21:39:07 +0100 Subject: [PATCH 506/670] firewire: ohci: fix crashes with TSB43AB23 on 64bit systems commit 7a481436787cbc932af6c407b317ac603969a242 upstream. Unsurprisingly, Texas Instruments TSB43AB23 exhibits the same behaviour as TSB43AB22/A in dual buffer IR DMA mode: If descriptors are located at physical addresses above the 31 bit address range (2 GB), the controller will overwrite random memory. With luck, this merely prevents video reception. With only a little less luck, the machine crashes. We use the same workaround here as with TSB43AB22/A: Switch off the dual buffer capability flag and use packet-per-buffer IR DMA instead. Another possible workaround would be to limit the coherent DMA mask to 31 bits. In Linux 2.6.33, this change serves effectively only as documentation since dual buffer mode is not used for any controller anymore. But somebody might want to re-enable it in the future to make use of features of dual buffer DMA that are not available in packet-per-buffer mode. In Linux 2.6.32 and older, this update is vital for anyone with this controller, more than 2 GB RAM, a 64 bit kernel, and FireWire video or audio applications. We have at least four reports: http://bugzilla.kernel.org/show_bug.cgi?id=13808 http://marc.info/?l=linux1394-user&m=126154279004083 https://bugzilla.redhat.com/show_bug.cgi?id=552142 http://marc.info/?l=linux1394-user&m=126432246128386 Reported-by: Paul Johnson Reported-by: Ronneil Camara Reported-by: G Zornetzer Reported-by: Mark Thompson Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman --- drivers/firewire/ohci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 1e504de739e5..720b39b0b4ed 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2412,6 +2412,7 @@ static void ohci_pmac_off(struct pci_dev *dev) #define PCI_VENDOR_ID_AGERE PCI_VENDOR_ID_ATT #define PCI_DEVICE_ID_AGERE_FW643 0x5901 +#define PCI_DEVICE_ID_TI_TSB43AB23 0x8024 static int __devinit pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) @@ -2477,7 +2478,8 @@ static int __devinit pci_probe(struct pci_dev *dev, #if !defined(CONFIG_X86_32) /* dual-buffer mode is broken with descriptor addresses above 2G */ if (dev->vendor == PCI_VENDOR_ID_TI && - dev->device == PCI_DEVICE_ID_TI_TSB43AB22) + (dev->device == PCI_DEVICE_ID_TI_TSB43AB22 || + dev->device == PCI_DEVICE_ID_TI_TSB43AB23)) ohci->use_dualbuffer = false; #endif From 76e789c066a7d65c180e916c0d74227fbe3e0b05 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 27 Jan 2010 10:12:40 +0100 Subject: [PATCH 507/670] S390: fix single stepped svcs with TRACE_IRQFLAGS=y commit 21ec7f6dbf10492ce9a21718040677d3e68bd57d upstream. If irq flags tracing is enabled the TRACE_IRQS_ON macros expands to a function call which clobbers registers %r0-%r5. The macro is used in the code path for single stepped system calls. The argument registers %r2-%r6 need to be restored from the stack before the system call function is called. Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/entry.S | 1 + arch/s390/kernel/entry64.S | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 48215d15762b..e8ef21c51bbe 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -571,6 +571,7 @@ pgm_svcper: mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP TRACE_IRQS_ON + lm %r2,%r6,SP_R2(%r15) # load svc arguments stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_do_svc) diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 9aff1d449b6e..f33658f09dd7 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -549,6 +549,7 @@ pgm_svcper: mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP TRACE_IRQS_ON + lmg %r2,%r6,SP_R2(%r15) # load svc arguments stosm __SF_EMPTY(%r15),0x03 # reenable interrupts j sysc_do_svc From b5b39c3961de96c8c82e2642f2174b3c41cb4327 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Wed, 20 Jan 2010 12:10:47 -0800 Subject: [PATCH 508/670] x86: Set hotpluggable nodes in nodes_possible_map commit 3a5fc0e40cb467e692737bc798bc99773c81e1e2 upstream. nodes_possible_map does not currently include nodes that have SRAT entries that are all ACPI_SRAT_MEM_HOT_PLUGGABLE since the bit is cleared in nodes_parsed if it does not have an online address range. Unequivocally setting the bit in nodes_parsed is insufficient since existing code, such as acpi_get_nodes(), assumes all nodes in the map have online address ranges. In fact, all code using nodes_parsed assumes such nodes represent an address range of online memory. nodes_possible_map is created by unioning nodes_parsed and cpu_nodes_parsed; the former represents nodes with online memory and the latter represents memoryless nodes. We now set the bit for hotpluggable nodes in cpu_nodes_parsed so that it also gets set in nodes_possible_map. [ hpa: Haicheng Li points out that this makes the naming of the variable cpu_nodes_parsed somewhat counterintuitive. However, leave it as is in the interest of keeping the pure bug fix patch small. ] Signed-off-by: David Rientjes Tested-by: Haicheng Li LKML-Reference: Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/mm/srat_64.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index dbb5381f7b3b..3871c600c4f3 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -229,9 +229,11 @@ update_nodes_add(int node, unsigned long start, unsigned long end) printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n"); } - if (changed) + if (changed) { + node_set(node, cpu_nodes_parsed); printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n", nd->start, nd->end); + } } /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ From 8c2cd3f39601fee6837727cb85c36dd19a083e0f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 23 Jan 2010 18:27:47 -0800 Subject: [PATCH 509/670] x86: Remove "x86 CPU features in debugfs" (CONFIG_X86_CPU_DEBUG) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b160091802d4a76dd063facb09fcf10bf5d5d747 upstream. CONFIG_X86_CPU_DEBUG, which provides some parsed versions of the x86 CPU configuration via debugfs, has caused boot failures on real hardware. The value of this feature has been marginal at best, as all this information is already available to userspace via generic interfaces. Causes crashes that have not been fixed + minimal utility -> remove. See the referenced LKML thread for more information. Reported-by: Ozan ÇaÄŸlayan Signed-off-by: H. Peter Anvin LKML-Reference: Cc: Jaswinder Singh Rajput Cc: Linus Torvalds Cc: Rafael J. Wysocki Cc: Yinghai Lu Signed-off-by: Greg Kroah-Hartman --- arch/x86/Kconfig | 6 - arch/x86/include/asm/cpu_debug.h | 127 ------ arch/x86/kernel/cpu/Makefile | 2 - arch/x86/kernel/cpu/cpu_debug.c | 688 ------------------------------- 4 files changed, 823 deletions(-) delete mode 100644 arch/x86/include/asm/cpu_debug.h delete mode 100644 arch/x86/kernel/cpu/cpu_debug.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 72ace9515a07..4fdb669e8469 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -984,12 +984,6 @@ config X86_CPUID with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to /dev/cpu/31/cpuid. -config X86_CPU_DEBUG - tristate "/sys/kernel/debug/x86/cpu/* - CPU Debug support" - ---help--- - If you select this option, this will provide various x86 CPUs - information through debugfs. - choice prompt "High Memory Support" default HIGHMEM4G if !X86_NUMAQ diff --git a/arch/x86/include/asm/cpu_debug.h b/arch/x86/include/asm/cpu_debug.h deleted file mode 100644 index d96c1ee3a95c..000000000000 --- a/arch/x86/include/asm/cpu_debug.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef _ASM_X86_CPU_DEBUG_H -#define _ASM_X86_CPU_DEBUG_H - -/* - * CPU x86 architecture debug - * - * Copyright(C) 2009 Jaswinder Singh Rajput - */ - -/* Register flags */ -enum cpu_debug_bit { -/* Model Specific Registers (MSRs) */ - CPU_MC_BIT, /* Machine Check */ - CPU_MONITOR_BIT, /* Monitor */ - CPU_TIME_BIT, /* Time */ - CPU_PMC_BIT, /* Performance Monitor */ - CPU_PLATFORM_BIT, /* Platform */ - CPU_APIC_BIT, /* APIC */ - CPU_POWERON_BIT, /* Power-on */ - CPU_CONTROL_BIT, /* Control */ - CPU_FEATURES_BIT, /* Features control */ - CPU_LBRANCH_BIT, /* Last Branch */ - CPU_BIOS_BIT, /* BIOS */ - CPU_FREQ_BIT, /* Frequency */ - CPU_MTTR_BIT, /* MTRR */ - CPU_PERF_BIT, /* Performance */ - CPU_CACHE_BIT, /* Cache */ - CPU_SYSENTER_BIT, /* Sysenter */ - CPU_THERM_BIT, /* Thermal */ - CPU_MISC_BIT, /* Miscellaneous */ - CPU_DEBUG_BIT, /* Debug */ - CPU_PAT_BIT, /* PAT */ - CPU_VMX_BIT, /* VMX */ - CPU_CALL_BIT, /* System Call */ - CPU_BASE_BIT, /* BASE Address */ - CPU_VER_BIT, /* Version ID */ - CPU_CONF_BIT, /* Configuration */ - CPU_SMM_BIT, /* System mgmt mode */ - CPU_SVM_BIT, /*Secure Virtual Machine*/ - CPU_OSVM_BIT, /* OS-Visible Workaround*/ -/* Standard Registers */ - CPU_TSS_BIT, /* Task Stack Segment */ - CPU_CR_BIT, /* Control Registers */ - CPU_DT_BIT, /* Descriptor Table */ -/* End of Registers flags */ - CPU_REG_ALL_BIT, /* Select all Registers */ -}; - -#define CPU_REG_ALL (~0) /* Select all Registers */ - -#define CPU_MC (1 << CPU_MC_BIT) -#define CPU_MONITOR (1 << CPU_MONITOR_BIT) -#define CPU_TIME (1 << CPU_TIME_BIT) -#define CPU_PMC (1 << CPU_PMC_BIT) -#define CPU_PLATFORM (1 << CPU_PLATFORM_BIT) -#define CPU_APIC (1 << CPU_APIC_BIT) -#define CPU_POWERON (1 << CPU_POWERON_BIT) -#define CPU_CONTROL (1 << CPU_CONTROL_BIT) -#define CPU_FEATURES (1 << CPU_FEATURES_BIT) -#define CPU_LBRANCH (1 << CPU_LBRANCH_BIT) -#define CPU_BIOS (1 << CPU_BIOS_BIT) -#define CPU_FREQ (1 << CPU_FREQ_BIT) -#define CPU_MTRR (1 << CPU_MTTR_BIT) -#define CPU_PERF (1 << CPU_PERF_BIT) -#define CPU_CACHE (1 << CPU_CACHE_BIT) -#define CPU_SYSENTER (1 << CPU_SYSENTER_BIT) -#define CPU_THERM (1 << CPU_THERM_BIT) -#define CPU_MISC (1 << CPU_MISC_BIT) -#define CPU_DEBUG (1 << CPU_DEBUG_BIT) -#define CPU_PAT (1 << CPU_PAT_BIT) -#define CPU_VMX (1 << CPU_VMX_BIT) -#define CPU_CALL (1 << CPU_CALL_BIT) -#define CPU_BASE (1 << CPU_BASE_BIT) -#define CPU_VER (1 << CPU_VER_BIT) -#define CPU_CONF (1 << CPU_CONF_BIT) -#define CPU_SMM (1 << CPU_SMM_BIT) -#define CPU_SVM (1 << CPU_SVM_BIT) -#define CPU_OSVM (1 << CPU_OSVM_BIT) -#define CPU_TSS (1 << CPU_TSS_BIT) -#define CPU_CR (1 << CPU_CR_BIT) -#define CPU_DT (1 << CPU_DT_BIT) - -/* Register file flags */ -enum cpu_file_bit { - CPU_INDEX_BIT, /* index */ - CPU_VALUE_BIT, /* value */ -}; - -#define CPU_FILE_VALUE (1 << CPU_VALUE_BIT) - -#define MAX_CPU_FILES 512 - -struct cpu_private { - unsigned cpu; - unsigned type; - unsigned reg; - unsigned file; -}; - -struct cpu_debug_base { - char *name; /* Register name */ - unsigned flag; /* Register flag */ - unsigned write; /* Register write flag */ -}; - -/* - * Currently it looks similar to cpu_debug_base but once we add more files - * cpu_file_base will go in different direction - */ -struct cpu_file_base { - char *name; /* Register file name */ - unsigned flag; /* Register file flag */ - unsigned write; /* Register write flag */ -}; - -struct cpu_cpuX_base { - struct dentry *dentry; /* Register dentry */ - int init; /* Register index file */ -}; - -struct cpu_debug_range { - unsigned min; /* Register range min */ - unsigned max; /* Register range max */ - unsigned flag; /* Supported flags */ -}; - -#endif /* _ASM_X86_CPU_DEBUG_H */ diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 68537e957a9b..ff502cc59d2f 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -18,8 +18,6 @@ obj-y += vmware.o hypervisor.o sched.o obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o obj-$(CONFIG_X86_64) += bugs_64.o -obj-$(CONFIG_X86_CPU_DEBUG) += cpu_debug.o - obj-$(CONFIG_CPU_SUP_INTEL) += intel.o obj-$(CONFIG_CPU_SUP_AMD) += amd.o obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o diff --git a/arch/x86/kernel/cpu/cpu_debug.c b/arch/x86/kernel/cpu/cpu_debug.c deleted file mode 100644 index dca325c03999..000000000000 --- a/arch/x86/kernel/cpu/cpu_debug.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - * CPU x86 architecture debug code - * - * Copyright(C) 2009 Jaswinder Singh Rajput - * - * For licencing details see kernel-base/COPYING - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static DEFINE_PER_CPU(struct cpu_cpuX_base [CPU_REG_ALL_BIT], cpu_arr); -static DEFINE_PER_CPU(struct cpu_private * [MAX_CPU_FILES], priv_arr); -static DEFINE_PER_CPU(int, cpu_priv_count); - -static DEFINE_MUTEX(cpu_debug_lock); - -static struct dentry *cpu_debugfs_dir; - -static struct cpu_debug_base cpu_base[] = { - { "mc", CPU_MC, 0 }, - { "monitor", CPU_MONITOR, 0 }, - { "time", CPU_TIME, 0 }, - { "pmc", CPU_PMC, 1 }, - { "platform", CPU_PLATFORM, 0 }, - { "apic", CPU_APIC, 0 }, - { "poweron", CPU_POWERON, 0 }, - { "control", CPU_CONTROL, 0 }, - { "features", CPU_FEATURES, 0 }, - { "lastbranch", CPU_LBRANCH, 0 }, - { "bios", CPU_BIOS, 0 }, - { "freq", CPU_FREQ, 0 }, - { "mtrr", CPU_MTRR, 0 }, - { "perf", CPU_PERF, 0 }, - { "cache", CPU_CACHE, 0 }, - { "sysenter", CPU_SYSENTER, 0 }, - { "therm", CPU_THERM, 0 }, - { "misc", CPU_MISC, 0 }, - { "debug", CPU_DEBUG, 0 }, - { "pat", CPU_PAT, 0 }, - { "vmx", CPU_VMX, 0 }, - { "call", CPU_CALL, 0 }, - { "base", CPU_BASE, 0 }, - { "ver", CPU_VER, 0 }, - { "conf", CPU_CONF, 0 }, - { "smm", CPU_SMM, 0 }, - { "svm", CPU_SVM, 0 }, - { "osvm", CPU_OSVM, 0 }, - { "tss", CPU_TSS, 0 }, - { "cr", CPU_CR, 0 }, - { "dt", CPU_DT, 0 }, - { "registers", CPU_REG_ALL, 0 }, -}; - -static struct cpu_file_base cpu_file[] = { - { "index", CPU_REG_ALL, 0 }, - { "value", CPU_REG_ALL, 1 }, -}; - -/* CPU Registers Range */ -static struct cpu_debug_range cpu_reg_range[] = { - { 0x00000000, 0x00000001, CPU_MC, }, - { 0x00000006, 0x00000007, CPU_MONITOR, }, - { 0x00000010, 0x00000010, CPU_TIME, }, - { 0x00000011, 0x00000013, CPU_PMC, }, - { 0x00000017, 0x00000017, CPU_PLATFORM, }, - { 0x0000001B, 0x0000001B, CPU_APIC, }, - { 0x0000002A, 0x0000002B, CPU_POWERON, }, - { 0x0000002C, 0x0000002C, CPU_FREQ, }, - { 0x0000003A, 0x0000003A, CPU_CONTROL, }, - { 0x00000040, 0x00000047, CPU_LBRANCH, }, - { 0x00000060, 0x00000067, CPU_LBRANCH, }, - { 0x00000079, 0x00000079, CPU_BIOS, }, - { 0x00000088, 0x0000008A, CPU_CACHE, }, - { 0x0000008B, 0x0000008B, CPU_BIOS, }, - { 0x0000009B, 0x0000009B, CPU_MONITOR, }, - { 0x000000C1, 0x000000C4, CPU_PMC, }, - { 0x000000CD, 0x000000CD, CPU_FREQ, }, - { 0x000000E7, 0x000000E8, CPU_PERF, }, - { 0x000000FE, 0x000000FE, CPU_MTRR, }, - - { 0x00000116, 0x0000011E, CPU_CACHE, }, - { 0x00000174, 0x00000176, CPU_SYSENTER, }, - { 0x00000179, 0x0000017B, CPU_MC, }, - { 0x00000186, 0x00000189, CPU_PMC, }, - { 0x00000198, 0x00000199, CPU_PERF, }, - { 0x0000019A, 0x0000019A, CPU_TIME, }, - { 0x0000019B, 0x0000019D, CPU_THERM, }, - { 0x000001A0, 0x000001A0, CPU_MISC, }, - { 0x000001C9, 0x000001C9, CPU_LBRANCH, }, - { 0x000001D7, 0x000001D8, CPU_LBRANCH, }, - { 0x000001D9, 0x000001D9, CPU_DEBUG, }, - { 0x000001DA, 0x000001E0, CPU_LBRANCH, }, - - { 0x00000200, 0x0000020F, CPU_MTRR, }, - { 0x00000250, 0x00000250, CPU_MTRR, }, - { 0x00000258, 0x00000259, CPU_MTRR, }, - { 0x00000268, 0x0000026F, CPU_MTRR, }, - { 0x00000277, 0x00000277, CPU_PAT, }, - { 0x000002FF, 0x000002FF, CPU_MTRR, }, - - { 0x00000300, 0x00000311, CPU_PMC, }, - { 0x00000345, 0x00000345, CPU_PMC, }, - { 0x00000360, 0x00000371, CPU_PMC, }, - { 0x0000038D, 0x00000390, CPU_PMC, }, - { 0x000003A0, 0x000003BE, CPU_PMC, }, - { 0x000003C0, 0x000003CD, CPU_PMC, }, - { 0x000003E0, 0x000003E1, CPU_PMC, }, - { 0x000003F0, 0x000003F2, CPU_PMC, }, - - { 0x00000400, 0x00000417, CPU_MC, }, - { 0x00000480, 0x0000048B, CPU_VMX, }, - - { 0x00000600, 0x00000600, CPU_DEBUG, }, - { 0x00000680, 0x0000068F, CPU_LBRANCH, }, - { 0x000006C0, 0x000006CF, CPU_LBRANCH, }, - - { 0x000107CC, 0x000107D3, CPU_PMC, }, - - { 0xC0000080, 0xC0000080, CPU_FEATURES, }, - { 0xC0000081, 0xC0000084, CPU_CALL, }, - { 0xC0000100, 0xC0000102, CPU_BASE, }, - { 0xC0000103, 0xC0000103, CPU_TIME, }, - - { 0xC0010000, 0xC0010007, CPU_PMC, }, - { 0xC0010010, 0xC0010010, CPU_CONF, }, - { 0xC0010015, 0xC0010015, CPU_CONF, }, - { 0xC0010016, 0xC001001A, CPU_MTRR, }, - { 0xC001001D, 0xC001001D, CPU_MTRR, }, - { 0xC001001F, 0xC001001F, CPU_CONF, }, - { 0xC0010030, 0xC0010035, CPU_BIOS, }, - { 0xC0010044, 0xC0010048, CPU_MC, }, - { 0xC0010050, 0xC0010056, CPU_SMM, }, - { 0xC0010058, 0xC0010058, CPU_CONF, }, - { 0xC0010060, 0xC0010060, CPU_CACHE, }, - { 0xC0010061, 0xC0010068, CPU_SMM, }, - { 0xC0010069, 0xC001006B, CPU_SMM, }, - { 0xC0010070, 0xC0010071, CPU_SMM, }, - { 0xC0010111, 0xC0010113, CPU_SMM, }, - { 0xC0010114, 0xC0010118, CPU_SVM, }, - { 0xC0010140, 0xC0010141, CPU_OSVM, }, - { 0xC0011022, 0xC0011023, CPU_CONF, }, -}; - -static int is_typeflag_valid(unsigned cpu, unsigned flag) -{ - int i; - - /* Standard Registers should be always valid */ - if (flag >= CPU_TSS) - return 1; - - for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) { - if (cpu_reg_range[i].flag == flag) - return 1; - } - - /* Invalid */ - return 0; -} - -static unsigned get_cpu_range(unsigned cpu, unsigned *min, unsigned *max, - int index, unsigned flag) -{ - if (cpu_reg_range[index].flag == flag) { - *min = cpu_reg_range[index].min; - *max = cpu_reg_range[index].max; - } else - *max = 0; - - return *max; -} - -/* This function can also be called with seq = NULL for printk */ -static void print_cpu_data(struct seq_file *seq, unsigned type, - u32 low, u32 high) -{ - struct cpu_private *priv; - u64 val = high; - - if (seq) { - priv = seq->private; - if (priv->file) { - val = (val << 32) | low; - seq_printf(seq, "0x%llx\n", val); - } else - seq_printf(seq, " %08x: %08x_%08x\n", - type, high, low); - } else - printk(KERN_INFO " %08x: %08x_%08x\n", type, high, low); -} - -/* This function can also be called with seq = NULL for printk */ -static void print_msr(struct seq_file *seq, unsigned cpu, unsigned flag) -{ - unsigned msr, msr_min, msr_max; - struct cpu_private *priv; - u32 low, high; - int i; - - if (seq) { - priv = seq->private; - if (priv->file) { - if (!rdmsr_safe_on_cpu(priv->cpu, priv->reg, - &low, &high)) - print_cpu_data(seq, priv->reg, low, high); - return; - } - } - - for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) { - if (!get_cpu_range(cpu, &msr_min, &msr_max, i, flag)) - continue; - - for (msr = msr_min; msr <= msr_max; msr++) { - if (rdmsr_safe_on_cpu(cpu, msr, &low, &high)) - continue; - print_cpu_data(seq, msr, low, high); - } - } -} - -static void print_tss(void *arg) -{ - struct pt_regs *regs = task_pt_regs(current); - struct seq_file *seq = arg; - unsigned int seg; - - seq_printf(seq, " RAX\t: %016lx\n", regs->ax); - seq_printf(seq, " RBX\t: %016lx\n", regs->bx); - seq_printf(seq, " RCX\t: %016lx\n", regs->cx); - seq_printf(seq, " RDX\t: %016lx\n", regs->dx); - - seq_printf(seq, " RSI\t: %016lx\n", regs->si); - seq_printf(seq, " RDI\t: %016lx\n", regs->di); - seq_printf(seq, " RBP\t: %016lx\n", regs->bp); - seq_printf(seq, " ESP\t: %016lx\n", regs->sp); - -#ifdef CONFIG_X86_64 - seq_printf(seq, " R08\t: %016lx\n", regs->r8); - seq_printf(seq, " R09\t: %016lx\n", regs->r9); - seq_printf(seq, " R10\t: %016lx\n", regs->r10); - seq_printf(seq, " R11\t: %016lx\n", regs->r11); - seq_printf(seq, " R12\t: %016lx\n", regs->r12); - seq_printf(seq, " R13\t: %016lx\n", regs->r13); - seq_printf(seq, " R14\t: %016lx\n", regs->r14); - seq_printf(seq, " R15\t: %016lx\n", regs->r15); -#endif - - asm("movl %%cs,%0" : "=r" (seg)); - seq_printf(seq, " CS\t: %04x\n", seg); - asm("movl %%ds,%0" : "=r" (seg)); - seq_printf(seq, " DS\t: %04x\n", seg); - seq_printf(seq, " SS\t: %04lx\n", regs->ss & 0xffff); - asm("movl %%es,%0" : "=r" (seg)); - seq_printf(seq, " ES\t: %04x\n", seg); - asm("movl %%fs,%0" : "=r" (seg)); - seq_printf(seq, " FS\t: %04x\n", seg); - asm("movl %%gs,%0" : "=r" (seg)); - seq_printf(seq, " GS\t: %04x\n", seg); - - seq_printf(seq, " EFLAGS\t: %016lx\n", regs->flags); - - seq_printf(seq, " EIP\t: %016lx\n", regs->ip); -} - -static void print_cr(void *arg) -{ - struct seq_file *seq = arg; - - seq_printf(seq, " cr0\t: %016lx\n", read_cr0()); - seq_printf(seq, " cr2\t: %016lx\n", read_cr2()); - seq_printf(seq, " cr3\t: %016lx\n", read_cr3()); - seq_printf(seq, " cr4\t: %016lx\n", read_cr4_safe()); -#ifdef CONFIG_X86_64 - seq_printf(seq, " cr8\t: %016lx\n", read_cr8()); -#endif -} - -static void print_desc_ptr(char *str, struct seq_file *seq, struct desc_ptr dt) -{ - seq_printf(seq, " %s\t: %016llx\n", str, (u64)(dt.address | dt.size)); -} - -static void print_dt(void *seq) -{ - struct desc_ptr dt; - unsigned long ldt; - - /* IDT */ - store_idt((struct desc_ptr *)&dt); - print_desc_ptr("IDT", seq, dt); - - /* GDT */ - store_gdt((struct desc_ptr *)&dt); - print_desc_ptr("GDT", seq, dt); - - /* LDT */ - store_ldt(ldt); - seq_printf(seq, " LDT\t: %016lx\n", ldt); - - /* TR */ - store_tr(ldt); - seq_printf(seq, " TR\t: %016lx\n", ldt); -} - -static void print_dr(void *arg) -{ - struct seq_file *seq = arg; - unsigned long dr; - int i; - - for (i = 0; i < 8; i++) { - /* Ignore db4, db5 */ - if ((i == 4) || (i == 5)) - continue; - get_debugreg(dr, i); - seq_printf(seq, " dr%d\t: %016lx\n", i, dr); - } - - seq_printf(seq, "\n MSR\t:\n"); -} - -static void print_apic(void *arg) -{ - struct seq_file *seq = arg; - -#ifdef CONFIG_X86_LOCAL_APIC - seq_printf(seq, " LAPIC\t:\n"); - seq_printf(seq, " ID\t\t: %08x\n", apic_read(APIC_ID) >> 24); - seq_printf(seq, " LVR\t\t: %08x\n", apic_read(APIC_LVR)); - seq_printf(seq, " TASKPRI\t: %08x\n", apic_read(APIC_TASKPRI)); - seq_printf(seq, " ARBPRI\t\t: %08x\n", apic_read(APIC_ARBPRI)); - seq_printf(seq, " PROCPRI\t: %08x\n", apic_read(APIC_PROCPRI)); - seq_printf(seq, " LDR\t\t: %08x\n", apic_read(APIC_LDR)); - seq_printf(seq, " DFR\t\t: %08x\n", apic_read(APIC_DFR)); - seq_printf(seq, " SPIV\t\t: %08x\n", apic_read(APIC_SPIV)); - seq_printf(seq, " ISR\t\t: %08x\n", apic_read(APIC_ISR)); - seq_printf(seq, " ESR\t\t: %08x\n", apic_read(APIC_ESR)); - seq_printf(seq, " ICR\t\t: %08x\n", apic_read(APIC_ICR)); - seq_printf(seq, " ICR2\t\t: %08x\n", apic_read(APIC_ICR2)); - seq_printf(seq, " LVTT\t\t: %08x\n", apic_read(APIC_LVTT)); - seq_printf(seq, " LVTTHMR\t: %08x\n", apic_read(APIC_LVTTHMR)); - seq_printf(seq, " LVTPC\t\t: %08x\n", apic_read(APIC_LVTPC)); - seq_printf(seq, " LVT0\t\t: %08x\n", apic_read(APIC_LVT0)); - seq_printf(seq, " LVT1\t\t: %08x\n", apic_read(APIC_LVT1)); - seq_printf(seq, " LVTERR\t\t: %08x\n", apic_read(APIC_LVTERR)); - seq_printf(seq, " TMICT\t\t: %08x\n", apic_read(APIC_TMICT)); - seq_printf(seq, " TMCCT\t\t: %08x\n", apic_read(APIC_TMCCT)); - seq_printf(seq, " TDCR\t\t: %08x\n", apic_read(APIC_TDCR)); - if (boot_cpu_has(X86_FEATURE_EXTAPIC)) { - unsigned int i, v, maxeilvt; - - v = apic_read(APIC_EFEAT); - maxeilvt = (v >> 16) & 0xff; - seq_printf(seq, " EFEAT\t\t: %08x\n", v); - seq_printf(seq, " ECTRL\t\t: %08x\n", apic_read(APIC_ECTRL)); - - for (i = 0; i < maxeilvt; i++) { - v = apic_read(APIC_EILVTn(i)); - seq_printf(seq, " EILVT%d\t\t: %08x\n", i, v); - } - } -#endif /* CONFIG_X86_LOCAL_APIC */ - seq_printf(seq, "\n MSR\t:\n"); -} - -static int cpu_seq_show(struct seq_file *seq, void *v) -{ - struct cpu_private *priv = seq->private; - - if (priv == NULL) - return -EINVAL; - - switch (cpu_base[priv->type].flag) { - case CPU_TSS: - smp_call_function_single(priv->cpu, print_tss, seq, 1); - break; - case CPU_CR: - smp_call_function_single(priv->cpu, print_cr, seq, 1); - break; - case CPU_DT: - smp_call_function_single(priv->cpu, print_dt, seq, 1); - break; - case CPU_DEBUG: - if (priv->file == CPU_INDEX_BIT) - smp_call_function_single(priv->cpu, print_dr, seq, 1); - print_msr(seq, priv->cpu, cpu_base[priv->type].flag); - break; - case CPU_APIC: - if (priv->file == CPU_INDEX_BIT) - smp_call_function_single(priv->cpu, print_apic, seq, 1); - print_msr(seq, priv->cpu, cpu_base[priv->type].flag); - break; - - default: - print_msr(seq, priv->cpu, cpu_base[priv->type].flag); - break; - } - seq_printf(seq, "\n"); - - return 0; -} - -static void *cpu_seq_start(struct seq_file *seq, loff_t *pos) -{ - if (*pos == 0) /* One time is enough ;-) */ - return seq; - - return NULL; -} - -static void *cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - (*pos)++; - - return cpu_seq_start(seq, pos); -} - -static void cpu_seq_stop(struct seq_file *seq, void *v) -{ -} - -static const struct seq_operations cpu_seq_ops = { - .start = cpu_seq_start, - .next = cpu_seq_next, - .stop = cpu_seq_stop, - .show = cpu_seq_show, -}; - -static int cpu_seq_open(struct inode *inode, struct file *file) -{ - struct cpu_private *priv = inode->i_private; - struct seq_file *seq; - int err; - - err = seq_open(file, &cpu_seq_ops); - if (!err) { - seq = file->private_data; - seq->private = priv; - } - - return err; -} - -static int write_msr(struct cpu_private *priv, u64 val) -{ - u32 low, high; - - high = (val >> 32) & 0xffffffff; - low = val & 0xffffffff; - - if (!wrmsr_safe_on_cpu(priv->cpu, priv->reg, low, high)) - return 0; - - return -EPERM; -} - -static int write_cpu_register(struct cpu_private *priv, const char *buf) -{ - int ret = -EPERM; - u64 val; - - ret = strict_strtoull(buf, 0, &val); - if (ret < 0) - return ret; - - /* Supporting only MSRs */ - if (priv->type < CPU_TSS_BIT) - return write_msr(priv, val); - - return ret; -} - -static ssize_t cpu_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *off) -{ - struct seq_file *seq = file->private_data; - struct cpu_private *priv = seq->private; - char buf[19]; - - if ((priv == NULL) || (count >= sizeof(buf))) - return -EINVAL; - - if (copy_from_user(&buf, ubuf, count)) - return -EFAULT; - - buf[count] = 0; - - if ((cpu_base[priv->type].write) && (cpu_file[priv->file].write)) - if (!write_cpu_register(priv, buf)) - return count; - - return -EACCES; -} - -static const struct file_operations cpu_fops = { - .owner = THIS_MODULE, - .open = cpu_seq_open, - .read = seq_read, - .write = cpu_write, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg, - unsigned file, struct dentry *dentry) -{ - struct cpu_private *priv = NULL; - - /* Already intialized */ - if (file == CPU_INDEX_BIT) - if (per_cpu(cpu_arr[type].init, cpu)) - return 0; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - - priv->cpu = cpu; - priv->type = type; - priv->reg = reg; - priv->file = file; - mutex_lock(&cpu_debug_lock); - per_cpu(priv_arr[type], cpu) = priv; - per_cpu(cpu_priv_count, cpu)++; - mutex_unlock(&cpu_debug_lock); - - if (file) - debugfs_create_file(cpu_file[file].name, S_IRUGO, - dentry, (void *)priv, &cpu_fops); - else { - debugfs_create_file(cpu_base[type].name, S_IRUGO, - per_cpu(cpu_arr[type].dentry, cpu), - (void *)priv, &cpu_fops); - mutex_lock(&cpu_debug_lock); - per_cpu(cpu_arr[type].init, cpu) = 1; - mutex_unlock(&cpu_debug_lock); - } - - return 0; -} - -static int cpu_init_regfiles(unsigned cpu, unsigned int type, unsigned reg, - struct dentry *dentry) -{ - unsigned file; - int err = 0; - - for (file = 0; file < ARRAY_SIZE(cpu_file); file++) { - err = cpu_create_file(cpu, type, reg, file, dentry); - if (err) - return err; - } - - return err; -} - -static int cpu_init_msr(unsigned cpu, unsigned type, struct dentry *dentry) -{ - struct dentry *cpu_dentry = NULL; - unsigned reg, reg_min, reg_max; - int i, err = 0; - char reg_dir[12]; - u32 low, high; - - for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) { - if (!get_cpu_range(cpu, ®_min, ®_max, i, - cpu_base[type].flag)) - continue; - - for (reg = reg_min; reg <= reg_max; reg++) { - if (rdmsr_safe_on_cpu(cpu, reg, &low, &high)) - continue; - - sprintf(reg_dir, "0x%x", reg); - cpu_dentry = debugfs_create_dir(reg_dir, dentry); - err = cpu_init_regfiles(cpu, type, reg, cpu_dentry); - if (err) - return err; - } - } - - return err; -} - -static int cpu_init_allreg(unsigned cpu, struct dentry *dentry) -{ - struct dentry *cpu_dentry = NULL; - unsigned type; - int err = 0; - - for (type = 0; type < ARRAY_SIZE(cpu_base) - 1; type++) { - if (!is_typeflag_valid(cpu, cpu_base[type].flag)) - continue; - cpu_dentry = debugfs_create_dir(cpu_base[type].name, dentry); - per_cpu(cpu_arr[type].dentry, cpu) = cpu_dentry; - - if (type < CPU_TSS_BIT) - err = cpu_init_msr(cpu, type, cpu_dentry); - else - err = cpu_create_file(cpu, type, 0, CPU_INDEX_BIT, - cpu_dentry); - if (err) - return err; - } - - return err; -} - -static int cpu_init_cpu(void) -{ - struct dentry *cpu_dentry = NULL; - struct cpuinfo_x86 *cpui; - char cpu_dir[12]; - unsigned cpu; - int err = 0; - - for (cpu = 0; cpu < nr_cpu_ids; cpu++) { - cpui = &cpu_data(cpu); - if (!cpu_has(cpui, X86_FEATURE_MSR)) - continue; - - sprintf(cpu_dir, "cpu%d", cpu); - cpu_dentry = debugfs_create_dir(cpu_dir, cpu_debugfs_dir); - err = cpu_init_allreg(cpu, cpu_dentry); - - pr_info("cpu%d(%d) debug files %d\n", - cpu, nr_cpu_ids, per_cpu(cpu_priv_count, cpu)); - if (per_cpu(cpu_priv_count, cpu) > MAX_CPU_FILES) { - pr_err("Register files count %d exceeds limit %d\n", - per_cpu(cpu_priv_count, cpu), MAX_CPU_FILES); - per_cpu(cpu_priv_count, cpu) = MAX_CPU_FILES; - err = -ENFILE; - } - if (err) - return err; - } - - return err; -} - -static int __init cpu_debug_init(void) -{ - cpu_debugfs_dir = debugfs_create_dir("cpu", arch_debugfs_dir); - - return cpu_init_cpu(); -} - -static void __exit cpu_debug_exit(void) -{ - int i, cpu; - - if (cpu_debugfs_dir) - debugfs_remove_recursive(cpu_debugfs_dir); - - for (cpu = 0; cpu < nr_cpu_ids; cpu++) - for (i = 0; i < per_cpu(cpu_priv_count, cpu); i++) - kfree(per_cpu(priv_arr[i], cpu)); -} - -module_init(cpu_debug_init); -module_exit(cpu_debug_exit); - -MODULE_AUTHOR("Jaswinder Singh Rajput"); -MODULE_DESCRIPTION("CPU Debug module"); -MODULE_LICENSE("GPL"); From 63693ee86b7ebdcf8f08a40158782b6751bda3fc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jan 2010 16:18:09 +0900 Subject: [PATCH 510/670] libata: retry FS IOs even if it has failed with AC_ERR_INVALID commit 534ead709235b967b659947c55d9130873a432c4 upstream. libata currently doesn't retry if a command fails with AC_ERR_INVALID assuming that retrying won't get it any further even if retried. However, a failure may be classified as invalid through hardware glitch (incorrect reading of the error register or firmware bug) and there isn't whole lot to gain by not retrying as actually invalid commands will be failed immediately. Also, commands serving FS IOs are extremely unlikely to be invalid. Retry FS IOs even if it's marked invalid. Transient and incorrect invalid failure was seen while debugging firmware related issue on Samsung n130 on bko#14314. http://bugzilla.kernel.org/show_bug.cgi?id=14314 Signed-off-by: Tejun Heo Reported-by: Johannes Stezenbach Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-eh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index bba2ae5df1c2..7d8d3c3b4c80 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2019,8 +2019,9 @@ static void ata_eh_link_autopsy(struct ata_link *link) qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); /* determine whether the command is worth retrying */ - if (!(qc->err_mask & AC_ERR_INVALID) && - ((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV)) + if (qc->flags & ATA_QCFLAG_IO || + (!(qc->err_mask & AC_ERR_INVALID) && + qc->err_mask != AC_ERR_DEV)) qc->flags |= ATA_QCFLAG_RETRY; /* accumulate error info */ From 083beff011df31d82abe859479ab6c33af5504f5 Mon Sep 17 00:00:00 2001 From: Felix Beck Date: Wed, 27 Jan 2010 10:12:39 +0100 Subject: [PATCH 511/670] zcrypt: Do not remove coprocessor for error 8/72 commit 19b123ebacacdce5e75045bfe82122b01c821a5b upstream. In a case where the number of the input data is bigger than the modulus of the key, the coprocessor adapters will report an 8/72 error. This case is not caught yet, thus the adapter will be taken offline. To prevent this, we return an -EINVAL instead. Signed-off-by: Felix Beck Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- drivers/s390/crypto/zcrypt_pcicc.c | 2 ++ drivers/s390/crypto/zcrypt_pcixcc.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c index f4b0c4795434..7f1e3ba4bb64 100644 --- a/drivers/s390/crypto/zcrypt_pcicc.c +++ b/drivers/s390/crypto/zcrypt_pcicc.c @@ -373,6 +373,8 @@ static int convert_type86(struct zcrypt_device *zdev, zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD; return -EAGAIN; } + if (service_rc == 8 && service_rs == 72) + return -EINVAL; zdev->online = 0; return -EAGAIN; /* repeat the request on a different device. */ } diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index 5677b40e4ac0..1f9e92387208 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c @@ -462,6 +462,8 @@ static int convert_type86_ica(struct zcrypt_device *zdev, } if (service_rc == 12 && service_rs == 769) return -EINVAL; + if (service_rc == 8 && service_rs == 72) + return -EINVAL; zdev->online = 0; return -EAGAIN; /* repeat the request on a different device. */ } From 1e8896049716fd580718bb9431c2ad3bddd114d7 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Wed, 27 Jan 2010 10:12:35 +0100 Subject: [PATCH 512/670] dasd: fix possible NULL pointer errors commit 294001a80c9810e2fe27aaaad7df8be12a103065 upstream. Fix possible NULL pointer in DASD messages and correct discipline checking. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- drivers/s390/block/dasd.c | 8 ++++---- drivers/s390/block/dasd_eckd.c | 2 +- drivers/s390/block/dasd_ioctl.c | 7 ++----- drivers/s390/block/dasd_proc.c | 7 ++----- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index aaccc8ecfa8f..513dec940384 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1005,8 +1005,8 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, if (device == NULL || device != dasd_device_from_cdev_locked(cdev) || strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { - DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: " - "bus_id %s", dev_name(&cdev->dev)); + DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", + "invalid device in request"); return; } @@ -1078,8 +1078,8 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, device = (struct dasd_device *) cqr->startdev; if (!device || strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { - DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: " - "bus_id %s", dev_name(&cdev->dev)); + DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", + "invalid device in request"); return; } diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 417b97cd3f94..80c205bb95ac 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -2980,7 +2980,7 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, len += sprintf(page + len, KERN_ERR PRINTK_HEADER " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d\n", req, scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw), - scsw_cc(&irb->scsw), req->intrc); + scsw_cc(&irb->scsw), req ? req->intrc : 0); len += sprintf(page + len, KERN_ERR PRINTK_HEADER " device %s: Failing CCW: %p\n", dev_name(&device->cdev->dev), diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index f756a1b0c57a..a5354b83d728 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -260,7 +260,7 @@ static int dasd_ioctl_information(struct dasd_block *block, struct ccw_dev_id dev_id; base = block->base; - if (!base->discipline->fill_info) + if (!base->discipline || !base->discipline->fill_info) return -EINVAL; dasd_info = kzalloc(sizeof(struct dasd_information2_t), GFP_KERNEL); @@ -303,10 +303,7 @@ static int dasd_ioctl_information(struct dasd_block *block, dasd_info->features |= ((base->features & DASD_FEATURE_READONLY) != 0); - if (base->discipline) - memcpy(dasd_info->type, base->discipline->name, 4); - else - memcpy(dasd_info->type, "none", 4); + memcpy(dasd_info->type, base->discipline->name, 4); if (block->request_queue->request_fn) { struct list_head *l; diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 654daa3cdfda..f9d7d384fd12 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -71,7 +71,7 @@ dasd_devices_show(struct seq_file *m, void *v) /* Print device number. */ seq_printf(m, "%s", dev_name(&device->cdev->dev)); /* Print discipline string. */ - if (device != NULL && device->discipline != NULL) + if (device->discipline != NULL) seq_printf(m, "(%s)", device->discipline->name); else seq_printf(m, "(none)"); @@ -91,10 +91,7 @@ dasd_devices_show(struct seq_file *m, void *v) substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " "; seq_printf(m, "%4s: ", substr); /* Print device status information. */ - switch ((device != NULL) ? device->state : -1) { - case -1: - seq_printf(m, "unknown"); - break; + switch (device->state) { case DASD_STATE_NEW: seq_printf(m, "new"); break; From e62a96c8317c306d81ba5c690bf8f1be10e6cad9 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 29 Oct 2009 11:04:28 +0800 Subject: [PATCH 513/670] ACPI: Add a generic API for _OSC -v2 commit 70023de88c58a81a730ab4d13c51a30e537ec76e upstream. v2->v1: .improve debug info as suggedted by Bjorn,Kenji .API is using uuid string as suggested by Alexey Add an API to execute _OSC. A lot of devices can have this method, so add a generic API. Signed-off-by: Shaohua Li Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/bus.c | 122 +++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 9 ++++ 2 files changed, 131 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 741191524353..12240be58f27 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -344,6 +344,128 @@ bool acpi_bus_can_wakeup(acpi_handle handle) EXPORT_SYMBOL(acpi_bus_can_wakeup); +static void acpi_print_osc_error(acpi_handle handle, + struct acpi_osc_context *context, char *error) +{ + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER}; + int i; + + if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) + printk(KERN_DEBUG "%s\n", error); + else { + printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error); + kfree(buffer.pointer); + } + printk(KERN_DEBUG"_OSC request data:"); + for (i = 0; i < context->cap.length; i += sizeof(u32)) + printk("%x ", *((u32 *)(context->cap.pointer + i))); + printk("\n"); +} + +static u8 hex_val(unsigned char c) +{ + return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10; +} + +static acpi_status acpi_str_to_uuid(char *str, u8 *uuid) +{ + int i; + static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21, + 24, 26, 28, 30, 32, 34}; + + if (strlen(str) != 36) + return AE_BAD_PARAMETER; + for (i = 0; i < 36; i++) { + if (i == 8 || i == 13 || i == 18 || i == 23) { + if (str[i] != '-') + return AE_BAD_PARAMETER; + } else if (!isxdigit(str[i])) + return AE_BAD_PARAMETER; + } + for (i = 0; i < 16; i++) { + uuid[i] = hex_val(str[opc_map_to_uuid[i]]) << 4; + uuid[i] |= hex_val(str[opc_map_to_uuid[i] + 1]); + } + return AE_OK; +} + +acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) +{ + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[4]; + union acpi_object *out_obj; + u8 uuid[16]; + u32 errors; + + if (!context) + return AE_ERROR; + if (ACPI_FAILURE(acpi_str_to_uuid(context->uuid_str, uuid))) + return AE_ERROR; + context->ret.length = ACPI_ALLOCATE_BUFFER; + context->ret.pointer = NULL; + + /* Setting up input parameters */ + input.count = 4; + input.pointer = in_params; + in_params[0].type = ACPI_TYPE_BUFFER; + in_params[0].buffer.length = 16; + in_params[0].buffer.pointer = uuid; + in_params[1].type = ACPI_TYPE_INTEGER; + in_params[1].integer.value = context->rev; + in_params[2].type = ACPI_TYPE_INTEGER; + in_params[2].integer.value = context->cap.length/sizeof(u32); + in_params[3].type = ACPI_TYPE_BUFFER; + in_params[3].buffer.length = context->cap.length; + in_params[3].buffer.pointer = context->cap.pointer; + + status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret); + if (ACPI_FAILURE(status)) + return status; + + /* return buffer should have the same length as cap buffer */ + if (context->ret.length != context->cap.length) + return AE_NULL_OBJECT; + + out_obj = context->ret.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { + acpi_print_osc_error(handle, context, + "_OSC evaluation returned wrong type"); + status = AE_TYPE; + goto out_kfree; + } + /* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); + if (errors) { + if (errors & OSC_REQUEST_ERROR) + acpi_print_osc_error(handle, context, + "_OSC request failed"); + if (errors & OSC_INVALID_UUID_ERROR) + acpi_print_osc_error(handle, context, + "_OSC invalid UUID"); + if (errors & OSC_INVALID_REVISION_ERROR) + acpi_print_osc_error(handle, context, + "_OSC invalid revision"); + if (errors & OSC_CAPABILITIES_MASK_ERROR) { + if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE] + & OSC_QUERY_ENABLE) + goto out_success; + status = AE_SUPPORT; + goto out_kfree; + } + status = AE_ERROR; + goto out_kfree; + } +out_success: + return AE_OK; + +out_kfree: + kfree(context->ret.pointer); + context->ret.pointer = NULL; + return status; +} +EXPORT_SYMBOL(acpi_run_osc); + /* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index dfcd920c3e54..3247e09db20d 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -253,6 +253,13 @@ void __init acpi_old_suspend_ordering(void); void __init acpi_s4_no_nvs(void); #endif /* CONFIG_PM_SLEEP */ +struct acpi_osc_context { + char *uuid_str; /* uuid string */ + int rev; + struct acpi_buffer cap; /* arg2/arg3 */ + struct acpi_buffer ret; /* free by caller if success */ +}; + #define OSC_QUERY_TYPE 0 #define OSC_SUPPORT_TYPE 1 #define OSC_CONTROL_TYPE 2 @@ -265,6 +272,8 @@ void __init acpi_s4_no_nvs(void); #define OSC_INVALID_REVISION_ERROR 8 #define OSC_CAPABILITIES_MASK_ERROR 16 +acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); + /* _OSC DW1 Definition (OS Support Fields) */ #define OSC_EXT_PCI_CONFIG_SUPPORT 1 #define OSC_ACTIVE_STATE_PWR_SUPPORT 2 From 1a52addab3426e94879ce3638cb9daf9058d48fd Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 29 Oct 2009 11:05:05 +0800 Subject: [PATCH 514/670] ACPI: Add platform-wide _OSC support. commit 3563ff964fdc36358cef0330936fdac28e65142a upstream. Signed-off-by: Shaohua Li Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/bus.c | 26 ++++++++++++++++++++++++++ include/linux/acpi.h | 7 +++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 12240be58f27..65f7e335f122 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -466,6 +466,30 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) } EXPORT_SYMBOL(acpi_run_osc); +static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; +static void acpi_bus_osc_support(void) +{ + u32 capbuf[2]; + struct acpi_osc_context context = { + .uuid_str = sb_uuid_str, + .rev = 1, + .cap.length = 8, + .cap.pointer = capbuf, + }; + acpi_handle handle; + + capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; + capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ +#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR + capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; +#endif + if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) + return; + if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) + kfree(context.ret.pointer); + /* do we need to check the returned cap? Sounds no */ +} + /* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ @@ -856,6 +880,8 @@ static int __init acpi_bus_init(void) status = acpi_ec_ecdt_probe(); /* Ignore result. Not having an ECDT is not fatal. */ + acpi_bus_osc_support(); + status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 3247e09db20d..c010b94625c2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -274,6 +274,13 @@ struct acpi_osc_context { acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); +/* platform-wide _OSC bits */ +#define OSC_SB_PAD_SUPPORT 1 +#define OSC_SB_PPC_OST_SUPPORT 2 +#define OSC_SB_PR3_SUPPORT 4 +#define OSC_SB_CPUHP_OST_SUPPORT 8 +#define OSC_SB_APEI_SUPPORT 16 + /* _OSC DW1 Definition (OS Support Fields) */ #define OSC_EXT_PCI_CONFIG_SUPPORT 1 #define OSC_ACTIVE_STATE_PWR_SUPPORT 2 From 0d48a1a716844bc72f0e105418261024c75ce494 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 23 Dec 2009 17:04:11 +0800 Subject: [PATCH 515/670] ACPI: fix OSC regression that caused aer and pciehp not to load commit 9dc130fccb874f2959ef313d7922d306dc6d4f75 upstream. Executing _OSC returns a buffer, which has an acpi object in it. Don't directly returns the buffer, instead, we return the acpi object's buffer. This fixes a regression since caller of acpi_run_osc expects an acpi object's buffer returned. Tested-by: Yinghai Lu Signed-off-by: Shaohua Li Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/bus.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 65f7e335f122..0c1ad3105da1 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -397,6 +397,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) union acpi_object *out_obj; u8 uuid[16]; u32 errors; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; if (!context) return AE_ERROR; @@ -419,16 +420,16 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) in_params[3].buffer.length = context->cap.length; in_params[3].buffer.pointer = context->cap.pointer; - status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret); + status = acpi_evaluate_object(handle, "_OSC", &input, &output); if (ACPI_FAILURE(status)) return status; - /* return buffer should have the same length as cap buffer */ - if (context->ret.length != context->cap.length) + if (!output.length) return AE_NULL_OBJECT; - out_obj = context->ret.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) { + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER + || out_obj->buffer.length != context->cap.length) { acpi_print_osc_error(handle, context, "_OSC evaluation returned wrong type"); status = AE_TYPE; @@ -457,11 +458,20 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) goto out_kfree; } out_success: - return AE_OK; + context->ret.length = out_obj->buffer.length; + context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL); + if (!context->ret.pointer) { + status = AE_NO_MEMORY; + goto out_kfree; + } + memcpy(context->ret.pointer, out_obj->buffer.pointer, + context->ret.length); + status = AE_OK; out_kfree: - kfree(context->ret.pointer); - context->ret.pointer = NULL; + kfree(output.pointer); + if (status != AE_OK) + context->ret.pointer = NULL; return status; } EXPORT_SYMBOL(acpi_run_osc); From 3b4f785d6fd9df90b783e9a6ce9414884877593e Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 21:29:58 +0800 Subject: [PATCH 516/670] ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes commit 6a4e2b7503d1f630bface040cf0f5a7aac1fabdb upstream. If the BIOS pokes the system-wide OSC bits to see if Linux supports evaluating _OST after a _PPC change notification, answer yes. Also, fix an oversight where we neglected to set the OSC bit advertising processor aggregator device support when acpi-pad is compiled as a module. Signed-off-by: Zhao Yakui Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 0c1ad3105da1..49f6ededb6b5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -490,9 +490,14 @@ static void acpi_bus_osc_support(void) capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ -#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR +#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ + defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; #endif + +#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) + capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; +#endif if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) From cfc7e54cd19cabdadf803be3d6a04d89f2663aa5 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 26 Jan 2010 17:47:05 +0200 Subject: [PATCH 517/670] UBI: fix volume creation input checking commit c5ce5b46af76f52dea21f467397d24c4ae6cb3ff upstream. Do not use an unchecked variable UBI_IOCMKVOL ioctl. Signed-off-by: Mika Westerberg Signed-off-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/ubi/cdev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index f237ddbb2713..111ea41c4ecd 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -853,7 +853,6 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd, break; } - req.name[req.name_len] = '\0'; err = verify_mkvol_req(ubi, &req); if (err) break; From dff2267e0c21d0d478b29bc921e8ec4f0ea462e6 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 19 Jan 2010 14:15:38 +0000 Subject: [PATCH 518/670] e1000: enhance frame fragment detection commit 40a14deaf411592b57cb0720f0e8004293ab9865 upstream. Originally From: Neil Horman Modified by: Jesse Brandeburg Hey all- A security discussion was recently given: http://events.ccc.de/congress/2009/Fahrplan//events/3596.en.html And a patch that I submitted awhile back was brought up. Apparently some of their testing revealed that they were able to force a buffer fragment in e1000 in which the trailing fragment was greater than 4 bytes. As a result the fragment check I introduced failed to detect the fragement and a partial invalid frame was passed up into the network stack. I've written this patch to correct it. I'm in the process of testing it now, but it makes good logical sense to me. Effectively it maintains a per-adapter state variable which detects a non-EOP frame, and discards it and subsequent non-EOP frames leading up to _and_ _including_ the next positive-EOP frame (as it is by definition the last fragment). This should prevent any and all partial frames from entering the network stack from e1000. Signed-off-by: Jesse Brandeburg Acked-by: Neil Horman Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/e1000/e1000.h | 2 ++ drivers/net/e1000/e1000_main.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 42e2b7e21c29..4a2ee85d49a4 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -326,6 +326,8 @@ struct e1000_adapter { /* for ioport free */ int bars; int need_ioport; + + bool discarding; }; enum e1000_state_t { diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index bcd192ca47b0..44dec941381b 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3827,13 +3827,22 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); /* !EOP means multiple descriptors were used to store a single - * packet, also make sure the frame isn't just CRC only */ - if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) { + * packet, if thats the case we need to toss it. In fact, we + * to toss every packet with the EOP bit clear and the next + * frame that _does_ have the EOP bit set, as it is by + * definition only a frame fragment + */ + if (unlikely(!(status & E1000_RXD_STAT_EOP))) + adapter->discarding = true; + + if (adapter->discarding) { /* All receives must fit into a single buffer */ E1000_DBG("%s: Receive packet consumed multiple" " buffers\n", netdev->name); /* recycle */ buffer_info->skb = skb; + if (status & E1000_RXD_STAT_EOP) + adapter->discarding = false; goto next_desc; } From b9ad9bb6350ddfb943e30ddd9ece9d349f7b374d Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 19 Jan 2010 14:15:59 +0000 Subject: [PATCH 519/670] e1000e: enhance frame fragment detection commit b94b50289622e816adc9f94111cfc2679c80177c upstream. Originally patched by Neil Horman e1000e could with a jumbo frame enabled interface, and packet split disabled, receive a packet that would overflow a single rx buffer. While in practice very hard to craft a packet that could abuse this, it is possible. this is related to CVE-2009-4538 Signed-off-by: Jesse Brandeburg CC: Neil Horman Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/e1000e/e1000.h | 1 + drivers/net/e1000e/netdev.c | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 3e187b0e4203..47db9bd47199 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -417,6 +417,7 @@ struct e1000_info { /* CRC Stripping defines */ #define FLAG2_CRC_STRIPPING (1 << 0) #define FLAG2_HAS_PHY_WAKEUP (1 << 1) +#define FLAG2_IS_DISCARDING (1 << 2) #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index fad8f9ea0043..8eb66782b851 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -482,14 +482,24 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); - /* !EOP means multiple descriptors were used to store a single - * packet, also make sure the frame isn't just CRC only */ - if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) { + /* + * !EOP means multiple descriptors were used to store a single + * packet, if that's the case we need to toss it. In fact, we + * need to toss every packet with the EOP bit clear and the + * next frame that _does_ have the EOP bit set, as it is by + * definition only a frame fragment + */ + if (unlikely(!(status & E1000_RXD_STAT_EOP))) + adapter->flags2 |= FLAG2_IS_DISCARDING; + + if (adapter->flags2 & FLAG2_IS_DISCARDING) { /* All receives must fit into a single buffer */ e_dbg("%s: Receive packet consumed multiple buffers\n", netdev->name); /* recycle */ buffer_info->skb = skb; + if (status & E1000_RXD_STAT_EOP) + adapter->flags2 &= ~FLAG2_IS_DISCARDING; goto next_desc; } @@ -747,10 +757,16 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, PCI_DMA_FROMDEVICE); buffer_info->dma = 0; - if (!(staterr & E1000_RXD_STAT_EOP)) { + /* see !EOP comment in other rx routine */ + if (!(staterr & E1000_RXD_STAT_EOP)) + adapter->flags2 |= FLAG2_IS_DISCARDING; + + if (adapter->flags2 & FLAG2_IS_DISCARDING) { e_dbg("%s: Packet Split buffers didn't pick up the " "full packet\n", netdev->name); dev_kfree_skb_irq(skb); + if (staterr & E1000_RXD_STAT_EOP) + adapter->flags2 &= ~FLAG2_IS_DISCARDING; goto next_desc; } @@ -1120,6 +1136,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; + adapter->flags2 &= ~FLAG2_IS_DISCARDING; writel(0, adapter->hw.hw_addr + rx_ring->head); writel(0, adapter->hw.hw_addr + rx_ring->tail); From f0b4195748d200d4475e1ca976e7cabaf17e7c44 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 22 Jan 2010 22:56:16 +0000 Subject: [PATCH 520/670] e1000/e1000e: don't use small hardware rx buffers commit 9926146b15fd96d78a4f7c32e7a26d50639369f4 upstream. When testing the "e1000: enhance frame fragment detection" (and e1000e) patches we found some bugs with reducing the MTU size. The 1024 byte descriptor used with the 1000 mtu test also (re) introduced the (originally) reported bug, and causes us to need the e1000_clean_tx_irq "enhance frame fragment detection" fix. So what has occured here is that 2.6.32 is only vulnerable for mtu < 1500 due to the jumbo specific routines in both e1000 and e1000e. So, 2.6.32 needs the 2kB buffer len fix for those smaller MTUs, but is not vulnerable to the original issue reported. It has been pointed out that this vulnerability needs to be patched in older kernels that don't have the e1000 jumbo routine. Without the jumbo routines, we need the "enhance frame fragment detection" fix the e1000, old e1000e is only vulnerable for < 1500 mtu, and needs a similar fix. We split the patches up to provide easy backport paths. There is only a slight bit of extra code when this fix and the original "enhance frame fragment detection" fixes are applied, so please apply both, even though it is a bit of overkill. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/e1000/e1000_main.c | 20 +------------------- drivers/net/e1000e/netdev.c | 20 +------------------- 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 44dec941381b..1a23f168bebd 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1698,18 +1698,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; switch (adapter->rx_buffer_len) { - case E1000_RXBUFFER_256: - rctl |= E1000_RCTL_SZ_256; - rctl &= ~E1000_RCTL_BSEX; - break; - case E1000_RXBUFFER_512: - rctl |= E1000_RCTL_SZ_512; - rctl &= ~E1000_RCTL_BSEX; - break; - case E1000_RXBUFFER_1024: - rctl |= E1000_RCTL_SZ_1024; - rctl &= ~E1000_RCTL_BSEX; - break; case E1000_RXBUFFER_2048: default: rctl |= E1000_RCTL_SZ_2048; @@ -3154,13 +3142,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) * however with the new *_jumbo_rx* routines, jumbo receives will use * fragmented skbs */ - if (max_frame <= E1000_RXBUFFER_256) - adapter->rx_buffer_len = E1000_RXBUFFER_256; - else if (max_frame <= E1000_RXBUFFER_512) - adapter->rx_buffer_len = E1000_RXBUFFER_512; - else if (max_frame <= E1000_RXBUFFER_1024) - adapter->rx_buffer_len = E1000_RXBUFFER_1024; - else if (max_frame <= E1000_RXBUFFER_2048) + if (max_frame <= E1000_RXBUFFER_2048) adapter->rx_buffer_len = E1000_RXBUFFER_2048; else #if (PAGE_SIZE >= E1000_RXBUFFER_16384) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 8eb66782b851..21545306bc1d 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2347,18 +2347,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; switch (adapter->rx_buffer_len) { - case 256: - rctl |= E1000_RCTL_SZ_256; - rctl &= ~E1000_RCTL_BSEX; - break; - case 512: - rctl |= E1000_RCTL_SZ_512; - rctl &= ~E1000_RCTL_BSEX; - break; - case 1024: - rctl |= E1000_RCTL_SZ_1024; - rctl &= ~E1000_RCTL_BSEX; - break; case 2048: default: rctl |= E1000_RCTL_SZ_2048; @@ -4338,13 +4326,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) * fragmented skbs */ - if (max_frame <= 256) - adapter->rx_buffer_len = 256; - else if (max_frame <= 512) - adapter->rx_buffer_len = 512; - else if (max_frame <= 1024) - adapter->rx_buffer_len = 1024; - else if (max_frame <= 2048) + if (max_frame <= 2048) adapter->rx_buffer_len = 2048; else adapter->rx_buffer_len = 4096; From 61d4374b51386dd40c03fd15df5a7f97347de688 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Thu, 17 Dec 2009 16:12:56 +0800 Subject: [PATCH 521/670] drm/i915: Reload hangcheck timer too for Ironlake commit c566ec49159b806db95a90fd8f37448376cd0ad2 upstream. Make sure hangcheck timer won't beat us unexpectedly on Ironlake. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_irq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7d1357e54eef..2d468e9fb9e8 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -282,6 +282,8 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) dev_priv->mm.irq_gem_seqno = seqno; trace_i915_gem_request_complete(dev, seqno); DRM_WAKEUP(&dev_priv->irq_queue); + dev_priv->hangcheck_count = 0; + mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); } I915_WRITE(GTIIR, gt_iir); From 703c300c7415c0a2f25dbd7d2f8773a5abd84099 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 23 Jan 2010 23:38:27 -0500 Subject: [PATCH 522/670] Fix a leak in affs_fill_super() commit afc70ed05a07bfe171f7a5b8fdc80bdb073d314f upstream. Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/affs/super.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/affs/super.c b/fs/affs/super.c index 104fdcb3a7fc..b2a5958c6191 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -316,6 +316,8 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) &blocksize,&sbi->s_prefix, sbi->s_volume, &mount_flags)) { printk(KERN_ERR "AFFS: Error parsing options\n"); + kfree(sbi->s_prefix); + kfree(sbi); return -EINVAL; } /* N.B. after this point s_prefix must be released */ From deb20f1c49d390d3fcb62fa9789486f170054004 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Jan 2010 00:52:22 -0500 Subject: [PATCH 523/670] Fix failure exits in bfs_fill_super() commit 5998649f779b7148a8a0c10c46cfa99e27d34dfe upstream. double iput(), leaks... Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/bfs/inode.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 6f60336c6628..8f3d9fd89604 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -353,35 +353,35 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) struct inode *inode; unsigned i, imap_len; struct bfs_sb_info *info; - long ret = -EINVAL; + int ret = -EINVAL; unsigned long i_sblock, i_eblock, i_eoff, s_size; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; + mutex_init(&info->bfs_lock); s->s_fs_info = info; sb_set_blocksize(s, BFS_BSIZE); - bh = sb_bread(s, 0); - if(!bh) + info->si_sbh = sb_bread(s, 0); + if (!info->si_sbh) goto out; - bfs_sb = (struct bfs_super_block *)bh->b_data; + bfs_sb = (struct bfs_super_block *)info->si_sbh->b_data; if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) { if (!silent) printf("No BFS filesystem on %s (magic=%08x)\n", s->s_id, le32_to_cpu(bfs_sb->s_magic)); - goto out; + goto out1; } if (BFS_UNCLEAN(bfs_sb, s) && !silent) printf("%s is unclean, continuing\n", s->s_id); s->s_magic = BFS_MAGIC; - info->si_sbh = bh; if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end)) { printf("Superblock is corrupted\n"); - goto out; + goto out1; } info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / @@ -390,7 +390,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) imap_len = (info->si_lasti / 8) + 1; info->si_imap = kzalloc(imap_len, GFP_KERNEL); if (!info->si_imap) - goto out; + goto out1; for (i = 0; i < BFS_ROOT_INO; i++) set_bit(i, info->si_imap); @@ -398,15 +398,13 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) inode = bfs_iget(s, BFS_ROOT_INO); if (IS_ERR(inode)) { ret = PTR_ERR(inode); - kfree(info->si_imap); - goto out; + goto out2; } s->s_root = d_alloc_root(inode); if (!s->s_root) { iput(inode); ret = -ENOMEM; - kfree(info->si_imap); - goto out; + goto out2; } info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS; @@ -419,10 +417,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) bh = sb_bread(s, info->si_blocks - 1); if (!bh) { printf("Last block not available: %lu\n", info->si_blocks - 1); - iput(inode); ret = -EIO; - kfree(info->si_imap); - goto out; + goto out3; } brelse(bh); @@ -459,11 +455,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) printf("Inode 0x%08x corrupted\n", i); brelse(bh); - s->s_root = NULL; - kfree(info->si_imap); - kfree(info); - s->s_fs_info = NULL; - return -EIO; + ret = -EIO; + goto out3; } if (!di->i_ino) { @@ -483,11 +476,17 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) s->s_dirt = 1; } dump_imap("read_super", s); - mutex_init(&info->bfs_lock); return 0; +out3: + dput(s->s_root); + s->s_root = NULL; +out2: + kfree(info->si_imap); +out1: + brelse(info->si_sbh); out: - brelse(bh); + mutex_destroy(&info->bfs_lock); kfree(info); s->s_fs_info = NULL; return ret; From 26d2257801281a5bd2833d8f22cebead57a4b4c6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 25 Jan 2010 06:16:19 -0500 Subject: [PATCH 524/670] fix oops in fs/9p late mount failure commit 083c73c253c23c20359a344dfe1198ea628e6259 upstream. if 9P ->get_sb() fails late (at root inode or root dentry allocation), we'll hit its ->kill_sb() with NULL ->s_root Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/9p/vfs_super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 14a86448572c..69357c0d9899 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -188,7 +188,8 @@ static void v9fs_kill_super(struct super_block *s) P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); - v9fs_dentry_release(s->s_root); /* clunk root */ + if (s->s_root) + v9fs_dentry_release(s->s_root); /* clunk root */ kill_anon_super(s); From 36a0a4afb2e996f59651a845e5680d2f80cc6f23 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 25 Jan 2010 06:05:54 -0500 Subject: [PATCH 525/670] fix leak in romfs_fill_super() commit 7e32b7bb734047c5e3cecf2e896b9cf8fc35d1e8 upstream. Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/romfs/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/romfs/super.c b/fs/romfs/super.c index c117fa80d1e9..42d213546894 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c @@ -544,6 +544,7 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent) error_rsb_inval: ret = -EINVAL; error_rsb: + kfree(rsb); return ret; } From d842c31e636e5dbc85c3c75d1b964a6ff6e4daeb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Jan 2010 00:04:07 -0500 Subject: [PATCH 526/670] Fix remount races with symlink handling in affs commit 29333920a5a46edcc9b728e2cf0134d5a9b516ee upstream. A couple of fields in affs_sb_info is used in follow_link() and symlink() for handling AFFS "absolute" symlinks. Need locking against affs_remount() updates. Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/affs/affs.h | 2 +- fs/affs/namei.c | 7 +++++-- fs/affs/super.c | 17 ++++++++++++++--- fs/affs/symlink.c | 7 +++++-- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/fs/affs/affs.h b/fs/affs/affs.h index e511dc621a2e..0e40caaba456 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h @@ -106,8 +106,8 @@ struct affs_sb_info { u32 s_last_bmap; struct buffer_head *s_bmap_bh; char *s_prefix; /* Prefix for volumes and assigns. */ - int s_prefix_len; /* Length of prefix. */ char s_volume[32]; /* Volume prefix for absolute symlinks. */ + spinlock_t symlink_lock; /* protects the previous two */ }; #define SF_INTL 0x0001 /* International filesystem. */ diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 960d336ec694..d70bbbac6b7b 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -341,10 +341,13 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) p = (char *)AFFS_HEAD(bh)->table; lc = '/'; if (*symname == '/') { + struct affs_sb_info *sbi = AFFS_SB(sb); while (*symname == '/') symname++; - while (AFFS_SB(sb)->s_volume[i]) /* Cannot overflow */ - *p++ = AFFS_SB(sb)->s_volume[i++]; + spin_lock(&sbi->symlink_lock); + while (sbi->s_volume[i]) /* Cannot overflow */ + *p++ = sbi->s_volume[i++]; + spin_unlock(&sbi->symlink_lock); } while (i < maxlen && (c = *symname++)) { if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') { diff --git a/fs/affs/super.c b/fs/affs/super.c index b2a5958c6191..be6a6e8ed7d6 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -221,8 +221,6 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s *mount_opts |= SF_MUFS; break; case Opt_prefix: - /* Free any previous prefix */ - kfree(*prefix); *prefix = match_strdup(&args[0]); if (!*prefix) return 0; @@ -311,6 +309,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) return -ENOMEM; sb->s_fs_info = sbi; mutex_init(&sbi->s_bmlock); + spin_lock_init(&sbi->symlink_lock); if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, &blocksize,&sbi->s_prefix, @@ -518,14 +517,18 @@ affs_remount(struct super_block *sb, int *flags, char *data) unsigned long mount_flags; int res = 0; char *new_opts = kstrdup(data, GFP_KERNEL); + char volume[32]; + char *prefix = NULL; pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data); *flags |= MS_NODIRATIME; + memcpy(volume, sbi->s_volume, 32); if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block, - &blocksize, &sbi->s_prefix, sbi->s_volume, + &blocksize, &prefix, volume, &mount_flags)) { + kfree(prefix); kfree(new_opts); return -EINVAL; } @@ -536,6 +539,14 @@ affs_remount(struct super_block *sb, int *flags, char *data) sbi->s_mode = mode; sbi->s_uid = uid; sbi->s_gid = gid; + /* protect against readers */ + spin_lock(&sbi->symlink_lock); + if (prefix) { + kfree(sbi->s_prefix); + sbi->s_prefix = prefix; + } + memcpy(sbi->s_volume, volume, 32); + spin_unlock(&sbi->symlink_lock); if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { unlock_kernel(); diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index 41782539c907..ee00f08c4f53 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -20,7 +20,6 @@ static int affs_symlink_readpage(struct file *file, struct page *page) int i, j; char c; char lc; - char *pf; pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino); @@ -32,11 +31,15 @@ static int affs_symlink_readpage(struct file *file, struct page *page) j = 0; lf = (struct slink_front *)bh->b_data; lc = 0; - pf = AFFS_SB(inode->i_sb)->s_prefix ? AFFS_SB(inode->i_sb)->s_prefix : "/"; if (strchr(lf->symname,':')) { /* Handle assign or volume name */ + struct affs_sb_info *sbi = AFFS_SB(inode->i_sb); + char *pf; + spin_lock(&sbi->symlink_lock); + pf = sbi->s_prefix ? sbi->s_prefix : "/"; while (i < 1023 && (c = pf[i])) link[i++] = c; + spin_unlock(&sbi->symlink_lock); while (i < 1023 && lf->symname[j] != ':') link[i++] = lf->symname[j++]; if (i < 1023) From 30d3844a878b9d6adb2aa76961042f0c73c7de6c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Jan 2010 00:06:22 -0500 Subject: [PATCH 527/670] fix affs parse_options() commit 217686e98321a4ff4c1a6cc535e511e37c5d2dbf upstream. Error handling in that sucker got broken back in 2003. If function returns 0 on failure, it's not nice to add return -EINVAL into it. Adding return 1 on other failure exits is also not a good thing (and yes, original success exits with 1 and some of failure exits with 0 are still there; so's the original logics in callers). Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/affs/super.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/affs/super.c b/fs/affs/super.c index be6a6e8ed7d6..d41e9673cd97 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -203,7 +203,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s switch (token) { case Opt_bs: if (match_int(&args[0], &n)) - return -EINVAL; + return 0; if (n != 512 && n != 1024 && n != 2048 && n != 4096) { printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); @@ -213,7 +213,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s break; case Opt_mode: if (match_octal(&args[0], &option)) - return 1; + return 0; *mode = option & 0777; *mount_opts |= SF_SETMODE; break; @@ -231,21 +231,21 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s break; case Opt_reserved: if (match_int(&args[0], reserved)) - return 1; + return 0; break; case Opt_root: if (match_int(&args[0], root)) - return 1; + return 0; break; case Opt_setgid: if (match_int(&args[0], &option)) - return 1; + return 0; *gid = option; *mount_opts |= SF_SETGID; break; case Opt_setuid: if (match_int(&args[0], &option)) - return -EINVAL; + return 0; *uid = option; *mount_opts |= SF_SETUID; break; From 629527c562c1cfae09776c8baeb9a8a273dc10e6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 25 Jan 2010 18:44:58 -0500 Subject: [PATCH 528/670] Fix failure exit in ipathfs commit 12e9a45609054fb83d4a8b716a5265cc1a393e10 upstream. deactivate_locked_super() will be done by caller of fill_super, doing it there as well is b0rken. Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/hw/ipath/ipath_fs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index b3684060465e..100da8542bba 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -346,10 +346,8 @@ static int ipathfs_fill_super(struct super_block *sb, void *data, list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) { spin_unlock_irqrestore(&ipath_devs_lock, flags); ret = create_device_files(sb, dd); - if (ret) { - deactivate_locked_super(sb); + if (ret) goto bail; - } spin_lock_irqsave(&ipath_devs_lock, flags); } From 0b3bf81197f05e1bf0ed93c5f2525030b127faaa Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 29 Jan 2010 17:46:34 +0000 Subject: [PATCH 529/670] mm: fix migratetype bug which slowed swapping commit a7016235a61d520e6806f38129001d935c4b6661 upstream. After memory pressure has forced it to dip into the reserves, 2.6.32's 5f8dcc21211a3d4e3a7a5ca366b469fb88117f61 "page-allocator: split per-cpu list into one-list-per-migrate-type" has been returning MIGRATE_RESERVE pages to the MIGRATE_MOVABLE free_list: in some sense depleting reserves. Fix that in the most straightforward way (which, considering the overheads of alternative approaches, is Mel's preference): the right migratetype is already in page_private(page), but free_pcppages_bulk() wasn't using it. How did this bug show up? As a 20% slowdown in my tmpfs loop kbuild swapping tests, on PowerMac G5 with SLUB allocator. Bisecting to that commit was easy, but explaining the magnitude of the slowdown not easy. The same effect appears, but much less markedly, with SLAB, and even less markedly on other machines (the PowerMac divides into fewer zones than x86, I think that may be a factor). We guess that lumpy reclaim of short-lived high-order pages is implicated in some way, and probably this bug has been tickling a poor decision somewhere in page reclaim. But instrumentation hasn't told me much, I've run out of time and imagination to determine exactly what's going on, and shouldn't hold up the fix any longer: it's valid, and might even fix other misbehaviours. Signed-off-by: Hugh Dickins Acked-by: Mel Gorman Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/page_alloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3a78e2e864e8..36992b68500b 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -559,8 +559,9 @@ static void free_pcppages_bulk(struct zone *zone, int count, page = list_entry(list->prev, struct page, lru); /* must delete as __free_one_page list manipulates */ list_del(&page->lru); - __free_one_page(page, zone, 0, migratetype); - trace_mm_page_pcpu_drain(page, 0, migratetype); + /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */ + __free_one_page(page, zone, 0, page_private(page)); + trace_mm_page_pcpu_drain(page, 0, page_private(page)); } while (--count && --batch_free && !list_empty(list)); } spin_unlock(&zone->lock); From 944a638b7bb07f3ef9a33af60e5ea8465b7adfd1 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 6 Jan 2010 17:23:17 +0000 Subject: [PATCH 530/670] FDPIC: Respect PT_GNU_STACK exec protection markings when creating NOMMU stack commit 04e4f2b18c8de1389d1e00fef0f42a8099910daf upstream. The current code will load the stack size and protection markings, but then only use the markings in the MMU code path. The NOMMU code path always passes PROT_EXEC to the mmap() call. While this doesn't matter to most people whilst the code is running, it will cause a pointless icache flush when starting every FDPIC application. Typically this icache flush will be of a region on the order of 128KB in size, or may be the entire icache, depending on the facilities available on the CPU. In the case where the arch default behaviour seems to be desired (EXSTACK_DEFAULT), we probe VM_STACK_FLAGS for VM_EXEC to determine whether we should be setting PROT_EXEC or not. For arches that support an MPU (Memory Protection Unit - an MMU without the virtual mapping capability), setting PROT_EXEC or not will make an important difference. It should be noted that this change also affects the executability of the brk region, since ELF-FDPIC has that share with the stack. However, this is probably irrelevant as NOMMU programs aren't likely to use the brk region, preferring instead allocation via mmap(). Signed-off-by: Mike Frysinger Signed-off-by: David Howells Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/blackfin/include/asm/page.h | 5 +++++ arch/frv/include/asm/page.h | 2 -- fs/binfmt_elf_fdpic.c | 13 +++++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/blackfin/include/asm/page.h b/arch/blackfin/include/asm/page.h index 944a07c6cfd6..1d04e4078340 100644 --- a/arch/blackfin/include/asm/page.h +++ b/arch/blackfin/include/asm/page.h @@ -10,4 +10,9 @@ #include #define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT) +#define VM_DATA_DEFAULT_FLAGS \ + (VM_READ | VM_WRITE | \ + ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + #endif diff --git a/arch/frv/include/asm/page.h b/arch/frv/include/asm/page.h index 25c6a5002355..8c97068ac8fc 100644 --- a/arch/frv/include/asm/page.h +++ b/arch/frv/include/asm/page.h @@ -63,12 +63,10 @@ extern unsigned long max_pfn; #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) -#ifdef CONFIG_MMU #define VM_DATA_DEFAULT_FLAGS \ (VM_READ | VM_WRITE | \ ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -#endif #endif /* __ASSEMBLY__ */ diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 38502c67987c..456cfcf7da0d 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -170,6 +170,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, unsigned long stack_size, entryaddr; #ifdef ELF_FDPIC_PLAT_INIT unsigned long dynaddr; +#endif +#ifndef CONFIG_MMU + unsigned long stack_prot; #endif struct file *interpreter = NULL; /* to shut gcc up */ char *interpreter_name = NULL; @@ -316,6 +319,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, * defunct, deceased, etc. after this point we have to exit via * error_kill */ set_personality(PER_LINUX_FDPIC); + if (elf_read_implies_exec(&exec_params.hdr, executable_stack)) + current->personality |= READ_IMPLIES_EXEC; set_binfmt(&elf_fdpic_format); current->mm->start_code = 0; @@ -377,9 +382,13 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, if (stack_size < PAGE_SIZE * 2) stack_size = PAGE_SIZE * 2; + stack_prot = PROT_READ | PROT_WRITE; + if (executable_stack == EXSTACK_ENABLE_X || + (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC)) + stack_prot |= PROT_EXEC; + down_write(¤t->mm->mmap_sem); - current->mm->start_brk = do_mmap(NULL, 0, stack_size, - PROT_READ | PROT_WRITE | PROT_EXEC, + current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, 0); From 336ca4cc1f9d14edbb5d155b41aa301aaeb731c4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 28 Jan 2010 22:14:42 -0800 Subject: [PATCH 531/670] Split 'flush_old_exec' into two functions commit 221af7f87b97431e3ee21ce4b0e77d5411cf1549 upstream. 'flush_old_exec()' is the point of no return when doing an execve(), and it is pretty badly misnamed. It doesn't just flush the old executable environment, it also starts up the new one. Which is very inconvenient for things like setting up the new personality, because we want the new personality to affect the starting of the new environment, but at the same time we do _not_ want the new personality to take effect if flushing the old one fails. As a result, the x86-64 '32-bit' personality is actually done using this insane "I'm going to change the ABI, but I haven't done it yet" bit (TIF_ABI_PENDING), with SET_PERSONALITY() not actually setting the personality, but just the "pending" bit, so that "flush_thread()" can do the actual personality magic. This patch in no way changes any of that insanity, but it does split the 'flush_old_exec()' function up into a preparatory part that can fail (still called flush_old_exec()), and a new part that will actually set up the new exec environment (setup_new_exec()). All callers are changed to trivially comply with the new world order. Signed-off-by: H. Peter Anvin Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/sh/kernel/process_64.c | 2 +- arch/x86/ia32/ia32_aout.c | 10 ++++++---- fs/binfmt_aout.c | 1 + fs/binfmt_elf.c | 27 ++------------------------- fs/binfmt_elf_fdpic.c | 3 +++ fs/binfmt_flat.c | 1 + fs/binfmt_som.c | 1 + fs/exec.c | 26 ++++++++++++++++---------- include/linux/binfmts.h | 1 + include/linux/sched.h | 2 +- 10 files changed, 33 insertions(+), 41 deletions(-) diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 1192398ef582..44aa119df783 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -367,7 +367,7 @@ void exit_thread(void) void flush_thread(void) { - /* Called by fs/exec.c (flush_old_exec) to remove traces of a + /* Called by fs/exec.c (setup_new_exec) to remove traces of a * previously running executable. */ #ifdef CONFIG_SH_FPU if (last_task_used_math == current) { diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 2a4d073d2cf1..435d2a5323da 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -308,15 +308,17 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (retval) return retval; - regs->cs = __USER32_CS; - regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 = - regs->r13 = regs->r14 = regs->r15 = 0; - /* OK, This is the point of no return */ set_personality(PER_LINUX); set_thread_flag(TIF_IA32); clear_thread_flag(TIF_ABI_PENDING); + setup_new_exec(bprm); + + regs->cs = __USER32_CS; + regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 = + regs->r13 = regs->r14 = regs->r15 = 0; + current->mm->end_code = ex.a_text + (current->mm->start_code = N_TXTADDR(ex)); current->mm->end_data = ex.a_data + diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index b639dcf7c778..0133b5a30413 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -263,6 +263,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) #else set_personality(PER_LINUX); #endif + setup_new_exec(bprm); current->mm->end_code = ex.a_text + (current->mm->start_code = N_TXTADDR(ex)); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index b9b3bb51b1e4..1ed37ba72343 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -662,27 +662,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0') goto out_free_interp; - /* - * The early SET_PERSONALITY here is so that the lookup - * for the interpreter happens in the namespace of the - * to-be-execed image. SET_PERSONALITY can select an - * alternate root. - * - * However, SET_PERSONALITY is NOT allowed to switch - * this task into the new images's memory mapping - * policy - that is, TASK_SIZE must still evaluate to - * that which is appropriate to the execing application. - * This is because exit_mmap() needs to have TASK_SIZE - * evaluate to the size of the old image. - * - * So if (say) a 64-bit application is execing a 32-bit - * application it is the architecture's responsibility - * to defer changing the value of TASK_SIZE until the - * switch really is going to happen - do this in - * flush_thread(). - akpm - */ - SET_PERSONALITY(loc->elf_ex); - interpreter = open_exec(elf_interpreter); retval = PTR_ERR(interpreter); if (IS_ERR(interpreter)) @@ -730,9 +709,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) /* Verify the interpreter has a valid arch */ if (!elf_check_arch(&loc->interp_elf_ex)) goto out_free_dentry; - } else { - /* Executables without an interpreter also need a personality */ - SET_PERSONALITY(loc->elf_ex); } /* Flush all traces of the currently running executable */ @@ -752,7 +728,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) current->flags |= PF_RANDOMIZE; - arch_pick_mmap_layout(current->mm); + + setup_new_exec(bprm); /* Do this so that we can load the interpreter, if need be. We will change some of these later */ diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 456cfcf7da0d..e7a0bb47252c 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -321,6 +321,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, set_personality(PER_LINUX_FDPIC); if (elf_read_implies_exec(&exec_params.hdr, executable_stack)) current->personality |= READ_IMPLIES_EXEC; + + setup_new_exec(bprm); + set_binfmt(&elf_fdpic_format); current->mm->start_code = 0; diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index a2796651e756..ca88c4687b84 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -519,6 +519,7 @@ static int load_flat_file(struct linux_binprm * bprm, /* OK, This is the point of no return */ set_personality(PER_LINUX_32BIT); + setup_new_exec(bprm); } /* diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c index eff74b9c9e77..35cf0023ddb8 100644 --- a/fs/binfmt_som.c +++ b/fs/binfmt_som.c @@ -227,6 +227,7 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) /* OK, This is the point of no return */ current->flags &= ~PF_FORKNOEXEC; current->personality = PER_HPUX; + setup_new_exec(bprm); /* Set the task size for HP-UX processes such that * the gateway page is outside the address space. diff --git a/fs/exec.c b/fs/exec.c index ba112bd4a339..b2ad94e25da7 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -931,9 +931,7 @@ void set_task_comm(struct task_struct *tsk, char *buf) int flush_old_exec(struct linux_binprm * bprm) { - char * name; - int i, ch, retval; - char tcomm[sizeof(current->comm)]; + int retval; /* * Make sure we have a private signal table and that @@ -953,6 +951,20 @@ int flush_old_exec(struct linux_binprm * bprm) goto out; bprm->mm = NULL; /* We're using it now */ + return 0; + +out: + return retval; +} +EXPORT_SYMBOL(flush_old_exec); + +void setup_new_exec(struct linux_binprm * bprm) +{ + int i, ch; + char * name; + char tcomm[sizeof(current->comm)]; + + arch_pick_mmap_layout(current->mm); /* This is the point of no return */ current->sas_ss_sp = current->sas_ss_size = 0; @@ -1009,14 +1021,8 @@ int flush_old_exec(struct linux_binprm * bprm) flush_signal_handlers(current, 0); flush_old_files(current->files); - - return 0; - -out: - return retval; } - -EXPORT_SYMBOL(flush_old_exec); +EXPORT_SYMBOL(setup_new_exec); /* * Prepare credentials and lock ->cred_guard_mutex. diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index aece486ac734..340f441fbdfe 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -101,6 +101,7 @@ extern int prepare_binprm(struct linux_binprm *); extern int __must_check remove_arg_zero(struct linux_binprm *); extern int search_binary_handler(struct linux_binprm *,struct pt_regs *); extern int flush_old_exec(struct linux_binprm * bprm); +extern void setup_new_exec(struct linux_binprm * bprm); extern int suid_dumpable; #define SUID_DUMP_DISABLE 0 /* No setuid dumping */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 0f67914a43c9..d3dce7db81d6 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1354,7 +1354,7 @@ struct task_struct { char comm[TASK_COMM_LEN]; /* executable name excluding path - access with [gs]et_task_comm (which lock it with task_lock()) - - initialized normally by flush_old_exec */ + - initialized normally by setup_new_exec */ /* file system info */ int link_count, total_link_count; #ifdef CONFIG_SYSVIPC From c2e245dff59d14f94d2befddcbfa4c667ac23eb0 Mon Sep 17 00:00:00 2001 From: David Miller Date: Thu, 28 Jan 2010 21:42:02 -0800 Subject: [PATCH 532/670] sparc: TIF_ABI_PENDING bit removal commit 94673e968cbcce07fa78dac4b0ae05d24b5816e1 upstream. Here are the sparc bits to remove TIF_ABI_PENDING now that set_personality() is called at the appropriate place in exec. Signed-off-by: David S. Miller Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/sparc/include/asm/elf_64.h | 13 +++---------- arch/sparc/include/asm/thread_info_64.h | 4 +--- arch/sparc/kernel/process_64.c | 8 -------- 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h index d42e393078c4..996808587914 100644 --- a/arch/sparc/include/asm/elf_64.h +++ b/arch/sparc/include/asm/elf_64.h @@ -196,17 +196,10 @@ static inline unsigned int sparc64_elf_hwcap(void) #define ELF_PLATFORM (NULL) #define SET_PERSONALITY(ex) \ -do { unsigned long new_flags = current_thread_info()->flags; \ - new_flags &= _TIF_32BIT; \ - if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ - new_flags |= _TIF_32BIT; \ +do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ + set_thread_flag(TIF_32BIT); \ else \ - new_flags &= ~_TIF_32BIT; \ - if ((current_thread_info()->flags & _TIF_32BIT) \ - != new_flags) \ - set_thread_flag(TIF_ABI_PENDING); \ - else \ - clear_thread_flag(TIF_ABI_PENDING); \ + clear_thread_flag(TIF_32BIT); \ /* flush_thread will update pgd cache */ \ if (personality(current->personality) != PER_LINUX32) \ set_personality(PER_LINUX | \ diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index 1b45a7bbe407..f78ad9a1b497 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -227,12 +227,11 @@ register struct thread_info *current_thread_info_reg asm("g6"); /* flag bit 8 is available */ #define TIF_SECCOMP 9 /* secure computing */ #define TIF_SYSCALL_AUDIT 10 /* syscall auditing active */ -/* flag bit 11 is available */ /* NOTE: Thread flags >= 12 should be ones we have no interest * in using in assembly, else we can't use the mask as * an immediate value in instructions such as andcc. */ -#define TIF_ABI_PENDING 12 +/* flag bit 12 is available */ #define TIF_MEMDIE 13 #define TIF_POLLING_NRFLAG 14 #define TIF_FREEZE 15 /* is freezing for suspend */ @@ -246,7 +245,6 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define _TIF_32BIT (1<task->mm; if (mm) tsb_context_switch(mm); From 5e806e1c71412081bdc0058c43595eb63d06a606 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 28 Jan 2010 22:14:43 -0800 Subject: [PATCH 533/670] x86: get rid of the insane TIF_ABI_PENDING bit commit 05d43ed8a89c159ff641d472f970e3f1baa66318 upstream. Now that the previous commit made it possible to do the personality setting at the point of no return, we do just that for ELF binaries. And suddenly all the reasons for that insane TIF_ABI_PENDING bit go away, and we can just make SET_PERSONALITY() just do the obvious thing for a 32-bit compat process. Everything becomes much more straightforward this way. Signed-off-by: H. Peter Anvin Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/x86/ia32/ia32_aout.c | 1 - arch/x86/include/asm/elf.h | 10 ++-------- arch/x86/include/asm/thread_info.h | 2 -- arch/x86/kernel/process.c | 12 ------------ arch/x86/kernel/process_64.c | 11 +++++++++++ 5 files changed, 13 insertions(+), 23 deletions(-) diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 435d2a5323da..f9f472462753 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -311,7 +311,6 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) /* OK, This is the point of no return */ set_personality(PER_LINUX); set_thread_flag(TIF_IA32); - clear_thread_flag(TIF_ABI_PENDING); setup_new_exec(bprm); diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 456a304b8172..8ac9d9ae129e 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -197,14 +197,8 @@ do { \ set_fs(USER_DS); \ } while (0) -#define COMPAT_SET_PERSONALITY(ex) \ -do { \ - if (test_thread_flag(TIF_IA32)) \ - clear_thread_flag(TIF_ABI_PENDING); \ - else \ - set_thread_flag(TIF_ABI_PENDING); \ - current->personality |= force_personality32; \ -} while (0) +void set_personality_ia32(void); +#define COMPAT_SET_PERSONALITY(ex) set_personality_ia32() #define COMPAT_ELF_PLATFORM ("i686") diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index d27d0a2fec4c..19c3ce4aaea7 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -86,7 +86,6 @@ struct thread_info { #define TIF_NOTSC 16 /* TSC is not accessible in userland */ #define TIF_IA32 17 /* 32bit process */ #define TIF_FORK 18 /* ret_from_fork */ -#define TIF_ABI_PENDING 19 #define TIF_MEMDIE 20 #define TIF_DEBUG 21 /* uses debug registers */ #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ @@ -110,7 +109,6 @@ struct thread_info { #define _TIF_NOTSC (1 << TIF_NOTSC) #define _TIF_IA32 (1 << TIF_IA32) #define _TIF_FORK (1 << TIF_FORK) -#define _TIF_ABI_PENDING (1 << TIF_ABI_PENDING) #define _TIF_DEBUG (1 << TIF_DEBUG) #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) #define _TIF_FREEZE (1 << TIF_FREEZE) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 5284cd2b5776..f010ab424f1f 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -91,18 +91,6 @@ void flush_thread(void) { struct task_struct *tsk = current; -#ifdef CONFIG_X86_64 - if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) { - clear_tsk_thread_flag(tsk, TIF_ABI_PENDING); - if (test_tsk_thread_flag(tsk, TIF_IA32)) { - clear_tsk_thread_flag(tsk, TIF_IA32); - } else { - set_tsk_thread_flag(tsk, TIF_IA32); - current_thread_info()->status |= TS_COMPAT; - } - } -#endif - clear_tsk_thread_flag(tsk, TIF_DEBUG); tsk->thread.debugreg0 = 0; diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index eb62cbcaa490..f9ce04f61003 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -540,6 +540,17 @@ sys_clone(unsigned long clone_flags, unsigned long newsp, return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); } +void set_personality_ia32(void) +{ + /* inherit personality from parent */ + + /* Make sure to be in 32bit mode */ + set_thread_flag(TIF_IA32); + + /* Prepare the first "return" to user space */ + current_thread_info()->status |= TS_COMPAT; +} + unsigned long get_wchan(struct task_struct *p) { unsigned long stack; From cf135e5571317539a44bf3022f4f2c14a64edaa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 28 Jan 2010 22:28:27 -0800 Subject: [PATCH 534/670] Input: winbond-cir - remove dmesg spam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 93fb84b50fe03aabca8d9dea5d3ba521a07e8571 upstream. I missed converting one dev_info call to deb_dbg before submitting the driver. Without this change, a message will be printed to dmesg for each button press if a RC6 remote is used. Signed-off-by: David Härdeman Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/misc/winbond-cir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c index 33309fe44e20..c8f5a9a3fa14 100644 --- a/drivers/input/misc/winbond-cir.c +++ b/drivers/input/misc/winbond-cir.c @@ -768,7 +768,7 @@ wbcir_parse_rc6(struct device *dev, struct wbcir_data *data) return; } - dev_info(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X " + dev_dbg(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X " "toggle %u mode %u scan 0x%08X\n", address, command, From 3492bbb3afd5fd9fa873015691004797371ec373 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Fri, 29 Jan 2010 11:27:31 -0800 Subject: [PATCH 535/670] x86: Disable HPET MSI on ATI SB700/SB800 commit 73472a46b5b28116b145fb5fc05242c1aa8e1461 upstream HPET MSI on platforms with ATI SB700/SB800 as they seem to have some side-effects on floppy DMA. Do not use HPET MSI on such platforms. Original problem report from Mark Hounschell http://lkml.indiana.edu/hypermail/linux/kernel/0912.2/01118.html Tested-by: Mark Hounschell Signed-off-by: Venkatesh Pallipadi Cc: LKML-Reference: <20100121190952.GA32523@linux-os.sc.intel.com> Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/hpet.h | 1 + arch/x86/kernel/hpet.c | 8 ++++++++ arch/x86/kernel/quirks.c | 13 +++++++++++++ 3 files changed, 22 insertions(+) diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h index 1c22cb05ad6a..3251e2316a7a 100644 --- a/arch/x86/include/asm/hpet.h +++ b/arch/x86/include/asm/hpet.h @@ -66,6 +66,7 @@ extern unsigned long hpet_address; extern unsigned long force_hpet_address; extern int hpet_force_user; +extern u8 hpet_msi_disable; extern int is_hpet_enabled(void); extern int hpet_enable(void); extern void hpet_disable(void); diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index dedc2bddf7a5..58778736496a 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -33,6 +33,8 @@ * HPET address is set in acpi/boot.c, when an ACPI entry exists */ unsigned long hpet_address; +u8 hpet_msi_disable; + #ifdef CONFIG_PCI_MSI static unsigned long hpet_num_timers; #endif @@ -584,6 +586,9 @@ static void hpet_msi_capability_lookup(unsigned int start_timer) unsigned int num_timers_used = 0; int i; + if (hpet_msi_disable) + return; + id = hpet_readl(HPET_ID); num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT); @@ -911,6 +916,9 @@ static __init int hpet_late_init(void) hpet_reserve_platform_timers(hpet_readl(HPET_ID)); hpet_print_config(); + if (hpet_msi_disable) + return 0; + for_each_online_cpu(cpu) { hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu); } diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 6c3b2c6fd772..0040164f1a82 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -491,6 +491,19 @@ void force_hpet_resume(void) break; } } + +/* + * HPET MSI on some boards (ATI SB700/SB800) has side effect on + * floppy DMA. Disable HPET MSI on such platforms. + */ +static void force_disable_hpet_msi(struct pci_dev *unused) +{ + hpet_msi_disable = 1; +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, + force_disable_hpet_msi); + #endif #if defined(CONFIG_PCI) && defined(CONFIG_NUMA) From 69bf9a60ba1577e437c36a260bb02e7e79ed7ccc Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 2 Oct 2009 13:44:01 -0700 Subject: [PATCH 536/670] iwlwifi: set default aggregation frame count limit to 31 commit 4d80d7210bb5a36a18978d1305b44375ecb857d9 upstream. Multiple MPDUs can be aggregated, transmitted, and finally acknowledged together using a single BA frame. Block ACK (BA) contains bitmap size of 64*16 bits so the maximum frame count is 64. The default value of aggregation frame count suggested by uCode is 31 to achieve best performance. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 81726ee32858..0eb25916f81d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2808,7 +2808,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, repeat_rate--; } - lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX; + lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; lq_cmd->agg_params.agg_time_limit = cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); From 612e99b2d1ba8839896c6ea78d4329782d4e16b8 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 11 Dec 2009 11:07:17 -0800 Subject: [PATCH 537/670] drm/i915: only enable hotplug for detected outputs commit b01f2c3a4a37d09a47ad73ccbb46d554d21cfeb0 upstream. This patch changes around our hotplug enable code a bit to only enable it for ports we actually detect and initialize. This prevents problems with stuck or spurious interrupts on outputs that aren't actually wired up, and is generally more correct. Fixes FDO bug #23183. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 4 ++-- drivers/gpu/drm/i915/i915_irq.c | 30 ++++++++++++++++++---------- drivers/gpu/drm/i915/i915_reg.h | 8 -------- drivers/gpu/drm/i915/intel_crt.c | 2 ++ drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++------ drivers/gpu/drm/i915/intel_dp.c | 6 ++++++ drivers/gpu/drm/i915/intel_hdmi.c | 5 +++++ drivers/gpu/drm/i915/intel_sdvo.c | 3 +++ drivers/gpu/drm/i915/intel_tv.c | 2 ++ 9 files changed, 59 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index bc2db7d16d18..eaa1893b6e9b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1252,6 +1252,8 @@ static int i915_load_modeset_init(struct drm_device *dev, if (ret) goto destroy_ringbuffer; + intel_modeset_init(dev); + ret = drm_irq_install(dev); if (ret) goto destroy_ringbuffer; @@ -1266,8 +1268,6 @@ static int i915_load_modeset_init(struct drm_device *dev, I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); - intel_modeset_init(dev); - drm_helper_initial_config(dev); return 0; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2d468e9fb9e8..63f28adf6509 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1044,6 +1044,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev) (void) I915_READ(IER); } +/* + * Must be called after intel_modeset_init or hotplug interrupts won't be + * enabled correctly. + */ int i915_driver_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1066,19 +1070,23 @@ int i915_driver_irq_postinstall(struct drm_device *dev) if (I915_HAS_HOTPLUG(dev)) { u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); - /* Leave other bits alone */ - hotplug_en |= HOTPLUG_EN_MASK; + /* Note HDMI and DP share bits */ + if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) + hotplug_en |= HDMID_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) + hotplug_en |= CRT_HOTPLUG_INT_EN; + /* Ignore TV since it's buggy */ + I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); - dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS | - TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS | - SDVOB_HOTPLUG_INT_STATUS; - if (IS_G4X(dev)) { - dev_priv->hotplug_supported_mask |= - HDMIB_HOTPLUG_INT_STATUS | - HDMIC_HOTPLUG_INT_STATUS | - HDMID_HOTPLUG_INT_STATUS; - } /* Enable in IER... */ enable_mask |= I915_DISPLAY_PORT_INTERRUPT; /* and unmask in IMR */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 54e5907723d7..fd537f4af52c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -863,14 +863,6 @@ #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) #define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ #define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f -#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \ - HDMIC_HOTPLUG_INT_EN | \ - HDMID_HOTPLUG_INT_EN | \ - SDVOB_HOTPLUG_INT_EN | \ - SDVOC_HOTPLUG_INT_EN | \ - TV_HOTPLUG_INT_EN | \ - CRT_HOTPLUG_INT_EN) - #define PORT_HOTPLUG_STAT 0x61114 #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index e5051446c48e..6d3730f327cf 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -576,4 +576,6 @@ void intel_crt_init(struct drm_device *dev) drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); drm_sysfs_connector_add(connector); + + dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 121b92e0eec7..601415dc17bf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4068,29 +4068,43 @@ static void intel_setup_outputs(struct drm_device *dev) bool found = false; if (I915_READ(SDVOB) & SDVO_DETECTED) { + DRM_DEBUG_KMS("probing SDVOB\n"); found = intel_sdvo_init(dev, SDVOB); - if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) + if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) { + DRM_DEBUG_KMS("probing HDMI on SDVOB\n"); intel_hdmi_init(dev, SDVOB); + } - if (!found && SUPPORTS_INTEGRATED_DP(dev)) + if (!found && SUPPORTS_INTEGRATED_DP(dev)) { + DRM_DEBUG_KMS("probing DP_B\n"); intel_dp_init(dev, DP_B); + } } /* Before G4X SDVOC doesn't have its own detect register */ - if (I915_READ(SDVOB) & SDVO_DETECTED) + if (I915_READ(SDVOB) & SDVO_DETECTED) { + DRM_DEBUG_KMS("probing SDVOC\n"); found = intel_sdvo_init(dev, SDVOC); + } if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) { - if (SUPPORTS_INTEGRATED_HDMI(dev)) + if (SUPPORTS_INTEGRATED_HDMI(dev)) { + DRM_DEBUG_KMS("probing HDMI on SDVOC\n"); intel_hdmi_init(dev, SDVOC); - if (SUPPORTS_INTEGRATED_DP(dev)) + } + if (SUPPORTS_INTEGRATED_DP(dev)) { + DRM_DEBUG_KMS("probing DP_C\n"); intel_dp_init(dev, DP_C); + } } - if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) + if (SUPPORTS_INTEGRATED_DP(dev) && + (I915_READ(DP_D) & DP_DETECTED)) { + DRM_DEBUG_KMS("probing DP_D\n"); intel_dp_init(dev, DP_D); + } } else if (IS_I8XX(dev)) intel_dvo_init(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 92a3d7b0d009..d487771d5434 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1290,14 +1290,20 @@ intel_dp_init(struct drm_device *dev, int output_reg) break; case DP_B: case PCH_DP_B: + dev_priv->hotplug_supported_mask |= + HDMIB_HOTPLUG_INT_STATUS; name = "DPDDC-B"; break; case DP_C: case PCH_DP_C: + dev_priv->hotplug_supported_mask |= + HDMIC_HOTPLUG_INT_STATUS; name = "DPDDC-C"; break; case DP_D: case PCH_DP_D: + dev_priv->hotplug_supported_mask |= + HDMID_HOTPLUG_INT_STATUS; name = "DPDDC-D"; break; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c33451aec1bd..85760bf7ffa5 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -254,21 +254,26 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) if (sdvox_reg == SDVOB) { intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); + dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; } else if (sdvox_reg == SDVOC) { intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); + dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; } else if (sdvox_reg == HDMIB) { intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, "HDMIB"); + dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; } else if (sdvox_reg == HDMIC) { intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, "HDMIC"); + dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; } else if (sdvox_reg == HDMID) { intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, "HDMID"); + dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; } if (!intel_output->ddc_bus) goto err_connector; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 29e21d32f9ce..3f5aaf14e6a3 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2743,6 +2743,7 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector) bool intel_sdvo_init(struct drm_device *dev, int output_device) { + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_connector *connector; struct intel_output *intel_output; struct intel_sdvo_priv *sdvo_priv; @@ -2789,10 +2790,12 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, "SDVOB/VGA DDC BUS"); + dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; } else { intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, "SDVOC/VGA DDC BUS"); + dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; } if (intel_output->ddc_bus == NULL) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 5b28b4e7ebe7..ce026f002ea5 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1801,6 +1801,8 @@ intel_tv_init(struct drm_device *dev) drm_connector_attach_property(connector, dev->mode_config.tv_bottom_margin_property, tv_priv->margin[TV_MARGIN_BOTTOM]); + + dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS; out: drm_sysfs_connector_add(connector); } From 80569f607b59fb59d0e7d86ae6467fefcab8e89b Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 29 Jan 2010 21:25:46 +0100 Subject: [PATCH 538/670] firewire: core: add_descriptor size check Backport of commit e300839da40e99581581c5d053a95a172651fec8 upstream. Presently, firewire-core only checks whether descriptors that are to be added by userspace drivers to the local node's config ROM do not exceed a size of 256 quadlets. However, the sum of the bare minimum ROM plus all descriptors (from firewire-core, from firewire-net, from userspace) must not exceed 256 quadlets. Otherwise, the bounds of a statically allocated buffer will be overwritten. If the kernel survives that, firewire-core will subsequently be unable to parse the local node's config ROM. (Note, userspace drivers can add descriptors only through device files of local nodes. These are usually only accessible by root, unlike device files of remote nodes which may be accessible to lesser privileged users.) Therefore add a test which takes the actual present and required ROM size into account for all descriptors of kernelspace and userspace drivers. Signed-off-by: Stefan Richter Signed-off-by: Greg Kroah-Hartman --- drivers/firewire/core-card.c | 42 +++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index e4864e894e4f..ed635ae2b5d3 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -57,6 +57,9 @@ static LIST_HEAD(card_list); static LIST_HEAD(descriptor_list); static int descriptor_count; +/* ROM header, bus info block, root dir header, capabilities = 7 quadlets */ +static size_t config_rom_length = 1 + 4 + 1 + 1; + #define BIB_CRC(v) ((v) << 0) #define BIB_CRC_LENGTH(v) ((v) << 16) #define BIB_INFO_LENGTH(v) ((v) << 24) @@ -72,7 +75,7 @@ static int descriptor_count; #define BIB_CMC ((1) << 30) #define BIB_IMC ((1) << 31) -static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) +static u32 *generate_config_rom(struct fw_card *card) { struct fw_descriptor *desc; static u32 config_rom[256]; @@ -131,7 +134,7 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) for (i = 0; i < j; i += length + 1) length = fw_compute_block_crc(config_rom + i); - *config_rom_length = j; + WARN_ON(j != config_rom_length); return config_rom; } @@ -140,17 +143,24 @@ static void update_config_roms(void) { struct fw_card *card; u32 *config_rom; - size_t length; list_for_each_entry (card, &card_list, link) { - config_rom = generate_config_rom(card, &length); - card->driver->set_config_rom(card, config_rom, length); + config_rom = generate_config_rom(card); + card->driver->set_config_rom(card, config_rom, + config_rom_length); } } +static size_t required_space(struct fw_descriptor *desc) +{ + /* descriptor + entry into root dir + optional immediate entry */ + return desc->length + 1 + (desc->immediate > 0 ? 1 : 0); +} + int fw_core_add_descriptor(struct fw_descriptor *desc) { size_t i; + int ret; /* * Check descriptor is valid; the length of all blocks in the @@ -166,15 +176,21 @@ int fw_core_add_descriptor(struct fw_descriptor *desc) mutex_lock(&card_mutex); - list_add_tail(&desc->link, &descriptor_list); - descriptor_count++; - if (desc->immediate > 0) + if (config_rom_length + required_space(desc) > 256) { + ret = -EBUSY; + } else { + list_add_tail(&desc->link, &descriptor_list); + config_rom_length += required_space(desc); descriptor_count++; - update_config_roms(); + if (desc->immediate > 0) + descriptor_count++; + update_config_roms(); + ret = 0; + } mutex_unlock(&card_mutex); - return 0; + return ret; } EXPORT_SYMBOL(fw_core_add_descriptor); @@ -183,6 +199,7 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc) mutex_lock(&card_mutex); list_del(&desc->link); + config_rom_length -= required_space(desc); descriptor_count--; if (desc->immediate > 0) descriptor_count--; @@ -436,7 +453,6 @@ int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid) { u32 *config_rom; - size_t length; int ret; card->max_receive = max_receive; @@ -445,8 +461,8 @@ int fw_card_add(struct fw_card *card, mutex_lock(&card_mutex); - config_rom = generate_config_rom(card, &length); - ret = card->driver->enable(card, config_rom, length); + config_rom = generate_config_rom(card); + ret = card->driver->enable(card, config_rom, config_rom_length); if (ret == 0) list_add_tail(&card->link, &card_list); From 6db6aced4d9eb83872d6b63dfd95e3c9d2de37c2 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 28 Aug 2009 10:47:16 +0200 Subject: [PATCH 539/670] SECURITY: selinux, fix update_rlimit_cpu parameter commit 17740d89785aeb4143770923d67c293849414710 upstream. Don't pass current RLIMIT_RTTIME to update_rlimit_cpu() in selinux_bprm_committing_creds, since update_rlimit_cpu expects RLIMIT_CPU limit. Use proper rlim[RLIMIT_CPU].rlim_cur instead to fix that. Signed-off-by: Jiri Slaby Acked-by: James Morris Cc: Stephen Smalley Cc: Eric Paris Cc: David Howells Signed-off-by: Greg Kroah-Hartman --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index bb230d5d7085..36d9e25688f8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2366,7 +2366,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) initrlim = init_task.signal->rlim + i; rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); } - update_rlimit_cpu(rlim->rlim_cur); + update_rlimit_cpu(current->signal->rlim[RLIMIT_CPU].rlim_cur); } } From 00362b9adebdca260ae03717665a16f6948a6a4a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 4 Jan 2010 15:30:54 +0000 Subject: [PATCH 540/670] regulator: Specify REGULATOR_CHANGE_STATUS for WM835x LED constraints commit a2fad9bf26a1d44a8d31a5c4528108a2b9f468ab upstream. The WM8350 LED driver needs to be able to enable and disable the regulators it is using. Previously the core wasn't properly enforcing status change constraints so the driver was able to function but this has always been intended to be required. Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/wm8350-regulator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 768bd0e5b48b..43ed81e56fef 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1504,7 +1504,8 @@ int wm8350_register_led(struct wm8350 *wm8350, int lednum, int dcdc, int isink, led->isink_init.consumer_supplies = &led->isink_consumer; led->isink_init.constraints.min_uA = 0; led->isink_init.constraints.max_uA = pdata->max_uA; - led->isink_init.constraints.valid_ops_mask = REGULATOR_CHANGE_CURRENT; + led->isink_init.constraints.valid_ops_mask + = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS; led->isink_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL; ret = wm8350_register_regulator(wm8350, isink, &led->isink_init); if (ret != 0) { @@ -1517,6 +1518,7 @@ int wm8350_register_led(struct wm8350 *wm8350, int lednum, int dcdc, int isink, led->dcdc_init.num_consumer_supplies = 1; led->dcdc_init.consumer_supplies = &led->dcdc_consumer; led->dcdc_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL; + led->dcdc_init.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; ret = wm8350_register_regulator(wm8350, dcdc, &led->dcdc_init); if (ret != 0) { platform_device_put(pdev); From 81590709e68af85629f969a305abab5e39649ad2 Mon Sep 17 00:00:00 2001 From: Leann Ogasawara Date: Wed, 27 Jan 2010 15:29:18 -0800 Subject: [PATCH 541/670] x86: Add Dell OptiPlex 760 reboot quirk commit 35ea63d70f827a26c150993b4b940925bb02b03f upstream. Dell OptiPlex 760 hangs on reboot unless reboot=bios is used. Add quirk to reboot through the BIOS. BugLink: https://bugs.launchpad.net/bugs/488319 Signed-off-by: Leann Ogasawara LKML-Reference: <1264634958.27335.1091.camel@emiko> Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/reboot.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 6caf26010970..bff34d68d9d1 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -203,6 +203,15 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "0T656F"), }, }, + { /* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G*/ + .callback = set_bios_reboot, + .ident = "Dell OptiPlex 760", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"), + DMI_MATCH(DMI_BOARD_NAME, "0G919G"), + }, + }, { /* Handle problems with rebooting on Dell 2400's */ .callback = set_bios_reboot, .ident = "Dell PowerEdge 2400", From d1a31038aadf0fb13befb444e60d96f3618766d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 28 Jan 2010 21:02:54 +0100 Subject: [PATCH 542/670] x86: Add quirk for Intel DG45FC board to avoid low memory corruption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7c099ce1575126395f186ecf58b51a60d5c3be7d upstream. Commit 6aa542a694dc9ea4344a8a590d2628c33d1b9431 added a quirk for the Intel DG45ID board due to low memory corruption. The Intel DG45FC shares the same BIOS (and the same bug) as noted in: http://bugzilla.kernel.org/show_bug.cgi?id=13736 Signed-off-by: David Härdeman LKML-Reference: <20100128200254.GA9134@hardeman.nu> Cc: Alexey Fisher Cc: ykzhao Cc: Tony Bones Cc: Ingo Molnar Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/setup.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 51aa5b211c67..8425f7ebe89e 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -667,19 +667,27 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"), }, }, - { /* - * AMI BIOS with low memory corruption was found on Intel DG45ID board. - * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will + * AMI BIOS with low memory corruption was found on Intel DG45ID and + * DG45FC boards. + * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will * match only DMI_BOARD_NAME and see if there is more bad products * with this vendor. */ + { .callback = dmi_low_memory_corruption, .ident = "AMI BIOS", .matches = { DMI_MATCH(DMI_BOARD_NAME, "DG45ID"), }, }, + { + .callback = dmi_low_memory_corruption, + .ident = "AMI BIOS", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "DG45FC"), + }, + }, #endif {} }; From 253f887cc8d719087f8de403cfe1a60b5e56b454 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 22 Jan 2010 16:40:20 +0100 Subject: [PATCH 543/670] x86/amd-iommu: Fix possible integer overflow commit d91afd15b041f27d34859c79afa9e172018a86f4 upstream. The variable i in this function could be increased to over 2**32 which would result in an integer overflow when using int. Fix it by changing i to unsigned long. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/amd_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 90b9b559e7a4..e3f85feaae2e 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -540,7 +540,7 @@ static void flush_all_devices_for_iommu(struct amd_iommu *iommu) static void flush_devices_by_domain(struct protection_domain *domain) { struct amd_iommu *iommu; - int i; + unsigned long i; for (i = 0; i <= amd_iommu_last_bdf; ++i) { if ((domain == NULL && amd_iommu_pd_table[i] == NULL) || From 359e2f2722ef7b5d5b3d1472409a5daf8a6954d5 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 1 Feb 2010 18:24:58 +0200 Subject: [PATCH 544/670] clocksource: fix compilation if no GENERIC_TIME commit a362c638bdf052bf424bce7645d39b101090f6ba upstream Commit a9238ce3bb0fda6e760780b702c6cbd3793087d3 broke compilation on platforms that do not implement GENERIC_TIME (e.g. iop32x): kernel/time/clocksource.c: In function 'clocksource_register': kernel/time/clocksource.c:556: error: implicit declaration of function 'clocksource_max_deferment' Provide the implementation of clocksource_max_deferment() also for such platforms. Signed-off-by: Aaro Koskinen Cc: Thomas Gleixner 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 5155dc3e2ea9..ecc7adbf0918 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -413,8 +413,6 @@ void clocksource_touch_watchdog(void) clocksource_resume_watchdog(); } -#ifdef CONFIG_GENERIC_TIME - /** * clocksource_max_deferment - Returns max time the clocksource can be deferred * @cs: Pointer to clocksource @@ -456,6 +454,8 @@ static u64 clocksource_max_deferment(struct clocksource *cs) return max_nsecs - (max_nsecs >> 5); } +#ifdef CONFIG_GENERIC_TIME + /** * clocksource_select - Select the best clocksource available * From 16b8efad28d99afaf50b2a2116bf8edf605a0912 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Fri, 8 Jan 2010 00:00:09 -0800 Subject: [PATCH 545/670] tcp: update the netstamp_needed counter when cloning sockets [ Upstream commit 704da560c0a0120d8869187f511491a00951a1d3 ] This fixes a netstamp_needed accounting issue when the listen socket has SO_TIMESTAMP set: s = socket(AF_INET, SOCK_STREAM, 0); setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, 1); -> netstamp_needed = 1 bind(s, ...); listen(s, ...); s2 = accept(s, ...); -> netstamp_needed = 1 close(s2); -> netstamp_needed = 0 close(s); -> netstamp_needed = -1 Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/sock.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/sock.c b/net/core/sock.c index 7626b6aacd68..6605e756bcd4 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1181,6 +1181,10 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) if (newsk->sk_prot->sockets_allocated) percpu_counter_inc(newsk->sk_prot->sockets_allocated); + + if (sock_flag(newsk, SOCK_TIMESTAMP) || + sock_flag(newsk, SOCK_TIMESTAMPING_RX_SOFTWARE)) + net_enable_timestamp(); } out: return newsk; From 16813330e739634925b347804d1e6a99b71c6399 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 4 Jan 2010 08:48:41 +0000 Subject: [PATCH 546/670] sky2: Fix oops in sky2_xmit_frame() after TX timeout [ Upstream commit 9db2f1bec36805e57a003f7bb90e003815d96de8 ] During TX timeout procedure dev could be awoken too early, e.g. by sky2_complete_tx() called from sky2_down(). Then sky2_xmit_frame() can run while buffers are freed causing an oops. This patch fixes it by adding netif_device_present() test in sky2_tx_complete(). Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=14925 With debugging by: Mike McCormack Reported-by: Berck E. Nash Tested-by: Berck E. Nash Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/sky2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 6a10d7ba5877..f3600b3eb8c5 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1806,7 +1806,8 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) sky2->tx_cons = idx; smp_mb(); - if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) + /* Wake unless it's detached, and called e.g. from sky2_down() */ + if (tx_avail(sky2) > MAX_SKB_TX_LE + 4 && netif_device_present(dev)) netif_wake_queue(dev); } From ecb7287c5f53747767efa0f0e844da69a6ec3a51 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Fri, 25 Dec 2009 17:30:22 -0800 Subject: [PATCH 547/670] net: restore ip source validation [ Upstream commit 28f6aeea3f12d37bd258b2c0d5ba891bff4ec479 ] when using policy routing and the skb mark: there are cases where a back path validation requires us to use a different routing table for src ip validation than the one used for mapping ingress dst ip. One such a case is transparent proxying where we pretend to be the destination system and therefore the local table is used for incoming packets but possibly a main table would be used on outbound. Make the default behavior to allow the above and if users need to turn on the symmetry via sysctl src_valid_mark Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/inetdevice.h | 1 + include/linux/sysctl.h | 1 + net/ipv4/devinet.c | 1 + net/ipv4/fib_frontend.c | 2 ++ 4 files changed, 5 insertions(+) diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index ad27c7da8798..9cd0bcf30759 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -83,6 +83,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev) #define IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING) #define IN_DEV_MFORWARD(in_dev) IN_DEV_ANDCONF((in_dev), MC_FORWARDING) #define IN_DEV_RPFILTER(in_dev) IN_DEV_MAXCONF((in_dev), RP_FILTER) +#define IN_DEV_SRC_VMARK(in_dev) IN_DEV_ORCONF((in_dev), SRC_VMARK) #define IN_DEV_SOURCE_ROUTE(in_dev) IN_DEV_ANDCONF((in_dev), \ ACCEPT_SOURCE_ROUTE) #define IN_DEV_BOOTP_RELAY(in_dev) IN_DEV_ANDCONF((in_dev), BOOTP_RELAY) diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 1e4743ee6831..0eb69420b2f4 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -490,6 +490,7 @@ enum NET_IPV4_CONF_PROMOTE_SECONDARIES=20, NET_IPV4_CONF_ARP_ACCEPT=21, NET_IPV4_CONF_ARP_NOTIFY=22, + NET_IPV4_CONF_SRC_VMARK=24, __NET_IPV4_CONF_MAX }; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 5df2f6a0b0f0..0030e73728e4 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1450,6 +1450,7 @@ static struct devinet_sysctl_table { DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"), DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE, "accept_source_route"), + DEVINET_SYSCTL_RW_ENTRY(SRC_VMARK, "src_valid_mark"), DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"), DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"), DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"), diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index aa00398be80e..29391eebd731 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -251,6 +251,8 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, if (in_dev) { no_addr = in_dev->ifa_list == NULL; rpf = IN_DEV_RPFILTER(in_dev); + if (mark && !IN_DEV_SRC_VMARK(in_dev)) + fl.mark = 0; } rcu_read_unlock(); From 3125258f78ae4930916d8c569a10dfd621db77ba Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sun, 10 Jan 2010 22:04:19 +0000 Subject: [PATCH 548/670] af_packet: Don't use skb after dev_queue_xmit() [ Upstream commit eb70df13ee52dbc0f2c0ffd8ed34a8cd27440baf ] tpacket_snd() can change and kfree an skb after dev_queue_xmit(), which is illegal. With debugging by: Stephen Hemminger Reported-by: Michael Breuer With help from: David S. Miller Signed-off-by: Jarek Poplawski Tested-by: Michael Breuer Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/packet/af_packet.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f2d116a5cb35..41866eb2b5b6 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1028,8 +1028,20 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) status = TP_STATUS_SEND_REQUEST; err = dev_queue_xmit(skb); - if (unlikely(err > 0 && (err = net_xmit_errno(err)) != 0)) - goto out_xmit; + if (unlikely(err > 0)) { + err = net_xmit_errno(err); + if (err && __packet_get_status(po, ph) == + TP_STATUS_AVAILABLE) { + /* skb was destructed already */ + skb = NULL; + goto out_status; + } + /* + * skb was dropped but not destructed yet; + * let's treat it like congestion or err < 0 + */ + err = 0; + } packet_increment_head(&po->tx_ring); len_sum += tp_len; } while (likely((ph != NULL) || ((!(msg->msg_flags & MSG_DONTWAIT)) @@ -1039,9 +1051,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) err = len_sum; goto out_put; -out_xmit: - skb->destructor = sock_wfree; - atomic_dec(&po->tx_ring.pending); out_status: __packet_set_status(po, ph, status); kfree_skb(skb); From a74e62c2ef1fda92ad697556261b0e00fee5d581 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sat, 16 Jan 2010 01:04:04 -0800 Subject: [PATCH 549/670] ax25: netrom: rose: Fix timer oopses [ Upstream commit d00c362f1b0ff54161e0a42b4554ac621a9ef92d ] Wrong ax25_cb refcounting in ax25_send_frame() and by its callers can cause timer oopses (first reported with 2.6.29.6 kernel). Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=14905 Reported-by: Bernard Pidoux Tested-by: Bernard Pidoux Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/netrom.h | 2 ++ net/ax25/ax25_out.c | 6 ++++++ net/netrom/nr_route.c | 11 ++++++----- net/rose/rose_link.c | 8 ++++++++ net/rose/rose_route.c | 5 +++++ 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/include/net/netrom.h b/include/net/netrom.h index 15696b1fd30f..ab170a60e7d3 100644 --- a/include/net/netrom.h +++ b/include/net/netrom.h @@ -132,6 +132,8 @@ static __inline__ void nr_node_put(struct nr_node *nr_node) static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh) { if (atomic_dec_and_test(&nr_neigh->refcount)) { + if (nr_neigh->ax25) + ax25_cb_put(nr_neigh->ax25); kfree(nr_neigh->digipeat); kfree(nr_neigh); } diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index bf706f83a5c9..14912600ec57 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -92,6 +92,12 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2 #endif } + /* + * There is one ref for the state machine; a caller needs + * one more to put it back, just like with the existing one. + */ + ax25_cb_hold(ax25); + ax25_cb_add(ax25); ax25->state = AX25_STATE_1; diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index 4eb1ac9a7679..850ffc00390f 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c @@ -842,12 +842,13 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) dptr = skb_push(skb, 1); *dptr = AX25_P_NETROM; - ax25s = ax25_send_frame(skb, 256, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev); - if (nr_neigh->ax25 && ax25s) { - /* We were already holding this ax25_cb */ + ax25s = nr_neigh->ax25; + nr_neigh->ax25 = ax25_send_frame(skb, 256, + (ax25_address *)dev->dev_addr, + &nr_neigh->callsign, + nr_neigh->digipeat, nr_neigh->dev); + if (ax25s) ax25_cb_put(ax25s); - } - nr_neigh->ax25 = ax25s; dev_put(dev); ret = (nr_neigh->ax25 != NULL); diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index bd86a63960ce..5ef5f6988a2e 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -101,13 +101,17 @@ static void rose_t0timer_expiry(unsigned long param) static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh) { ax25_address *rose_call; + ax25_cb *ax25s; if (ax25cmp(&rose_callsign, &null_ax25_address) == 0) rose_call = (ax25_address *)neigh->dev->dev_addr; else rose_call = &rose_callsign; + ax25s = neigh->ax25; neigh->ax25 = ax25_send_frame(skb, 260, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); + if (ax25s) + ax25_cb_put(ax25s); return (neigh->ax25 != NULL); } @@ -120,13 +124,17 @@ static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh) static int rose_link_up(struct rose_neigh *neigh) { ax25_address *rose_call; + ax25_cb *ax25s; if (ax25cmp(&rose_callsign, &null_ax25_address) == 0) rose_call = (ax25_address *)neigh->dev->dev_addr; else rose_call = &rose_callsign; + ax25s = neigh->ax25; neigh->ax25 = ax25_find_cb(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); + if (ax25s) + ax25_cb_put(ax25s); return (neigh->ax25 != NULL); } diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index f3e21989b88c..08230fa6a502 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -234,6 +234,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) if ((s = rose_neigh_list) == rose_neigh) { rose_neigh_list = rose_neigh->next; + if (rose_neigh->ax25) + ax25_cb_put(rose_neigh->ax25); kfree(rose_neigh->digipeat); kfree(rose_neigh); return; @@ -242,6 +244,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) while (s != NULL && s->next != NULL) { if (s->next == rose_neigh) { s->next = rose_neigh->next; + if (rose_neigh->ax25) + ax25_cb_put(rose_neigh->ax25); kfree(rose_neigh->digipeat); kfree(rose_neigh); return; @@ -810,6 +814,7 @@ void rose_link_failed(ax25_cb *ax25, int reason) if (rose_neigh != NULL) { rose_neigh->ax25 = NULL; + ax25_cb_put(ax25); rose_del_route_by_neigh(rose_neigh); rose_kill_by_neigh(rose_neigh); From 4f7d6662c57dbaa6be09cc0bad2c01d005638a4d Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Mon, 1 Feb 2010 16:54:05 -0200 Subject: [PATCH 550/670] KVM: allow userspace to adjust kvmclock offset (cherry picked from afbcf7ab8d1bc8c2d04792f6d9e786e0adeb328d) When we migrate a kvm guest that uses pvclock between two hosts, we may suffer a large skew. This is because there can be significant differences between the monotonic clock of the hosts involved. When a new host with a much larger monotonic time starts running the guest, the view of time will be significantly impacted. Situation is much worse when we do the opposite, and migrate to a host with a smaller monotonic clock. This proposed ioctl will allow userspace to inform us what is the monotonic clock value in the source host, so we can keep the time skew short, and more importantly, never goes backwards. Userspace may also need to trigger the current data, since from the first migration onwards, it won't be reflected by a simple call to clock_gettime() anymore. [marcelo: future-proof abi with a flags field] [jan: fix KVM_GET_CLOCK by clearing flags field instead of checking it] Signed-off-by: Glauber Costa Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity Signed-off-by: Greg Kroah-Hartman --- Documentation/kvm/api.txt | 36 ++++++++++++++++++++++++++++ arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/x86.c | 42 ++++++++++++++++++++++++++++++++- include/linux/kvm.h | 9 +++++++ 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/Documentation/kvm/api.txt b/Documentation/kvm/api.txt index 5a4bc8cf6d04..db3a7062d793 100644 --- a/Documentation/kvm/api.txt +++ b/Documentation/kvm/api.txt @@ -593,6 +593,42 @@ struct kvm_irqchip { } chip; }; +4.27 KVM_GET_CLOCK + +Capability: KVM_CAP_ADJUST_CLOCK +Architectures: x86 +Type: vm ioctl +Parameters: struct kvm_clock_data (out) +Returns: 0 on success, -1 on error + +Gets the current timestamp of kvmclock as seen by the current guest. In +conjunction with KVM_SET_CLOCK, it is used to ensure monotonicity on scenarios +such as migration. + +struct kvm_clock_data { + __u64 clock; /* kvmclock current value */ + __u32 flags; + __u32 pad[9]; +}; + +4.28 KVM_SET_CLOCK + +Capability: KVM_CAP_ADJUST_CLOCK +Architectures: x86 +Type: vm ioctl +Parameters: struct kvm_clock_data (in) +Returns: 0 on success, -1 on error + +Sets the current timestamp of kvmclock to the valued specific in its parameter. +In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios +such as migration. + +struct kvm_clock_data { + __u64 clock; /* kvmclock current value */ + __u32 flags; + __u32 pad[9]; +}; + 5. The kvm_run structure Application code obtains a pointer to the kvm_run structure by diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index d83892226f73..d759a1f55084 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -412,6 +412,7 @@ struct kvm_arch{ unsigned long irq_sources_bitmap; unsigned long irq_states[KVM_IOAPIC_NUM_PINS]; u64 vm_init_tsc; + s64 kvmclock_offset; }; struct kvm_vm_stat { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6378e0742691..145741c979bf 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -680,7 +680,8 @@ static void kvm_write_guest_time(struct kvm_vcpu *v) /* With all the info we got, fill in the values */ vcpu->hv_clock.system_time = ts.tv_nsec + - (NSEC_PER_SEC * (u64)ts.tv_sec); + (NSEC_PER_SEC * (u64)ts.tv_sec) + v->kvm->arch.kvmclock_offset; + /* * The interface expects us to write an even number signaling that the * update is finished. Since the guest won't see the intermediate @@ -1227,6 +1228,7 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_PIT2: case KVM_CAP_PIT_STATE2: case KVM_CAP_SET_IDENTITY_MAP_ADDR: + case KVM_CAP_ADJUST_CLOCK: r = 1; break; case KVM_CAP_COALESCED_MMIO: @@ -2424,6 +2426,44 @@ long kvm_arch_vm_ioctl(struct file *filp, r = 0; break; } + case KVM_SET_CLOCK: { + struct timespec now; + struct kvm_clock_data user_ns; + u64 now_ns; + s64 delta; + + r = -EFAULT; + if (copy_from_user(&user_ns, argp, sizeof(user_ns))) + goto out; + + r = -EINVAL; + if (user_ns.flags) + goto out; + + r = 0; + ktime_get_ts(&now); + now_ns = timespec_to_ns(&now); + delta = user_ns.clock - now_ns; + kvm->arch.kvmclock_offset = delta; + break; + } + case KVM_GET_CLOCK: { + struct timespec now; + struct kvm_clock_data user_ns; + u64 now_ns; + + ktime_get_ts(&now); + now_ns = timespec_to_ns(&now); + user_ns.clock = kvm->arch.kvmclock_offset + now_ns; + user_ns.flags = 0; + + r = -EFAULT; + if (copy_to_user(argp, &user_ns, sizeof(user_ns))) + goto out; + r = 0; + break; + } + default: ; } diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 8908dd6cd343..0eadd71c4877 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -439,6 +439,7 @@ struct kvm_ioeventfd { #endif #define KVM_CAP_IOEVENTFD 36 #define KVM_CAP_SET_IDENTITY_MAP_ADDR 37 +#define KVM_CAP_ADJUST_CLOCK 39 #ifdef KVM_CAP_IRQ_ROUTING @@ -501,6 +502,12 @@ struct kvm_irqfd { __u8 pad[20]; }; +struct kvm_clock_data { + __u64 clock; + __u32 flags; + __u32 pad[9]; +}; + /* * ioctls for VM fds */ @@ -550,6 +557,8 @@ struct kvm_irqfd { #define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config) #define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78) #define KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd) +#define KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data) +#define KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data) /* * ioctls for vcpu fds From 9c66557324ea4879abe8c9dde769a0061c81e1ac Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 21 Jan 2010 23:26:27 +0100 Subject: [PATCH 551/670] oprofile/x86: add Xeon 7500 series support commit e83e452b0692c9c13372540deb88a77d4ae2553d upstream. Add Xeon 7500 series support to oprofile. Straight forward: it's the same as Core i7, so just detect the model number. No user space changes needed. Signed-off-by: Andi Kleen Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index cb88b1a0bd5f..5a14cd578cc4 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -598,6 +598,7 @@ static int __init ppro_init(char **cpu_type) case 15: case 23: *cpu_type = "i386/core_2"; break; + case 0x2e: case 26: spec = &op_arch_perfmon_spec; *cpu_type = "i386/core_i7"; From 42f7e233e4afae9d327f24c73379920adc905f95 Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Mon, 18 Jan 2010 11:25:36 -0600 Subject: [PATCH 552/670] oprofile/x86: fix crash when profiling more than 28 events commit d8cc108f4fab42b380c6b3f3356f99e8dd5372e2 upstream. With multiplexing enabled oprofile crashs when profiling more than 28 events. This patch fixes this. Signed-off-by: Suravee Suthikulpanit Signed-off-by: Robert Richter Signed-off-by: Greg Kroah-Hartman --- arch/x86/oprofile/nmi_int.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 5a14cd578cc4..3347f696edc7 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -222,7 +222,7 @@ static void nmi_cpu_switch(void *dummy) /* move to next set */ si += model->num_counters; - if ((si > model->num_virt_counters) || (counter_config[si].count == 0)) + if ((si >= model->num_virt_counters) || (counter_config[si].count == 0)) per_cpu(switch_index, cpu) = 0; else per_cpu(switch_index, cpu) = si; From dce6a09aaf62aff73b8123e9bb8ad2247b355848 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 11 Jan 2010 11:14:44 +0900 Subject: [PATCH 553/670] libata: retry link resume if necessary commit 5040ab67a2c6d5710ba497dc52a8f7035729d7b0 upstream. Interestingly, when SIDPR is used in ata_piix, writes to DET in SControl sometimes get ignored leading to detection failure. Update sata_link_resume() such that it reads back SControl after clearing DET and retry if it's not clear. Signed-off-by: Tejun Heo Reported-by: fengxiangjun Reported-by: Jim Faulkner Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-core.c | 40 +++++++++++++++++++++++++++++++-------- include/linux/libata.h | 3 +++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index dc72690ed5db..91fed3c93d66 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3790,21 +3790,45 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params, int sata_link_resume(struct ata_link *link, const unsigned long *params, unsigned long deadline) { + int tries = ATA_LINK_RESUME_TRIES; u32 scontrol, serror; int rc; if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) return rc; - scontrol = (scontrol & 0x0f0) | 0x300; - - if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol))) - return rc; - - /* Some PHYs react badly if SStatus is pounded immediately - * after resuming. Delay 200ms before debouncing. + /* + * Writes to SControl sometimes get ignored under certain + * controllers (ata_piix SIDPR). Make sure DET actually is + * cleared. */ - msleep(200); + do { + scontrol = (scontrol & 0x0f0) | 0x300; + if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol))) + return rc; + /* + * Some PHYs react badly if SStatus is pounded + * immediately after resuming. Delay 200ms before + * debouncing. + */ + msleep(200); + + /* is SControl restored correctly? */ + if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) + return rc; + } while ((scontrol & 0xf0f) != 0x300 && --tries); + + if ((scontrol & 0xf0f) != 0x300) { + ata_link_printk(link, KERN_ERR, + "failed to resume link (SControl %X)\n", + scontrol); + return 0; + } + + if (tries < ATA_LINK_RESUME_TRIES) + ata_link_printk(link, KERN_WARNING, + "link resume succeeded after %d retries\n", + ATA_LINK_RESUME_TRIES - tries); if ((rc = sata_link_debounce(link, params, deadline))) return rc; diff --git a/include/linux/libata.h b/include/linux/libata.h index 87698640c091..b0f6d97a06c2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -354,6 +354,9 @@ enum { /* max tries if error condition is still set after ->error_handler */ ATA_EH_MAX_TRIES = 5, + /* sometimes resuming a link requires several retries */ + ATA_LINK_RESUME_TRIES = 5, + /* how hard are we gonna try to probe/recover devices */ ATA_PROBE_MAX_TRIES = 3, ATA_EH_DEV_TRIES = 3, From 56d4b77f0492eb137fd950e48a7b2364f380d33d Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 1 Feb 2010 22:24:18 +1100 Subject: [PATCH 554/670] mm: percpu-vmap fix RCU list walking commit de5604231ce4bc8db1bc1dcd27d8540cbedf1518 upstream. RCU list walking of the per-cpu vmap cache was broken. It did not use RCU primitives, and also the union of free_list and rcu_head is obviously wrong (because free_list is indeed the list we are RCU walking). While we are there, remove a couple of unused fields from an earlier iteration. These APIs aren't actually used anywhere, because of problems with the XFS conversion. Christoph has now verified that the problems are solved with these patches. Also it is an exported interface, so I think it will be good to be merged now (and Christoph wants to get the XFS changes into their local tree). Cc: linux-mm@kvack.org Tested-by: Christoph Hellwig Signed-off-by: Nick Piggin Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmalloc.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index a3a99d39188b..6e5a1d263842 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -667,8 +667,6 @@ static bool vmap_initialized __read_mostly = false; struct vmap_block_queue { spinlock_t lock; struct list_head free; - struct list_head dirty; - unsigned int nr_dirty; }; struct vmap_block { @@ -678,10 +676,8 @@ struct vmap_block { unsigned long free, dirty; DECLARE_BITMAP(alloc_map, VMAP_BBMAP_BITS); DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS); - union { - struct list_head free_list; - struct rcu_head rcu_head; - }; + struct list_head free_list; + struct rcu_head rcu_head; }; /* Queue of free and dirty vmap blocks, for allocation and flushing purposes */ @@ -757,7 +753,7 @@ static struct vmap_block *new_vmap_block(gfp_t gfp_mask) vbq = &get_cpu_var(vmap_block_queue); vb->vbq = vbq; spin_lock(&vbq->lock); - list_add(&vb->free_list, &vbq->free); + list_add_rcu(&vb->free_list, &vbq->free); spin_unlock(&vbq->lock); put_cpu_var(vmap_cpu_blocks); @@ -776,8 +772,6 @@ static void free_vmap_block(struct vmap_block *vb) struct vmap_block *tmp; unsigned long vb_idx; - BUG_ON(!list_empty(&vb->free_list)); - vb_idx = addr_to_vb_idx(vb->va->va_start); spin_lock(&vmap_block_tree_lock); tmp = radix_tree_delete(&vmap_block_tree, vb_idx); @@ -816,7 +810,7 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask) vb->free -= 1UL << order; if (vb->free == 0) { spin_lock(&vbq->lock); - list_del_init(&vb->free_list); + list_del_rcu(&vb->free_list); spin_unlock(&vbq->lock); } spin_unlock(&vb->lock); @@ -860,11 +854,11 @@ static void vb_free(const void *addr, unsigned long size) BUG_ON(!vb); spin_lock(&vb->lock); - bitmap_allocate_region(vb->dirty_map, offset >> PAGE_SHIFT, order); + BUG_ON(bitmap_allocate_region(vb->dirty_map, offset >> PAGE_SHIFT, order)); vb->dirty += 1UL << order; if (vb->dirty == VMAP_BBMAP_BITS) { - BUG_ON(vb->free || !list_empty(&vb->free_list)); + BUG_ON(vb->free); spin_unlock(&vb->lock); free_vmap_block(vb); } else @@ -1033,8 +1027,6 @@ void __init vmalloc_init(void) vbq = &per_cpu(vmap_block_queue, i); spin_lock_init(&vbq->lock); INIT_LIST_HEAD(&vbq->free); - INIT_LIST_HEAD(&vbq->dirty); - vbq->nr_dirty = 0; } /* Import existing vmlist entries. */ From e52299d0b100ab8d92fe6e980b4d7ee24dd1398c Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 1 Feb 2010 22:25:57 +1100 Subject: [PATCH 555/670] mm: purge fragmented percpu vmap blocks commit 02b709df817c0db174f249cc59e5f7fd01b64d92 upstream. Improve handling of fragmented per-CPU vmaps. We previously don't free up per-CPU maps until all its addresses have been used and freed. So fragmented blocks could fill up vmalloc space even if they actually had no active vmap regions within them. Add some logic to allow all CPUs to have these blocks purged in the case of failure to allocate a new vm area, and also put some logic to trim such blocks of a current CPU if we hit them in the allocation path (so as to avoid a large build up of them). Christoph reported some vmap allocation failures when using the per CPU vmap APIs in XFS, which cannot be reproduced after this patch and the previous bug fix. Cc: linux-mm@kvack.org Tested-by: Christoph Hellwig Signed-off-by: Nick Piggin Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmalloc.c | 91 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 11 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 6e5a1d263842..c2287313b985 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -509,6 +509,9 @@ static unsigned long lazy_max_pages(void) static atomic_t vmap_lazy_nr = ATOMIC_INIT(0); +/* for per-CPU blocks */ +static void purge_fragmented_blocks_allcpus(void); + /* * Purges all lazily-freed vmap areas. * @@ -539,6 +542,9 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end, } else spin_lock(&purge_lock); + if (sync) + purge_fragmented_blocks_allcpus(); + rcu_read_lock(); list_for_each_entry_rcu(va, &vmap_area_list, list) { if (va->flags & VM_LAZY_FREE) { @@ -678,6 +684,7 @@ struct vmap_block { DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS); struct list_head free_list; struct rcu_head rcu_head; + struct list_head purge; }; /* Queue of free and dirty vmap blocks, for allocation and flushing purposes */ @@ -782,12 +789,61 @@ static void free_vmap_block(struct vmap_block *vb) call_rcu(&vb->rcu_head, rcu_free_vb); } +static void purge_fragmented_blocks(int cpu) +{ + LIST_HEAD(purge); + struct vmap_block *vb; + struct vmap_block *n_vb; + struct vmap_block_queue *vbq = &per_cpu(vmap_block_queue, cpu); + + rcu_read_lock(); + list_for_each_entry_rcu(vb, &vbq->free, free_list) { + + if (!(vb->free + vb->dirty == VMAP_BBMAP_BITS && vb->dirty != VMAP_BBMAP_BITS)) + continue; + + spin_lock(&vb->lock); + if (vb->free + vb->dirty == VMAP_BBMAP_BITS && vb->dirty != VMAP_BBMAP_BITS) { + vb->free = 0; /* prevent further allocs after releasing lock */ + vb->dirty = VMAP_BBMAP_BITS; /* prevent purging it again */ + bitmap_fill(vb->alloc_map, VMAP_BBMAP_BITS); + bitmap_fill(vb->dirty_map, VMAP_BBMAP_BITS); + spin_lock(&vbq->lock); + list_del_rcu(&vb->free_list); + spin_unlock(&vbq->lock); + spin_unlock(&vb->lock); + list_add_tail(&vb->purge, &purge); + } else + spin_unlock(&vb->lock); + } + rcu_read_unlock(); + + list_for_each_entry_safe(vb, n_vb, &purge, purge) { + list_del(&vb->purge); + free_vmap_block(vb); + } +} + +static void purge_fragmented_blocks_thiscpu(void) +{ + purge_fragmented_blocks(smp_processor_id()); +} + +static void purge_fragmented_blocks_allcpus(void) +{ + int cpu; + + for_each_possible_cpu(cpu) + purge_fragmented_blocks(cpu); +} + static void *vb_alloc(unsigned long size, gfp_t gfp_mask) { struct vmap_block_queue *vbq; struct vmap_block *vb; unsigned long addr = 0; unsigned int order; + int purge = 0; BUG_ON(size & ~PAGE_MASK); BUG_ON(size > PAGE_SIZE*VMAP_MAX_ALLOC); @@ -800,24 +856,37 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask) int i; spin_lock(&vb->lock); + if (vb->free < 1UL << order) + goto next; i = bitmap_find_free_region(vb->alloc_map, VMAP_BBMAP_BITS, order); - if (i >= 0) { - addr = vb->va->va_start + (i << PAGE_SHIFT); - BUG_ON(addr_to_vb_idx(addr) != - addr_to_vb_idx(vb->va->va_start)); - vb->free -= 1UL << order; - if (vb->free == 0) { - spin_lock(&vbq->lock); - list_del_rcu(&vb->free_list); - spin_unlock(&vbq->lock); + if (i < 0) { + if (vb->free + vb->dirty == VMAP_BBMAP_BITS) { + /* fragmented and no outstanding allocations */ + BUG_ON(vb->dirty != VMAP_BBMAP_BITS); + purge = 1; } - spin_unlock(&vb->lock); - break; + goto next; + } + addr = vb->va->va_start + (i << PAGE_SHIFT); + BUG_ON(addr_to_vb_idx(addr) != + addr_to_vb_idx(vb->va->va_start)); + vb->free -= 1UL << order; + if (vb->free == 0) { + spin_lock(&vbq->lock); + list_del_rcu(&vb->free_list); + spin_unlock(&vbq->lock); } spin_unlock(&vb->lock); + break; +next: + spin_unlock(&vb->lock); } + + if (purge) + purge_fragmented_blocks_thiscpu(); + put_cpu_var(vmap_cpu_blocks); rcu_read_unlock(); From cb723ba5d03bf719dbc7409b4d67572d4472ef8b Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 27 Jan 2010 22:44:36 +0300 Subject: [PATCH 556/670] block: fix bio_add_page for non trivial merge_bvec_fn case commit 1d6165851cd8e3f919d446cd6da35dee44e8837e upstream. We have to properly decrease bi_size in order to merge_bvec_fn return right result. Otherwise this result in false merge rejects for two absolutely valid bio_vecs. This may cause significant performance penalty for example fs_block_size == 1k and block device is raid0 with small chunk_size = 8k. Then it is impossible to merge 7-th fs-block in to bio which already has 6 fs-blocks. Signed-off-by: Dmitry Monakhov Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/bio.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/bio.c b/fs/bio.c index 12da5db8682c..e0c9e71cc404 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -542,13 +542,18 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page if (page == prev->bv_page && offset == prev->bv_offset + prev->bv_len) { + unsigned int prev_bv_len = prev->bv_len; prev->bv_len += len; if (q->merge_bvec_fn) { struct bvec_merge_data bvm = { + /* prev_bvec is already charged in + bi_size, discharge it in order to + simulate merging updated prev_bvec + as new bvec. */ .bi_bdev = bio->bi_bdev, .bi_sector = bio->bi_sector, - .bi_size = bio->bi_size, + .bi_size = bio->bi_size - prev_bv_len, .bi_rw = bio->bi_rw, }; From 94af44b66b66bf9c848f11dc12fcd1558e55f995 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 2 Feb 2010 12:37:44 -0800 Subject: [PATCH 557/670] Fix 'flush_old_exec()/setup_new_exec()' split commit 7ab02af428c2d312c0cf8fb0b01cc1eb21131a3d upstream. Commit 221af7f87b9 ("Split 'flush_old_exec' into two functions") split the function at the point of no return - ie right where there were no more error cases to check. That made sense from a technical standpoint, but when we then also combined it with the actual personality setting going in between flush_old_exec() and setup_new_exec(), it needs to be a bit more careful. In particular, we need to make sure that we really flush the old personality bits in the 'flush' stage, rather than later in the 'setup' stage, since otherwise we might be flushing the _new_ personality state that we're just setting up. So this moves the flags and personality flushing (and 'flush_thread()', which is the arch-specific function that generally resets lazy FP state etc) of the old process into flush_old_exec(), so that it doesn't affect any state that execve() is setting up for the new process environment. This was reported by Michal Simek as breaking his Microblaze qemu environment. Reported-and-tested-by: Michal Simek Cc: Peter Anvin Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/exec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index b2ad94e25da7..7fa4efd50425 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -951,6 +951,11 @@ int flush_old_exec(struct linux_binprm * bprm) goto out; bprm->mm = NULL; /* We're using it now */ + + current->flags &= ~PF_RANDOMIZE; + flush_thread(); + current->personality &= ~bprm->per_clear; + return 0; out: @@ -987,9 +992,6 @@ void setup_new_exec(struct linux_binprm * bprm) tcomm[i] = '\0'; set_task_comm(current, tcomm); - current->flags &= ~PF_RANDOMIZE; - flush_thread(); - /* Set the new mm task size. We have to do that late because it may * depend on TIF_32BIT which is only updated in flush_thread() on * some architectures like powerpc @@ -1005,8 +1007,6 @@ void setup_new_exec(struct linux_binprm * bprm) set_dumpable(current->mm, suid_dumpable); } - current->personality &= ~bprm->per_clear; - /* * Flush performance counters when crossing a * security domain: From 8857a1abeb4572aa5237d0461165e983e01da707 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Fri, 29 Jan 2010 21:50:36 +1300 Subject: [PATCH 558/670] random: drop weird m_time/a_time manipulation commit a996996dd75a9086b12d1cb4010f26e1748993f0 upstream. No other driver does anything remotely like this that I know of except for the tty drivers, and I can't see any reason for random/urandom to do it. In fact, it's a (trivial, harmless) timing information leak. And obviously, it generates power- and flash-cycle wasting I/O, especially if combined with something like hwrngd. Also, it breaks ubifs's expectations. Signed-off-by: Matt Mackall Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 04b505e5a5e2..53058de44a7f 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1051,12 +1051,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) /* like a named pipe */ } - /* - * If we gave the user some bytes, update the access time. - */ - if (count) - file_accessed(file); - return (count ? count : retval); } @@ -1116,8 +1110,6 @@ static ssize_t random_write(struct file *file, const char __user *buffer, if (ret) return ret; - inode->i_mtime = current_fs_time(inode->i_sb); - mark_inode_dirty(inode); return (ssize_t)count; } From 964814800330216ded04e5a9a21f95d7998dfd62 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 1 Feb 2010 21:48:28 +1100 Subject: [PATCH 559/670] random: Remove unused inode variable commit cd1510cb5f892907fe1a662f90b41fb3a42954e0 upstream. The previous changeset left behind an unused inode variable. This patch removes it. Reported-by: Stephen Rothwell Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 53058de44a7f..908ac1f54ca9 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1101,7 +1101,6 @@ static ssize_t random_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { size_t ret; - struct inode *inode = file->f_path.dentry->d_inode; ret = write_pool(&blocking_pool, buffer, count); if (ret) From 0ae2b7de3957a477ec0f332c4da5633499b4d3aa Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 30 Jan 2010 20:28:19 +0100 Subject: [PATCH 560/670] block: fix bugs in bio-integrity mempool usage commit 9e9432c267e4047db98b9d4fba95099c6effcef9 upstream. Fix two bugs in the bio integrity code: use_bip_pool() always returns 0 because it checks against the wrong limit, causing the mempool to be used only when regular allocation fails. When the mempool is used as a fallback we don't free the data properly. Signed-Off-By: Chuck Ebbert Acked-by: Martin K. Petersen Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/bio-integrity.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 49a34e7f7306..a16f29e888cd 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -61,7 +61,7 @@ static inline unsigned int vecs_to_idx(unsigned int nr) static inline int use_bip_pool(unsigned int idx) { - if (idx == BIOVEC_NR_POOLS) + if (idx == BIOVEC_MAX_IDX) return 1; return 0; @@ -95,6 +95,7 @@ struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio, /* Use mempool if lower order alloc failed or max vecs were requested */ if (bip == NULL) { + idx = BIOVEC_MAX_IDX; /* so we free the payload properly later */ bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask); if (unlikely(bip == NULL)) { From f06f00e00cbf497623fda3c1c317f28cf5d9a770 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 27 Jan 2010 07:41:19 +0000 Subject: [PATCH 561/670] usb: r8a66597-hdc disable interrupts fix commit e5ff15bec96ba18698dae5de0bbf7e6a0653ca65 upstream. This patch improves disable_controller() in the r8a66597-hdc driver to disable all interrupts and clear status flags. It also makes sure that disable_controller() is called during probe(). This fixes the relatively rare case of unexpected pending interrupts after kexec reboot. Signed-off-by: Magnus Damm Acked-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index e33d36256350..5b56f53bbeda 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -216,8 +216,17 @@ static void disable_controller(struct r8a66597 *r8a66597) { int port; + /* disable interrupts */ r8a66597_write(r8a66597, 0, INTENB0); - r8a66597_write(r8a66597, 0, INTSTS0); + r8a66597_write(r8a66597, 0, INTENB1); + r8a66597_write(r8a66597, 0, BRDYENB); + r8a66597_write(r8a66597, 0, BEMPENB); + r8a66597_write(r8a66597, 0, NRDYENB); + + /* clear status */ + r8a66597_write(r8a66597, 0, BRDYSTS); + r8a66597_write(r8a66597, 0, NRDYSTS); + r8a66597_write(r8a66597, 0, BEMPSTS); for (port = 0; port < r8a66597->max_root_hub; port++) r8a66597_disable_port(r8a66597, port); @@ -2470,6 +2479,12 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) r8a66597->rh_timer.data = (unsigned long)r8a66597; r8a66597->reg = (unsigned long)reg; + /* make sure no interrupts are pending */ + ret = r8a66597_clock_enable(r8a66597); + if (ret < 0) + goto clean_up3; + disable_controller(r8a66597); + for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) { INIT_LIST_HEAD(&r8a66597->pipe_queue[i]); init_timer(&r8a66597->td_timer[i]); From 43d7ff26361d05f9f97a92726bd2acc9652ce65c Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Tue, 2 Feb 2010 15:58:48 -0800 Subject: [PATCH 562/670] connector: Delete buggy notification code. commit f98bfbd78c37c5946cc53089da32a5f741efdeb7 upstream. On Tue, Feb 02, 2010 at 02:57:14PM -0800, Greg KH (gregkh@suse.de) wrote: > > There are at least two ways to fix it: using a big cannon and a small > > one. The former way is to disable notification registration, since it is > > not used by anyone at all. Second way is to check whether calling > > process is root and its destination group is -1 (kind of priveledged > > one) before command is dispatched to workqueue. > > Well if no one is using it, removing it makes the most sense, right? > > No objection from me, care to make up a patch either way for this? Getting it is not used, let's drop support for notifications about (un)registered events from connector. Another option was to check credentials on receiving, but we can always restore it without bugs if needed, but genetlink has a wider code base and none complained, that userspace can not get notification when some other clients were (un)registered. Kudos for Sebastian Krahmer , who found a bug in the code. Signed-off-by: Evgeniy Polyakov Acked-by: Greg Kroah-Hartman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/connector/connector.c | 175 ---------------------------------- include/linux/connector.h | 32 ------- 2 files changed, 207 deletions(-) diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index f06024668f99..537c29ac4487 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -36,17 +36,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Evgeniy Polyakov "); MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector."); -static u32 cn_idx = CN_IDX_CONNECTOR; -static u32 cn_val = CN_VAL_CONNECTOR; - -module_param(cn_idx, uint, 0); -module_param(cn_val, uint, 0); -MODULE_PARM_DESC(cn_idx, "Connector's main device idx."); -MODULE_PARM_DESC(cn_val, "Connector's main device val."); - -static DEFINE_MUTEX(notify_lock); -static LIST_HEAD(notify_list); - static struct cn_dev cdev; static int cn_already_initialized; @@ -209,54 +198,6 @@ static void cn_rx_skb(struct sk_buff *__skb) } } -/* - * Notification routing. - * - * Gets id and checks if there are notification request for it's idx - * and val. If there are such requests notify the listeners with the - * given notify event. - * - */ -static void cn_notify(struct cb_id *id, u32 notify_event) -{ - struct cn_ctl_entry *ent; - - mutex_lock(¬ify_lock); - list_for_each_entry(ent, ¬ify_list, notify_entry) { - int i; - struct cn_notify_req *req; - struct cn_ctl_msg *ctl = ent->msg; - int idx_found, val_found; - - idx_found = val_found = 0; - - req = (struct cn_notify_req *)ctl->data; - for (i = 0; i < ctl->idx_notify_num; ++i, ++req) { - if (id->idx >= req->first && - id->idx < req->first + req->range) { - idx_found = 1; - break; - } - } - - for (i = 0; i < ctl->val_notify_num; ++i, ++req) { - if (id->val >= req->first && - id->val < req->first + req->range) { - val_found = 1; - break; - } - } - - if (idx_found && val_found) { - struct cn_msg m = { .ack = notify_event, }; - - memcpy(&m.id, id, sizeof(m.id)); - cn_netlink_send(&m, ctl->group, GFP_KERNEL); - } - } - mutex_unlock(¬ify_lock); -} - /* * Callback add routing - adds callback with given ID and name. * If there is registered callback with the same ID it will not be added. @@ -276,8 +217,6 @@ int cn_add_callback(struct cb_id *id, char *name, if (err) return err; - cn_notify(id, 0); - return 0; } EXPORT_SYMBOL_GPL(cn_add_callback); @@ -295,111 +234,9 @@ void cn_del_callback(struct cb_id *id) struct cn_dev *dev = &cdev; cn_queue_del_callback(dev->cbdev, id); - cn_notify(id, 1); } EXPORT_SYMBOL_GPL(cn_del_callback); -/* - * Checks two connector's control messages to be the same. - * Returns 1 if they are the same or if the first one is corrupted. - */ -static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2) -{ - int i; - struct cn_notify_req *req1, *req2; - - if (m1->idx_notify_num != m2->idx_notify_num) - return 0; - - if (m1->val_notify_num != m2->val_notify_num) - return 0; - - if (m1->len != m2->len) - return 0; - - if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) != - m1->len) - return 1; - - req1 = (struct cn_notify_req *)m1->data; - req2 = (struct cn_notify_req *)m2->data; - - for (i = 0; i < m1->idx_notify_num; ++i) { - if (req1->first != req2->first || req1->range != req2->range) - return 0; - req1++; - req2++; - } - - for (i = 0; i < m1->val_notify_num; ++i) { - if (req1->first != req2->first || req1->range != req2->range) - return 0; - req1++; - req2++; - } - - return 1; -} - -/* - * Main connector device's callback. - * - * Used for notification of a request's processing. - */ -static void cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) -{ - struct cn_ctl_msg *ctl; - struct cn_ctl_entry *ent; - u32 size; - - if (msg->len < sizeof(*ctl)) - return; - - ctl = (struct cn_ctl_msg *)msg->data; - - size = (sizeof(*ctl) + ((ctl->idx_notify_num + - ctl->val_notify_num) * - sizeof(struct cn_notify_req))); - - if (msg->len != size) - return; - - if (ctl->len + sizeof(*ctl) != msg->len) - return; - - /* - * Remove notification. - */ - if (ctl->group == 0) { - struct cn_ctl_entry *n; - - mutex_lock(¬ify_lock); - list_for_each_entry_safe(ent, n, ¬ify_list, notify_entry) { - if (cn_ctl_msg_equals(ent->msg, ctl)) { - list_del(&ent->notify_entry); - kfree(ent); - } - } - mutex_unlock(¬ify_lock); - - return; - } - - size += sizeof(*ent); - - ent = kzalloc(size, GFP_KERNEL); - if (!ent) - return; - - ent->msg = (struct cn_ctl_msg *)(ent + 1); - - memcpy(ent->msg, ctl, size - sizeof(*ent)); - - mutex_lock(¬ify_lock); - list_add(&ent->notify_entry, ¬ify_list); - mutex_unlock(¬ify_lock); -} - static int cn_proc_show(struct seq_file *m, void *v) { struct cn_queue_dev *dev = cdev.cbdev; @@ -437,11 +274,8 @@ static const struct file_operations cn_file_ops = { static int __devinit cn_init(void) { struct cn_dev *dev = &cdev; - int err; dev->input = cn_rx_skb; - dev->id.idx = cn_idx; - dev->id.val = cn_val; dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR, CN_NETLINK_USERS + 0xf, @@ -457,14 +291,6 @@ static int __devinit cn_init(void) cn_already_initialized = 1; - err = cn_add_callback(&dev->id, "connector", &cn_callback); - if (err) { - cn_already_initialized = 0; - cn_queue_free_dev(dev->cbdev); - netlink_kernel_release(dev->nls); - return -EINVAL; - } - proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops); return 0; @@ -478,7 +304,6 @@ static void __devexit cn_fini(void) proc_net_remove(&init_net, "connector"); - cn_del_callback(&dev->id); cn_queue_free_dev(dev->cbdev); netlink_kernel_release(dev->nls); } diff --git a/include/linux/connector.h b/include/linux/connector.h index 3a14615fd35c..ecb61c40b344 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -24,9 +24,6 @@ #include -#define CN_IDX_CONNECTOR 0xffffffff -#define CN_VAL_CONNECTOR 0xffffffff - /* * Process Events connector unique ids -- used for message routing */ @@ -73,30 +70,6 @@ struct cn_msg { __u8 data[0]; }; -/* - * Notify structure - requests notification about - * registering/unregistering idx/val in range [first, first+range]. - */ -struct cn_notify_req { - __u32 first; - __u32 range; -}; - -/* - * Main notification control message - * *_notify_num - number of appropriate cn_notify_req structures after - * this struct. - * group - notification receiver's idx. - * len - total length of the attached data. - */ -struct cn_ctl_msg { - __u32 idx_notify_num; - __u32 val_notify_num; - __u32 group; - __u32 len; - __u8 data[0]; -}; - #ifdef __KERNEL__ #include @@ -149,11 +122,6 @@ struct cn_callback_entry { u32 seq, group; }; -struct cn_ctl_entry { - struct list_head notify_entry; - struct cn_ctl_msg *msg; -}; - struct cn_dev { struct cb_id id; From e38d76ea394dd90a78c002e8298d47390b858334 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 27 Jan 2010 21:56:44 +0000 Subject: [PATCH 563/670] be2net: Bug fix to support newer generation of BE ASIC commit 7b139c83c590d4965259aad8889cbb08104b2891 upstream. Bug fix in be2net for newer generation of BladeEngine ASIC. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/benet/be.h | 5 +++++ drivers/net/benet/be_cmds.h | 3 ++- drivers/net/benet/be_main.c | 25 +++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index a84f1c55378d..511b92237ad0 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -272,8 +272,13 @@ struct be_adapter { u32 cap; u32 rx_fc; /* Rx flow control */ u32 tx_fc; /* Tx flow control */ + u8 generation; /* BladeEngine ASIC generation */ }; +/* BladeEngine Generation numbers */ +#define BE_GEN2 2 +#define BE_GEN3 3 + extern const struct ethtool_ops be_ethtool_ops; #define drvr_stats(adapter) (&adapter->stats.drvr_stats) diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index e5f9676cf1bc..ad33d5508f54 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -154,7 +154,8 @@ struct be_cmd_req_hdr { u8 domain; /* dword 0 */ u32 timeout; /* dword 1 */ u32 request_length; /* dword 2 */ - u32 rsvd; /* dword 3 */ + u8 version; /* dword 3 */ + u8 rsvd[3]; /* dword 3 */ }; #define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 3749bb1e8ba5..a25da9aeedaa 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1944,6 +1944,7 @@ static void be_unmap_pci_bars(struct be_adapter *adapter) static int be_map_pci_bars(struct be_adapter *adapter) { u8 __iomem *addr; + int pcicfg_reg; addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), pci_resource_len(adapter->pdev, 2)); @@ -1957,8 +1958,13 @@ static int be_map_pci_bars(struct be_adapter *adapter) goto pci_map_err; adapter->db = addr; - addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1), - pci_resource_len(adapter->pdev, 1)); + if (adapter->generation == BE_GEN2) + pcicfg_reg = 1; + else + pcicfg_reg = 0; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, pcicfg_reg), + pci_resource_len(adapter->pdev, pcicfg_reg)); if (addr == NULL) goto pci_map_err; adapter->pcicfg = addr; @@ -2028,6 +2034,7 @@ static int be_stats_init(struct be_adapter *adapter) cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); if (cmd->va == NULL) return -1; + memset(cmd->va, cmd->size, 0); return 0; } @@ -2101,6 +2108,20 @@ static int __devinit be_probe(struct pci_dev *pdev, goto rel_reg; } adapter = netdev_priv(netdev); + + switch (pdev->device) { + case BE_DEVICE_ID1: + case OC_DEVICE_ID1: + adapter->generation = BE_GEN2; + break; + case BE_DEVICE_ID2: + case OC_DEVICE_ID2: + adapter->generation = BE_GEN3; + break; + default: + adapter->generation = 0; + } + adapter->pdev = pdev; pci_set_drvdata(pdev, adapter); adapter->netdev = netdev; From 78da404b13afa162e9da0384f553db5f19bc94b0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Jan 2010 21:36:21 -0800 Subject: [PATCH 564/670] be2net: Fix memset() arg ordering. commit d291b9af1a1a12f59a464494900c6e0db26e2ec3 upstream. Noticed by Ben Hutchings. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/benet/be_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index a25da9aeedaa..ec983cb67d1f 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2034,7 +2034,7 @@ static int be_stats_init(struct be_adapter *adapter) cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); if (cmd->va == NULL) return -1; - memset(cmd->va, cmd->size, 0); + memset(cmd->va, 0, cmd->size); return 0; } From 3a9353f232812dc9057cbee39c618f400a8c5f60 Mon Sep 17 00:00:00 2001 From: anfei zhou Date: Tue, 2 Feb 2010 13:44:02 -0800 Subject: [PATCH 565/670] mm: flush dcache before writing into page to avoid alias commit 931e80e4b3263db75c8e34f078d22f11bbabd3a3 upstream. The cache alias problem will happen if the changes of user shared mapping is not flushed before copying, then user and kernel mapping may be mapped into two different cache line, it is impossible to guarantee the coherence after iov_iter_copy_from_user_atomic. So the right steps should be: flush_dcache_page(page); kmap_atomic(page); write to page; kunmap_atomic(page); flush_dcache_page(page); More precisely, we might create two new APIs flush_dcache_user_page and flush_dcache_kern_page to replace the two flush_dcache_page accordingly. Here is a snippet tested on omap2430 with VIPT cache, and I think it is not ARM-specific: int val = 0x11111111; fd = open("abc", O_RDWR); addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); *(addr+0) = 0x44444444; tmp = *(addr+0); *(addr+1) = 0x77777777; write(fd, &val, sizeof(int)); close(fd); The results are not always 0x11111111 0x77777777 at the beginning as expected. Sometimes we see 0x44444444 0x77777777. Signed-off-by: Anfei Cc: Russell King Cc: Miklos Szeredi Cc: Nick Piggin Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/fuse/file.c | 3 +++ mm/filemap.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index c18913a777ae..a9f5e137f1d3 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -828,6 +828,9 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, if (!page) break; + if (mapping_writably_mapped(mapping)) + flush_dcache_page(page); + pagefault_disable(); tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes); pagefault_enable(); diff --git a/mm/filemap.c b/mm/filemap.c index fbdacb717ae9..8e96c9076f80 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2253,6 +2253,9 @@ static ssize_t generic_perform_write(struct file *file, if (unlikely(status)) break; + if (mapping_writably_mapped(mapping)) + flush_dcache_page(page); + pagefault_disable(); copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes); pagefault_enable(); From b260729c8a49452ae9491e3cb94750687f221d2b Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 26 Jan 2010 15:58:57 +0800 Subject: [PATCH 566/670] mac80211: fix NULL pointer dereference when ftrace is enabled commit 3092ad054406f069991ca561adc74f2d9fbb6867 upstream. I got below kernel oops when I try to bring down the network interface if ftrace is enabled. The root cause is drv_ampdu_action() is passed with a NULL ssn pointer in the BA session tear down case. We need to check and avoid dereferencing it in trace entry assignment. BUG: unable to handle kernel NULL pointer dereference Modules linked in: at (null) IP: [] ftrace_raw_event_drv_ampdu_action+0x10a/0x160 [mac80211] *pde = 00000000 Oops: 0000 [#1] SMP DEBUG_PAGEALLOC [...] Call Trace: [] ? ftrace_raw_event_drv_ampdu_action+0x0/0x160 [mac80211] [] ? __ieee80211_stop_rx_ba_session+0xfc/0x220 [mac80211] [] ? ieee80211_sta_tear_down_BA_sessions+0x3b/0x50 [mac80211] [] ? ieee80211_set_disassoc+0xe6/0x230 [mac80211] [] ? ieee80211_set_disassoc+0x9c/0x230 [mac80211] [] ? ieee80211_mgd_deauth+0x158/0x170 [mac80211] [] ? ieee80211_deauth+0x1b/0x20 [mac80211] [] ? __cfg80211_mlme_deauth+0xe9/0x120 [cfg80211] [] ? __cfg80211_disconnect+0x170/0x1d0 [cfg80211] Cc: Johannes Berg Signed-off-by: Zhu Yi Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/driver-trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 37b9051afcf3..d87645e3e41a 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -655,7 +655,7 @@ TRACE_EVENT(drv_ampdu_action, __entry->ret = ret; __entry->action = action; __entry->tid = tid; - __entry->ssn = *ssn; + __entry->ssn = ssn ? *ssn : 0; ), TP_printk( From 682efb8384326571bb180214a5d4661cc6befa41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 2 Feb 2010 13:44:10 -0800 Subject: [PATCH 567/670] imxfb: correct location of callbacks in suspend and resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1ec562035ba64e724652cb12b8a770b3906e9bf5 upstream. The probe function passes a pointer to a struct fb_info to platform_set_drvdata(), so don't interpret the return value of platform_get_drvdata() as a pointer to struct imxfb_info. The original imxfb_info *fbi backlight_power was NULL but in imxfb_suspend it was 4 resulting in an oops as imxfb_suspend calls imxfb_disable_controller(fbi) which in turn has if (fbi->backlight_power) fbi->backlight_power(0); Signed-off-by: Uwe Kleine-König Acked-by: Sascha Hauer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/imxfb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 66358fa825f3..b4b6deceed15 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -593,7 +593,8 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf */ static int imxfb_suspend(struct platform_device *dev, pm_message_t state) { - struct imxfb_info *fbi = platform_get_drvdata(dev); + struct fb_info *info = platform_get_drvdata(dev); + struct imxfb_info *fbi = info->par; pr_debug("%s\n", __func__); @@ -603,7 +604,8 @@ static int imxfb_suspend(struct platform_device *dev, pm_message_t state) static int imxfb_resume(struct platform_device *dev) { - struct imxfb_info *fbi = platform_get_drvdata(dev); + struct fb_info *info = platform_get_drvdata(dev); + struct imxfb_info *fbi = info->par; pr_debug("%s\n", __func__); From 906f68dd91cc512036909a10350d479dfc56d378 Mon Sep 17 00:00:00 2001 From: Alberto Panizzo Date: Tue, 2 Feb 2010 13:43:59 -0800 Subject: [PATCH 568/670] mx3fb: some debug and initialisation fixes commit b3cb53721890879d7bde31f5f9eefd4edf41ab64 upstream. Fix the kernel oops when dev_dbg is called with mx3_fbi->txd == NULL Fix the late initialisation of mx3fb->backlight_level. If not, in the chain of function started by init_fb_chan(), in __blank() call sdc_set_brightness(mx3fb, mx3fb->backlight_level) that will shut down the CONTRAST PWM output. Signed-off-by: Alberto Panizzo Acked-by: Guennadi Liakhovetski Cc: Sascha Hauer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/video/mx3fb.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 054ef29be479..772ba3f45e6f 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -324,8 +324,11 @@ static void sdc_enable_channel(struct mx3fb_info *mx3_fbi) unsigned long flags; dma_cookie_t cookie; - dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi, - to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg); + if (mx3_fbi->txd) + dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi, + to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg); + else + dev_dbg(mx3fb->dev, "mx3fbi %p, txd = NULL\n", mx3_fbi); /* This enables the channel */ if (mx3_fbi->cookie < 0) { @@ -646,6 +649,7 @@ static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t a static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value) { + dev_dbg(mx3fb->dev, "%s: value = %d\n", __func__, value); /* This might be board-specific */ mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL); return; @@ -1486,12 +1490,12 @@ static int mx3fb_probe(struct platform_device *pdev) goto ersdc0; } + mx3fb->backlight_level = 255; + ret = init_fb_chan(mx3fb, to_idmac_chan(chan)); if (ret < 0) goto eisdc0; - mx3fb->backlight_level = 255; - return 0; eisdc0: From 35cfb03de1dcd87f405db30a9da65bd63bfa59fe Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 26 Jan 2010 18:27:09 +0000 Subject: [PATCH 569/670] starfire: clean up properly if firmware loading fails commit c928febf4bc703ea542340e5a208e0445d998839 upstream. netdev_open() will return without cleaning up net device or hardware state if firmware loading fails. This results in a BUG() on a second attempt to bring the interface up, reported in , and probably has even worse effects if the driver is removed afterwards. Call netdev_close() to clean up on failure. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=15091 Signed-off-by: Ben Hutchings Reported-by: Michael Moffatt Tested-by: Michael Moffatt Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/starfire.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index a36e2b51e88c..e65ee4dcd518 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1063,7 +1063,7 @@ static int netdev_open(struct net_device *dev) if (retval) { printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", FIRMWARE_RX); - return retval; + goto out_init; } if (fw_rx->size % 4) { printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", @@ -1108,6 +1108,9 @@ static int netdev_open(struct net_device *dev) release_firmware(fw_tx); out_rx: release_firmware(fw_rx); +out_init: + if (retval) + netdev_close(dev); return retval; } From e06fbe9a4092960a1db1fa973c9ec13a3ddce3f9 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 3 Feb 2010 09:31:36 +1100 Subject: [PATCH 570/670] kernel/cred.c: use kmem_cache_free commit b8a1d37c5f981cdd2e83c9fd98198832324cd57a upstream. Free memory allocated using kmem_cache_zalloc using kmem_cache_free rather than kfree. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,E,c; @@ x = \(kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache_alloc_node\)(c,...) ... when != x = E when != &x ?-kfree(x) +kmem_cache_free(c,x) // Signed-off-by: Julia Lawall Acked-by: David Howells Cc: James Morris Cc: Steve Dickson Signed-off-by: Andrew Morton Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman --- kernel/cred.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/cred.c b/kernel/cred.c index dd76cfe5f5b0..1ed8ca18790c 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -224,7 +224,7 @@ struct cred *cred_alloc_blank(void) #ifdef CONFIG_KEYS new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL); if (!new->tgcred) { - kfree(new); + kmem_cache_free(cred_jar, new); return NULL; } atomic_set(&new->tgcred->usage, 1); From b31aa5cccb9b5850135c07d8a0cb22984a5fe0f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 2 Feb 2010 13:44:12 -0800 Subject: [PATCH 571/670] uartlite: fix crash when using as console MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 03eac7bb882a75e6ee5705288f7ec36ad2e7d0d5 upstream. Move the ulite_console_setup to the .devinit section since it might be called on probe, which is in devinit. Fixes the crash below where the uartlite hw is probed after the .init section is freed from the kernel. uartlite: ttyUL0 at MMIO 0xc8000100 (irq = 30) is a uartlite BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] ulite_console_setup+0x6f/0xa8 *pdpt = 0000000036fb0001 *pde = 0000000000000000 Oops: 0000 [#1] PREEMPT SMP last sysfs file: /sys/devices/pci0000:00/0000:00:1f.1/host0/uevent Modules linked in: puffin(+) serio_raw Pid: 151, comm: modprobe Not tainted (2.6.31.5-1.0.b1-b1 #1) POULSBO EIP: 0060:[] EFLAGS: 00010246 CPU: 0 EIP is at ulite_console_setup+0x6f/0xa8 EAX: c16ec824 EBX: c16ec824 ECX: c176719f EDX: 00000000 ESI: 00000000 EDI: c17b42c4 EBP: f6fd1cf0 ESP: f6fd1cd8 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Process modprobe (pid: 151, ti=f6fd0000 task=f6fa1020 task.ti=f6fd0000) Stack: c1031f51 00000000 00000000 00000246 c182237c f7742000 f6fd1d5c c11fd316 <0> c16ec85c f77420d4 0000001e 00000000 00000000 c1633e78 4f494d4d 63783020 <0> 30303038 00303031 f6fd1d3c c10e0786 f6fd1d48 00000000 f6fd1d48 00000000 Call Trace: [] ? register_console+0xf6/0x1fc [] ? uart_add_one_port+0x237/0x2bb [] ? sysfs_add_one+0x13/0xd3 [] ? sysfs_do_create_link+0xba/0xfc [] ? ulite_probe+0x198/0x1eb [] ? platform_drv_probe+0xc/0xe [] ? driver_probe_device+0x79/0x105 [] ? __device_attach+0x28/0x30 [] ? bus_for_each_drv+0x3d/0x67 [] ? device_attach+0x44/0x58 [] ? __device_attach+0x0/0x30 [] ? bus_probe_device+0x1f/0x34 [] ? device_add+0x385/0x4c0 [] ? _write_unlock+0x8/0x1f [] ? platform_device_add+0xd9/0x11c [] ? mfd_add_devices+0x165/0x1bc [] ? puffin_probe+0x2d0/0x390 [puffin] [] ? pci_match_device+0xa0/0xa7 [] ? local_pci_probe+0xe/0x10 [] ? pci_device_probe+0x43/0x66 [] ? driver_probe_device+0x79/0x105 [] ? __driver_attach+0x43/0x5f [] ? bus_for_each_dev+0x3d/0x67 [] ? driver_attach+0x14/0x16 [] ? __driver_attach+0x0/0x5f [] ? bus_add_driver+0xf9/0x220 [] ? driver_register+0x8b/0xeb [] ? __pci_register_driver+0x43/0x9f [] ? __blocking_notifier_call_chain+0x40/0x4c [] ? puffin_init+0x0/0x48 [puffin] [] ? puffin_init+0x17/0x48 [puffin] [] ? do_one_initcall+0x4c/0x131 [] ? sys_init_module+0xa7/0x1b7 [] ? syscall_call+0x7/0xb Code: 6e 74 00 00 00 92 33 00 00 18 00 0e 01 73 79 6e 63 65 2d 72 65 67 69 73 74 72 79 0c 00 49 32 00 00 14 00 09 01 61 6c 73 61 2d 69 <6e> 66 6f 00 00 00 42 37 00 00 10 00 07 01 6b 69 6c 6c 61 6c 6c EIP: [] ulite_console_setup+0x6f/0xa8 SS:ESP 0068:f6fd1cd8 CR2: 0000000000000000 Signed-off-by: Richard Röjfors Acked-by: Peter Korsgaard Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/serial/uartlite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index 377f2712289e..ab2ab3c81834 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -394,7 +394,7 @@ static void ulite_console_write(struct console *co, const char *s, spin_unlock_irqrestore(&port->lock, flags); } -static int __init ulite_console_setup(struct console *co, char *options) +static int __devinit ulite_console_setup(struct console *co, char *options) { struct uart_port *port; int baud = 9600; From 2c7f87e9dc8167999d4169b58f4be04fd357e9eb Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Tue, 2 Feb 2010 13:44:17 -0800 Subject: [PATCH 572/670] pktcdvd: removing device does not remove its sysfs dir commit ca0bf64d99f6e3f6e2fe2585e52a0ac57354beac upstream. This is the counterpart to cba767175becadc5c4016cceb7bfdd2c7fe722f4 ("pktcdvd: remove broken dev_t export of class devices"). Device is not registered using dev_t, so it should not be destroyed using device_destroy which looks up the device by dev_t. This will fail and adding the device again will fail with the "duplicate name" error. This is fixed using device_unregister instead of device_destroy. Signed-off-by: Thadeu Lima de Souza Cascardo Cc: Kay Sievers Cc: Peter Osterlund Cc: Al Viro Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/block/pktcdvd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 2ddf03ae034e..68b5957f107c 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -322,7 +322,7 @@ static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd) pkt_kobj_remove(pd->kobj_stat); pkt_kobj_remove(pd->kobj_wqueue); if (class_pktcdvd) - device_destroy(class_pktcdvd, pd->pkt_dev); + device_unregister(pd->dev); } From 1c97637c37d73d0afa0759468eec8132b442452f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 23 Jan 2010 20:04:18 +0100 Subject: [PATCH 573/670] ath9k: fix eeprom INI values override for 2GHz-only cards commit aa8bc9ef18a2c5b2b97e1f36ee9604cf15743f96 upstream. Among other changes, this commit: commit 06d0f0663e11cab4ec5f2c143a118d71a12fbbe9 Author: Sujith Date: Thu Feb 12 10:06:45 2009 +0530 ath9k: Enable Fractional N mode changed the hw attach code to fix up initialization values only for dual band devices, however the commit message did not give a reason as to why this would be useful or necessary. According to tests by Jorge Boncompte, this breaks at least some 2GHz-only cards, so the code should be changed back to the unconditional INI fixup. Signed-off-by: Felix Fietkau Reported-by: Jorge Boncompte Tested-by: Pavel Roskin Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/hw.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c7aa05a82877..0905b38f7b62 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -880,12 +880,11 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) } } -static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah) +static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) { u32 i, j; - if ((ah->hw_version.devid == AR9280_DEVID_PCI) && - test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) { + if (ah->hw_version.devid == AR9280_DEVID_PCI) { /* EEPROM Fixup */ for (i = 0; i < ah->iniModes.ia_rows; i++) { @@ -980,7 +979,7 @@ int ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_mode_gain_regs(ah); ath9k_hw_fill_cap_info(ah); - ath9k_hw_init_11a_eeprom_fix(ah); + ath9k_hw_init_eeprom_fix(ah); r = ath9k_hw_init_macaddr(ah); if (r) { From a420e9f34f545968efdf414de17c374445ef2589 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 19 Jan 2010 20:51:32 +0100 Subject: [PATCH 574/670] ath9k: fix beacon slot/buffer leak commit 74401773f80b6d42f7a4c6994ca0cca883b03745 upstream. When cleaning up beacon buffers and slots, ath9k currently checks if sc->ah->opmode is set to a beacon related mode before cleaning up buffers. An unfortunate ordering of interface up/down commands can lead to sc->ah->opmode being set to monitor mode, while there are AP interfaces present on the same wiphy. Always cleaning up beacon buffers if present fixes this issue. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 80df8f36c4ef..5864eaa53cfc 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2285,10 +2285,10 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { ath9k_ps_wakeup(sc); ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - ath_beacon_return(sc, avp); ath9k_ps_restore(sc); } + ath_beacon_return(sc, avp); sc->sc_flags &= ~SC_OP_BEACONS; for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { From e4a6a351099037e7d20ec8b21907f38f3e35d483 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Sat, 30 Jan 2010 10:20:59 +0000 Subject: [PATCH 575/670] powerpc: TIF_ABI_PENDING bit removal commit 94f28da8409c6059135e89ac64a0839993124155 upstream. Here are the powerpc bits to remove TIF_ABI_PENDING now that set_personality() is called at the appropriate place in exec. Signed-off-by: Andreas Schwab Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/elf.h | 8 ++------ arch/powerpc/include/asm/thread_info.h | 2 -- arch/powerpc/kernel/process.c | 12 ------------ 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index 014a624f4c8e..56985023a47d 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h @@ -236,14 +236,10 @@ typedef elf_vrregset_t elf_fpxregset_t; #ifdef __powerpc64__ # define SET_PERSONALITY(ex) \ do { \ - unsigned long new_flags = 0; \ if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ - new_flags = _TIF_32BIT; \ - if ((current_thread_info()->flags & _TIF_32BIT) \ - != new_flags) \ - set_thread_flag(TIF_ABI_PENDING); \ + set_thread_flag(TIF_32BIT); \ else \ - clear_thread_flag(TIF_ABI_PENDING); \ + clear_thread_flag(TIF_32BIT); \ if (personality(current->personality) != PER_LINUX32) \ set_personality(PER_LINUX | \ (current->personality & (~PER_MASK))); \ diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index c8b329255678..aa9d383a1c09 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -111,7 +111,6 @@ static inline struct thread_info *current_thread_info(void) #define TIF_NOTIFY_RESUME 13 /* callback before returning to user */ #define TIF_FREEZE 14 /* Freezing for suspend */ #define TIF_RUNLATCH 15 /* Is the runlatch enabled? */ -#define TIF_ABI_PENDING 16 /* 32/64 bit switch needed */ /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1<thread.dabr) { From 6117db7678e1175d482ce4a2a31203d39f050319 Mon Sep 17 00:00:00 2001 From: jamal Date: Thu, 4 Feb 2010 14:50:56 -0500 Subject: [PATCH 576/670] NET: fix oops at bootime in sysctl code This fixes the boot time oops on the 2.6.32-stable tree. It is needed only in this tree due to the divergance from upstream. From: jamal Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- kernel/sysctl_check.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c index b6e7aaea4604..469193ccf5b7 100644 --- a/kernel/sysctl_check.c +++ b/kernel/sysctl_check.c @@ -220,6 +220,7 @@ static const struct trans_ctl_table trans_net_ipv4_conf_vars_table[] = { { NET_IPV4_CONF_PROMOTE_SECONDARIES, "promote_secondaries" }, { NET_IPV4_CONF_ARP_ACCEPT, "arp_accept" }, { NET_IPV4_CONF_ARP_NOTIFY, "arp_notify" }, + { NET_IPV4_CONF_SRC_VMARK, "src_valid_mark" }, {} }; From b0e43706172ebfee90c82337dfae49119a4e722e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 9 Feb 2010 04:57:19 -0800 Subject: [PATCH 577/670] Linux 2.6.32.8 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 07d3c6ac5502..f282cab90dc4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = .7 +EXTRAVERSION = .8 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* From 7313f5ad0cb1b501cbe67cf6c2dee018a2aa3321 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 5 Feb 2010 16:16:50 -0800 Subject: [PATCH 578/670] Fix potential crash with sys_move_pages commit 6f5a55f1a6c5abee15a0e878e5c74d9f1569b8b0 upstream. We incorrectly depended on the 'node_state/node_isset()' functions testing the node range, rather than checking it explicitly. That's not reliable, even if it might often happen to work. So do the proper explicit test. Reported-by: Marcus Meissner Acked-and-tested-by: Brice Goglin Acked-by: Hugh Dickins Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/migrate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/migrate.c b/mm/migrate.c index 7dbcb22316d2..0e39f94b2d9c 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -953,6 +953,9 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task, goto out_pm; err = -ENODEV; + if (node < 0 || node >= MAX_NUMNODES) + goto out_pm; + if (!node_state(node, N_HIGH_MEMORY)) goto out_pm; From 5f6af116c22817a6fe1999cc2d3925897af89086 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Sat, 23 Jan 2010 22:36:29 +0100 Subject: [PATCH 579/670] futex_lock_pi() key refcnt fix commit 5ecb01cfdf96c5f465192bdb2a4fd4a61a24c6cc upstream. This fixes a futex key reference count bug in futex_lock_pi(), where a key's reference count is incremented twice but decremented only once, causing the backing object to not be released. If the futex is created in a temporary file in an ext3 file system, this bug causes the file's inode to become an "undead" orphan, which causes an oops from a BUG_ON() in ext3_put_super() when the file system is unmounted. glibc's test suite is known to trigger this, see . The bug is a regression from 2.6.28-git3, namely Peter Zijlstra's 38d47c1b7075bd7ec3881141bb3629da58f88dab "[PATCH] futex: rely on get_user_pages() for shared futexes". That commit made get_futex_key() also increment the reference count of the futex key, and updated its callers to decrement the key's reference count before returning. Unfortunately the normal exit path in futex_lock_pi() wasn't corrected: the reference count is incremented by get_futex_key() and queue_lock(), but the normal exit path only decrements once, via unqueue_me_pi(). The fix is to put_futex_key() after unqueue_me_pi(), since 2.6.31 this is easily done by 'goto out_put_key' rather than 'goto out'. Signed-off-by: Mikael Pettersson Acked-by: Peter Zijlstra Acked-by: Darren Hart Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/futex.c b/kernel/futex.c index 3b749090411d..af6f896f5313 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1971,7 +1971,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, /* Unqueue and drop the lock */ unqueue_me_pi(&q); - goto out; + goto out_put_key; out_unlock_put_key: queue_unlock(&q, hb); From c03d9d422d8dd3e8d2cd9e200e420bbaed5cb577 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 2 Feb 2010 11:40:27 +0100 Subject: [PATCH 580/670] futex: Handle user space corruption gracefully commit 51246bfd189064079c54421507236fd2723b18f3 upstream. If the owner of a PI futex dies we fix up the pi_state and set pi_state->owner to NULL. When a malicious or just sloppy programmed user space application sets the futex value to 0 e.g. by calling pthread_mutex_init(), then the futex can be acquired again. A new waiter manages to enqueue itself on the pi_state w/o damage, but on unlock the kernel dereferences pi_state->owner and oopses. Prevent this by checking pi_state->owner in the unlock path. If pi_state->owner is not current we know that user space manipulated the futex value. Ignore the mess and return -EINVAL. This catches the above case and also the case where a task hijacks the futex by setting the tid value and then tries to unlock it. Reported-by: Jermome Marchand Signed-off-by: Thomas Gleixner Acked-by: Darren Hart Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/futex.c b/kernel/futex.c index af6f896f5313..eed4a9cbddda 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -758,6 +758,13 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) if (!pi_state) return -EINVAL; + /* + * If current does not own the pi_state then the futex is + * inconsistent and user space fiddled with the futex value. + */ + if (pi_state->owner != current) + return -EINVAL; + spin_lock(&pi_state->pi_mutex.wait_lock); new_owner = rt_mutex_next_owner(&pi_state->pi_mutex); From 22240ab64b5c6e76b3aa011808111cc3aed0a1ff Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 3 Feb 2010 09:33:05 +0100 Subject: [PATCH 581/670] futex: Handle futex value corruption gracefully commit 59647b6ac3050dd964bc556fe6ef22f4db5b935c upstream. The WARN_ON in lookup_pi_state which complains about a mismatch between pi_state->owner->pid and the pid which we retrieved from the user space futex is completely bogus. The code just emits the warning and then continues despite the fact that it detected an inconsistent state of the futex. A conveniant way for user space to spam the syslog. Replace the WARN_ON by a consistency check. If the values do not match return -EINVAL and let user space deal with the mess it created. This also fixes the missing task_pid_vnr() when we compare the pi_state->owner pid with the futex value. Reported-by: Jermome Marchand Signed-off-by: Thomas Gleixner Acked-by: Darren Hart Acked-by: Peter Zijlstra Signed-off-by: Greg Kroah-Hartman --- kernel/futex.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index eed4a9cbddda..1ad4fa6db725 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -530,8 +530,25 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, return -EINVAL; WARN_ON(!atomic_read(&pi_state->refcount)); - WARN_ON(pid && pi_state->owner && - pi_state->owner->pid != pid); + + /* + * When pi_state->owner is NULL then the owner died + * and another waiter is on the fly. pi_state->owner + * is fixed up by the task which acquires + * pi_state->rt_mutex. + * + * We do not check for pid == 0 which can happen when + * the owner died and robust_list_exit() cleared the + * TID. + */ + if (pid && pi_state->owner) { + /* + * Bail out if user space manipulated the + * futex value. + */ + if (pid != task_pid_vnr(pi_state->owner)) + return -EINVAL; + } atomic_inc(&pi_state->refcount); *ps = pi_state; From 3520341ce308afaf676c961e8432ff5c87d3121b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 7 Feb 2010 10:11:23 -0800 Subject: [PATCH 582/670] Fix race in tty_fasync() properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 80e1e823989ec44d8e35bdfddadbddcffec90424 upstream. This reverts commit 703625118069 ("tty: fix race in tty_fasync") and commit b04da8bfdfbb ("fnctl: f_modown should call write_lock_irqsave/ restore") that tried to fix up some of the fallout but was incomplete. It turns out that we really cannot hold 'tty->ctrl_lock' over calling __f_setown, because not only did that cause problems with interrupt disables (which the second commit fixed), it also causes a potential ABBA deadlock due to lock ordering. Thanks to Tetsuo Handa for following up on the issue, and running lockdep to show the problem. It goes roughly like this: - f_getown gets filp->f_owner.lock for reading without interrupts disabled, so an interrupt that happens while that lock is held can cause a lockdep chain from f_owner.lock -> sighand->siglock. - at the same time, the tty->ctrl_lock -> f_owner.lock chain that commit 703625118069 introduced, together with the pre-existing sighand->siglock -> tty->ctrl_lock chain means that we have a lock dependency the other way too. So instead of extending tty->ctrl_lock over the whole __f_setown() call, we now just take a reference to the 'pid' structure while holding the lock, and then release it after having done the __f_setown. That still guarantees that 'struct pid' won't go away from under us, which is all we really ever needed. Reported-and-tested-by: Tetsuo Handa Acked-by: Greg Kroah-Hartman Acked-by: Américo Wang Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_io.c | 4 +++- fs/fcntl.c | 6 ++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index e919bd9c92d2..05cab2cea85e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1930,8 +1930,10 @@ static int tty_fasync(int fd, struct file *filp, int on) pid = task_pid(current); type = PIDTYPE_PID; } - retval = __f_setown(filp, pid, type, 0); + get_pid(pid); spin_unlock_irqrestore(&tty->ctrl_lock, flags); + retval = __f_setown(filp, pid, type, 0); + put_pid(pid); if (retval) goto out; } else { diff --git a/fs/fcntl.c b/fs/fcntl.c index 5ef953e6f908..97e01dc0d95f 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -199,9 +199,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg) static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, int force) { - unsigned long flags; - - write_lock_irqsave(&filp->f_owner.lock, flags); + write_lock_irq(&filp->f_owner.lock); if (force || !filp->f_owner.pid) { put_pid(filp->f_owner.pid); filp->f_owner.pid = get_pid(pid); @@ -213,7 +211,7 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, filp->f_owner.euid = cred->euid; } } - write_unlock_irqrestore(&filp->f_owner.lock, flags); + write_unlock_irq(&filp->f_owner.lock); } int __f_setown(struct file *filp, struct pid *pid, enum pid_type type, From 3659b59c77436fb29437cb57cdd72a26de0ded8c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 5 Feb 2010 19:58:36 +0100 Subject: [PATCH 583/670] hwmon: (w83781d) Request I/O ports individually for probing commit b0bcdd3cd0adb85a7686b396ba50493871b1135c upstream. Different motherboards have different PNP declarations for W83781D/W83782D chips. Some declare the whole range of I/O ports (8 ports), some declare only the useful ports (2 ports at offset 5) and some declare fancy ranges, for example 4 ports at offset 4. To properly handle all cases, request all ports individually for probing. After we have determined that we really have a W83781D or W83782D chip, the useful port range will be requested again, as a single block. I did not see a board which needs this yet, but I know of one for lm78 driver and I'd like to keep the logic of these two drivers in sync. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83781d.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index d27ed1bac002..f0b6883fb4da 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -1818,17 +1818,17 @@ static int __init w83781d_isa_found(unsigned short address) { int val, save, found = 0; + int port; - /* We have to request the region in two parts because some - boards declare base+4 to base+7 as a PNP device */ - if (!request_region(address, 4, "w83781d")) { - pr_debug("w83781d: Failed to request low part of region\n"); - return 0; - } - if (!request_region(address + 4, 4, "w83781d")) { - pr_debug("w83781d: Failed to request high part of region\n"); - release_region(address, 4); - return 0; + /* Some boards declare base+0 to base+7 as a PNP device, some base+4 + * to base+7 and some base+5 to base+6. So we better request each port + * individually for the probing phase. */ + for (port = address; port < address + W83781D_EXTENT; port++) { + if (!request_region(port, 1, "w83781d")) { + pr_debug("w83781d: Failed to request port 0x%x\n", + port); + goto release; + } } #define REALLY_SLOW_IO @@ -1902,8 +1902,8 @@ w83781d_isa_found(unsigned short address) val == 0x30 ? "W83782D" : "W83781D", (int)address); release: - release_region(address + 4, 4); - release_region(address, 4); + for (port--; port >= address; port--) + release_region(port, 1); return found; } From 3f28a62b9db311d6f45a5b0d7a9b2d4daae4afe1 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 5 Feb 2010 19:58:36 +0100 Subject: [PATCH 584/670] hwmon: (lm78) Request I/O ports individually for probing commit 197027e6ef830d60e10f76efc8d12bf3b6c35db5 upstream. Different motherboards have different PNP declarations for LM78/LM79 chips. Some declare the whole range of I/O ports (8 ports), some declare only the useful ports (2 ports at offset 5) and some declare fancy ranges, for example 4 ports at offset 4. To properly handle all cases, request all ports individually for probing. After we have determined that we really have an LM78 or LM79 chip, the useful port range will be requested again, as a single block. This fixes the driver on the Olivetti M3000 DT 540, at least. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/lm78.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index f7e70163e016..1508e0ad1830 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -870,17 +870,16 @@ static struct lm78_data *lm78_update_device(struct device *dev) static int __init lm78_isa_found(unsigned short address) { int val, save, found = 0; + int port; - /* We have to request the region in two parts because some - boards declare base+4 to base+7 as a PNP device */ - if (!request_region(address, 4, "lm78")) { - pr_debug("lm78: Failed to request low part of region\n"); - return 0; - } - if (!request_region(address + 4, 4, "lm78")) { - pr_debug("lm78: Failed to request high part of region\n"); - release_region(address, 4); - return 0; + /* Some boards declare base+0 to base+7 as a PNP device, some base+4 + * to base+7 and some base+5 to base+6. So we better request each port + * individually for the probing phase. */ + for (port = address; port < address + LM78_EXTENT; port++) { + if (!request_region(port, 1, "lm78")) { + pr_debug("lm78: Failed to request port 0x%x\n", port); + goto release; + } } #define REALLY_SLOW_IO @@ -944,8 +943,8 @@ static int __init lm78_isa_found(unsigned short address) val & 0x80 ? "LM79" : "LM78", (int)address); release: - release_region(address + 4, 4); - release_region(address, 4); + for (port--; port >= address; port--) + release_region(port, 1); return found; } From ea5d622831d40005e9219658d4987b1efd2350ab Mon Sep 17 00:00:00 2001 From: Ray Copeland Date: Fri, 5 Feb 2010 19:58:35 +0100 Subject: [PATCH 585/670] hwmon: (adt7462) Wrong ADT7462_VOLT_COUNT commit 85f8d3e5faea8bd36c3e5196f8334f7db45e19b2 upstream. The #define ADT7462_VOLT_COUNT is wrong, it should be 13 not 12. All the for loops that use this as a limit count are of the typical form, "for (n = 0; n < ADT7462_VOLT_COUNT; n++)", so to loop through all voltages w/o missing the last one it is necessary for the count to be one greater than it is. (Specifically, you will miss the +1.5V 3GPIO input with count = 12 vs. 13.) Signed-off-by: Ray Copeland Acked-by: "Darrick J. Wong" Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/adt7462.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index 262c133048ce..14f910d3dd9b 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -182,7 +182,7 @@ I2C_CLIENT_INSMOD_1(adt7462); * * Some, but not all, of these voltages have low/high limits. */ -#define ADT7462_VOLT_COUNT 12 +#define ADT7462_VOLT_COUNT 13 #define ADT7462_VENDOR 0x41 #define ADT7462_DEVICE 0x62 From c58b0c5ba927f27a610bb6b0b08b2d6288d5da17 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 2 Feb 2010 19:58:25 +0100 Subject: [PATCH 586/670] ALSA: ctxfi - fix PTP address initialization commit 21956b61f594f7924d98240da74bc81c28601fa9 upstream. After hours of debugging, I finally found the reason why some source and runtime combination does not work. The PTP (page table pages) address must be aligned. I am not sure how much, but alignment to PAGE_SIZE is sufficient. Also, use ALSA's page allocation routines to ensure proper virtual -> physical address translation. Signed-off-by: Jaroslav Kysela Signed-off-by: Greg Kroah-Hartman --- sound/pci/ctxfi/ctatc.c | 15 ++------------- sound/pci/ctxfi/ctvmem.c | 38 ++++++++++++++++++-------------------- sound/pci/ctxfi/ctvmem.h | 8 +++++--- 3 files changed, 25 insertions(+), 36 deletions(-) diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 75454648d50c..cb1f53373653 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -166,18 +166,7 @@ static void ct_unmap_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm) static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index) { - struct ct_vm *vm; - void *kvirt_addr; - unsigned long phys_addr; - - vm = atc->vm; - kvirt_addr = vm->get_ptp_virt(vm, index); - if (kvirt_addr == NULL) - phys_addr = (~0UL); - else - phys_addr = virt_to_phys(kvirt_addr); - - return phys_addr; + return atc->vm->get_ptp_phys(atc->vm, index); } static unsigned int convert_format(snd_pcm_format_t snd_format) @@ -1669,7 +1658,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, } /* Set up device virtual memory management object */ - err = ct_vm_create(&atc->vm); + err = ct_vm_create(&atc->vm, pci); if (err < 0) goto error1; diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c index 6b78752e9503..65da6e466f80 100644 --- a/sound/pci/ctxfi/ctvmem.c +++ b/sound/pci/ctxfi/ctvmem.c @@ -138,7 +138,7 @@ ct_vm_map(struct ct_vm *vm, struct snd_pcm_substream *substream, int size) return NULL; } - ptp = vm->ptp[0]; + ptp = (unsigned long *)vm->ptp[0].area; pte_start = (block->addr >> CT_PAGE_SHIFT); pages = block->size >> CT_PAGE_SHIFT; for (i = 0; i < pages; i++) { @@ -158,25 +158,25 @@ static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block) } /* * - * return the host (kmalloced) addr of the @index-th device - * page talbe page on success, or NULL on failure. - * The first returned NULL indicates the termination. + * return the host physical addr of the @index-th device + * page table page on success, or ~0UL on failure. + * The first returned ~0UL indicates the termination. * */ -static void * -ct_get_ptp_virt(struct ct_vm *vm, int index) +static dma_addr_t +ct_get_ptp_phys(struct ct_vm *vm, int index) { - void *addr; + dma_addr_t addr; - addr = (index >= CT_PTP_NUM) ? NULL : vm->ptp[index]; + addr = (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr; return addr; } -int ct_vm_create(struct ct_vm **rvm) +int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci) { struct ct_vm *vm; struct ct_vm_block *block; - int i; + int i, err = 0; *rvm = NULL; @@ -188,23 +188,21 @@ int ct_vm_create(struct ct_vm **rvm) /* Allocate page table pages */ for (i = 0; i < CT_PTP_NUM; i++) { - vm->ptp[i] = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!vm->ptp[i]) + err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(pci), + PAGE_SIZE, &vm->ptp[i]); + if (err < 0) break; } - if (!i) { + if (err < 0) { /* no page table pages are allocated */ - kfree(vm); + ct_vm_destroy(vm); return -ENOMEM; } vm->size = CT_ADDRS_PER_PAGE * i; - /* Initialise remaining ptps */ - for (; i < CT_PTP_NUM; i++) - vm->ptp[i] = NULL; - vm->map = ct_vm_map; vm->unmap = ct_vm_unmap; - vm->get_ptp_virt = ct_get_ptp_virt; + vm->get_ptp_phys = ct_get_ptp_phys; INIT_LIST_HEAD(&vm->unused); INIT_LIST_HEAD(&vm->used); block = kzalloc(sizeof(*block), GFP_KERNEL); @@ -242,7 +240,7 @@ void ct_vm_destroy(struct ct_vm *vm) /* free allocated page table pages */ for (i = 0; i < CT_PTP_NUM; i++) - kfree(vm->ptp[i]); + snd_dma_free_pages(&vm->ptp[i]); vm->size = 0; diff --git a/sound/pci/ctxfi/ctvmem.h b/sound/pci/ctxfi/ctvmem.h index 01e4fd0386a3..b23adfca4de6 100644 --- a/sound/pci/ctxfi/ctvmem.h +++ b/sound/pci/ctxfi/ctvmem.h @@ -22,6 +22,8 @@ #include #include +#include +#include /* The chip can handle the page table of 4k pages * (emu20k1 can handle even 8k pages, but we don't use it right now) @@ -41,7 +43,7 @@ struct snd_pcm_substream; /* Virtual memory management object for card device */ struct ct_vm { - void *ptp[CT_PTP_NUM]; /* Device page table pages */ + struct snd_dma_buffer ptp[CT_PTP_NUM]; /* Device page table pages */ unsigned int size; /* Available addr space in bytes */ struct list_head unused; /* List of unused blocks */ struct list_head used; /* List of used blocks */ @@ -52,10 +54,10 @@ struct ct_vm { int size); /* Unmap device logical addr area. */ void (*unmap)(struct ct_vm *, struct ct_vm_block *block); - void *(*get_ptp_virt)(struct ct_vm *vm, int index); + dma_addr_t (*get_ptp_phys)(struct ct_vm *vm, int index); }; -int ct_vm_create(struct ct_vm **rvm); +int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci); void ct_vm_destroy(struct ct_vm *vm); #endif /* CTVMEM_H */ From 6240058ce3725f5e708e1c17c3a676217e44ba9b Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 25 Jan 2010 10:35:16 +0800 Subject: [PATCH 587/670] drm/i915: disable hotplug detect before Ironlake CRT detect commit eceb784cec4dc0fcc2993d9ee4a7c0d111ada80a upstream. This tries to fix CRT detect loop hang seen on some Ironlake form factor, to clear up hotplug detect state before taking CRT detect to make sure next hotplug detect cycle is consistent. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_crt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6d3730f327cf..5e730e6f8a74 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -185,6 +185,9 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector) adpa = I915_READ(PCH_ADPA); adpa &= ~ADPA_CRT_HOTPLUG_MASK; + /* disable HPD first */ + I915_WRITE(PCH_ADPA, adpa); + (void)I915_READ(PCH_ADPA); adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 | ADPA_CRT_HOTPLUG_WARMUP_10MS | From e0ddca206e8b551662316053087e9e1184f11a34 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 19 Oct 2009 10:08:17 +0900 Subject: [PATCH 588/670] drm/i915: enable self-refresh on 965 commit 1dc7546d1a73664e5d117715b214bea9cae5951c upstream. Need to calculate the SR watermark and enable it. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 32 ++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 601415dc17bf..e41f9e6582d2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2556,15 +2556,39 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); } -static void i965_update_wm(struct drm_device *dev, int unused, int unused2, - int unused3, int unused4) +static void i965_update_wm(struct drm_device *dev, int planea_clock, + int planeb_clock, int sr_hdisplay, int pixel_size) { struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long line_time_us; + int sr_clock, sr_entries, srwm = 1; - DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n"); + /* Calc sr entries for one plane configs */ + if (sr_hdisplay && (!planea_clock || !planeb_clock)) { + /* self-refresh has much higher latency */ + const static int sr_latency_ns = 12000; + + sr_clock = planea_clock ? planea_clock : planeb_clock; + line_time_us = ((sr_hdisplay * 1000) / sr_clock); + + /* Use ns/us then divide to preserve precision */ + sr_entries = (((sr_latency_ns / line_time_us) + 1) * + pixel_size * sr_hdisplay) / 1000; + sr_entries = roundup(sr_entries / I915_FIFO_LINE_SIZE, 1); + DRM_DEBUG("self-refresh entries: %d\n", sr_entries); + srwm = I945_FIFO_SIZE - sr_entries; + if (srwm < 0) + srwm = 1; + srwm &= 0x3f; + I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); + } + + DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n", + srwm); /* 965 has limitations... */ - I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0)); + I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | (8 << 16) | (8 << 8) | + (8 << 0)); I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); } From de00361567b613202c24bb31d48481da6d9d2959 Mon Sep 17 00:00:00 2001 From: David John Date: Wed, 27 Jan 2010 15:19:08 +0530 Subject: [PATCH 589/670] drm/i915: Disable SR when more than one pipe is enabled commit 33c5fd121eabbccc9103daf6cda36941eb3c349f upstream. Self Refresh should be disabled on dual plane configs. Otherwise, as the SR watermark is not calculated for such configs, switching to non VGA mode causes FIFO underrun and display flicker. This fixes Korg Bug #14897. Signed-off-by: David John Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e41f9e6582d2..c4b8d2a16d80 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2538,6 +2538,10 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, sr_entries = roundup(sr_entries / cacheline_size, 1); DRM_DEBUG("self-refresh entries: %d\n", sr_entries); I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); + } else { + /* Turn off self refresh if both pipes are enabled */ + I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) + & ~FW_BLC_SELF_EN); } DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", @@ -2581,6 +2585,10 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, srwm = 1; srwm &= 0x3f; I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); + } else { + /* Turn off self refresh if both pipes are enabled */ + I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) + & ~FW_BLC_SELF_EN); } DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n", @@ -2649,6 +2657,10 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, if (srwm < 0) srwm = 1; I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f)); + } else { + /* Turn off self refresh if both pipes are enabled */ + I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) + & ~FW_BLC_SELF_EN); } DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", From 89fcd01fc9e169e4082c842b82cc428b3693f4b3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 1 Dec 2009 11:56:30 -0800 Subject: [PATCH 590/670] drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup. commit f0217c42c9ab3d772e543f635ce628b9478f70b6 upstream. This is a sync of a fix I made in the old UMS code. If the BIOS uses the GMBUS and doesn't clear that setup, then our bit-banging I2C can fail, leading to monitors not being detected. Signed-off-by: Eric Anholt Cc: maximilian attems Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 14 ++++++++++++++ drivers/gpu/drm/i915/i915_suspend.c | 5 ++++- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_i2c.c | 19 +++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fd537f4af52c..d5af2fbf7de4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -405,6 +405,13 @@ # define GPIO_DATA_VAL_IN (1 << 12) # define GPIO_DATA_PULLUP_DISABLE (1 << 13) +#define GMBUS0 0x5100 +#define GMBUS1 0x5104 +#define GMBUS2 0x5108 +#define GMBUS3 0x510c +#define GMBUS4 0x5110 +#define GMBUS5 0x5120 + /* * Clock control & power management */ @@ -2153,6 +2160,13 @@ #define PCH_GPIOE 0xc5020 #define PCH_GPIOF 0xc5024 +#define PCH_GMBUS0 0xc5100 +#define PCH_GMBUS1 0xc5104 +#define PCH_GMBUS2 0xc5108 +#define PCH_GMBUS3 0xc510c +#define PCH_GMBUS4 0xc5110 +#define PCH_GMBUS5 0xc5120 + #define PCH_DPLL_A 0xc6014 #define PCH_DPLL_B 0xc6018 diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 6eec8171a44e..7ad742f3517e 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -27,7 +27,7 @@ #include "drmP.h" #include "drm.h" #include "i915_drm.h" -#include "i915_drv.h" +#include "intel_drv.h" static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) { @@ -846,6 +846,9 @@ int i915_restore_state(struct drm_device *dev) for (i = 0; i < 3; i++) I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); + /* I2C state */ + intel_i2c_reset_gmbus(dev); + return 0; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ef61fe9507e2..6c7c19f4cfaf 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -134,6 +134,8 @@ void intel_i2c_destroy(struct i2c_adapter *adapter); int intel_ddc_get_modes(struct intel_output *intel_output); extern bool intel_ddc_probe(struct intel_output *intel_output); void intel_i2c_quirk_set(struct drm_device *dev, bool enable); +void intel_i2c_reset_gmbus(struct drm_device *dev); + extern void intel_crt_init(struct drm_device *dev); extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); extern bool intel_sdvo_init(struct drm_device *dev, int output_device); diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index c7eab724c418..b94acc4cc05f 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -118,6 +118,23 @@ static void set_data(void *data, int state_high) udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ } +/* Clears the GMBUS setup. Our driver doesn't make use of the GMBUS I2C + * engine, but if the BIOS leaves it enabled, then that can break our use + * of the bit-banging I2C interfaces. This is notably the case with the + * Mac Mini in EFI mode. + */ +void +intel_i2c_reset_gmbus(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (IS_IGDNG(dev)) { + I915_WRITE(PCH_GMBUS0, 0); + } else { + I915_WRITE(GMBUS0, 0); + } +} + /** * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg * @dev: DRM device @@ -168,6 +185,8 @@ struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, if(i2c_bit_add_bus(&chan->adapter)) goto out_free; + intel_i2c_reset_gmbus(dev); + /* JJJ: raise SCL and SDA? */ intel_i2c_quirk_set(dev, true); set_data(chan, 1); From 192ff23a2206eb5136c779bfed73171a4d214ad6 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 13:30:36 +0800 Subject: [PATCH 591/670] drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list commit 40f33a92100f4d9b6e85ad642100cfe42d7ff57d upstream. The HP comaq nx9020/Samsung SX20S laptop always report that the LID status is closed and we can't use it reliabily for LVDS detection. So add the two boxes into the quirk list. http://bugzilla.kernel.org/show_bug.cgi?id=14957 http://bugzilla.kernel.org/show_bug.cgi?id=14554 Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_lvds.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 0e0e4b47a7d0..7b1908bacf84 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -601,6 +601,20 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, /* Some lid devices report incorrect lid status, assume they're connected */ static const struct dmi_system_id bad_lid_status[] = { + { + .ident = "Compaq nx9020", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_BOARD_NAME, "3084"), + }, + }, + { + .ident = "Samsung SX20S", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_BOARD_NAME, "SX20S"), + }, + }, { .ident = "Aspire One", .matches = { From 215bccb7df012f5d1fcf3e686c0a8167cea91ad3 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Thu, 21 Jan 2010 15:20:18 +0800 Subject: [PATCH 592/670] drm/i915: Fix the incorrect DMI string for Samsung SX20S laptop commit f034b12dbb5749b11e9390e15e93ffa87ece8038 upstream. Signed-off-by: Zhao Yakui Reported-by: Philipp Kohlbecher Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_lvds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 7b1908bacf84..972770662d9d 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -611,7 +611,7 @@ static const struct dmi_system_id bad_lid_status[] = { { .ident = "Samsung SX20S", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"), DMI_MATCH(DMI_BOARD_NAME, "SX20S"), }, }, From 6ea0e838a5594a90c5a0a4fdf989831e34684cb0 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 11 Dec 2009 09:26:10 +0800 Subject: [PATCH 593/670] drm/i915: Add MALATA PC-81005 to ACPI LID quirk list commit a3cb5195f6db58dbebd8a31b877ddce082c9b63d upstream. The MALATA PC-81005 laptop always reports that the LID status is closed and we can't use it reliabily for LVDS detection. So add this box into the quirk list. https://bugs.freedesktop.org/show_bug.cgi?id=25523 Signed-off-by: Zhao Yakui Review-by: Jesse Barnes Tested-by: Hector Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_lvds.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 972770662d9d..952bb4e2484d 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -622,6 +622,13 @@ static const struct dmi_system_id bad_lid_status[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"), }, }, + { + .ident = "PC-81005", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MALATA"), + DMI_MATCH(DMI_PRODUCT_NAME, "PC-81005"), + }, + }, { } }; From ce460107ed450221d040be0cf088973e58ad23eb Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 4 Feb 2010 06:57:58 +0000 Subject: [PATCH 594/670] usb: r8a66597-hcd: Flush the D-cache for the pipe-in transfer buffers. commit 2717568e7c44fe7dc3f4f52ea823811cfeede2b5 upstream. This implements the same D-cache flushing logic for r8a66597-hcd as Catalin's isp1760 (http://patchwork.kernel.org/patch/76391/) change, with the same note applying here as well: When the HDC driver writes the data to the transfer buffers it pollutes the D-cache (unlike DMA drivers where the device writes the data). If the corresponding pages get mapped into user space, there are no additional cache flushing operations performed and this causes random user space faults on architectures with separate I and D caches (Harvard) or those with aliasing D-cache. This fixes up crashes during USB boot on SH7724 and others: http://marc.info/?l=linux-sh&m=126439837308912&w=2 Reported-by: Goda Yusuke Tested-by: Goda Yusuke Signed-off-by: Paul Mundt Acked-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 37 ++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 5b56f53bbeda..9260c743baa6 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -35,7 +35,9 @@ #include #include #include +#include #include +#include #include "../core/hcd.h" #include "r8a66597.h" @@ -820,6 +822,26 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb, enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb); } +static void r8a66597_urb_done(struct r8a66597 *r8a66597, struct urb *urb, + int status) +__releases(r8a66597->lock) +__acquires(r8a66597->lock) +{ + if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) { + void *ptr; + + for (ptr = urb->transfer_buffer; + ptr < urb->transfer_buffer + urb->transfer_buffer_length; + ptr += PAGE_SIZE) + flush_dcache_page(virt_to_page(ptr)); + } + + usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); + spin_unlock(&r8a66597->lock); + usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, status); + spin_lock(&r8a66597->lock); +} + /* this function must be called with interrupt disabled */ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) { @@ -840,15 +862,9 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) list_del(&td->queue); kfree(td); - if (urb) { - usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), - urb); + if (urb) + r8a66597_urb_done(r8a66597, urb, -ENODEV); - spin_unlock(&r8a66597->lock); - usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, - -ENODEV); - spin_lock(&r8a66597->lock); - } break; } } @@ -1285,10 +1301,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock) if (usb_pipeisoc(urb->pipe)) urb->start_frame = r8a66597_get_frame(hcd); - usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); - spin_unlock(&r8a66597->lock); - usb_hcd_giveback_urb(hcd, urb, status); - spin_lock(&r8a66597->lock); + r8a66597_urb_done(r8a66597, urb, status); } if (restart) { From 17eff773b4c988e6de965446283de7315ffbac85 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 5 Feb 2010 17:48:13 +0100 Subject: [PATCH 595/670] i2c-tiny-usb: Fix on big-endian systems commit 1c010ff8912cbc08d80e865aab9c32b6b00c527d upstream. The functionality bit vector is always returned as a little-endian 32-bit number by the device, so it must be byte-swapped to the host endianness. On the other hand, the delay value is handled by the USB stack, so no byte swapping is needed on our side. This fixes bug #15105: http://bugzilla.kernel.org/show_bug.cgi?id=15105 Reported-by: Jens Richter Signed-off-by: Jean Delvare Tested-by: Jens Richter Cc: Till Harbaum Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-tiny-usb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index b1c050ff311d..e29b6d5ba8ef 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -13,6 +13,7 @@ #include #include #include +#include /* include interfaces to usb layer */ #include @@ -31,8 +32,8 @@ #define CMD_I2C_IO_END (1<<1) /* i2c bit delay, default is 10us -> 100kHz */ -static int delay = 10; -module_param(delay, int, 0); +static unsigned short delay = 10; +module_param(delay, ushort, 0); MODULE_PARM_DESC(delay, "bit delay in microseconds, " "e.g. 10 for 100kHz (default is 100kHz)"); @@ -109,7 +110,7 @@ static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) static u32 usb_func(struct i2c_adapter *adapter) { - u32 func; + __le32 func; /* get functionality from adapter */ if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) != @@ -118,7 +119,7 @@ static u32 usb_func(struct i2c_adapter *adapter) return 0; } - return func; + return le32_to_cpu(func); } /* This is the actual algorithm we define */ @@ -216,8 +217,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, "i2c-tiny-usb at bus %03d device %03d", dev->usb_dev->bus->busnum, dev->usb_dev->devnum); - if (usb_write(&dev->adapter, CMD_SET_DELAY, - cpu_to_le16(delay), 0, NULL, 0) != 0) { + if (usb_write(&dev->adapter, CMD_SET_DELAY, delay, 0, NULL, 0) != 0) { dev_err(&dev->adapter.dev, "failure setting delay to %dus\n", delay); retval = -EIO; From d37bec021841c4388e9046d331291b4787932fdf Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Sat, 6 Feb 2010 10:41:53 -0800 Subject: [PATCH 596/670] drm/i915: handle FBC and self-refresh better commit ee25df2bc379728c45d81e04cf87984db1425edf upstream. On 945, we need to avoid entering self-refresh if the compressor is busy, or we may cause display FIFO underruns leading to ugly flicker. Fixes fdo bug #24314, kernel bug #15043. Tested-by: Alexander Lam Signed-off-by: Jesse Barnes Tested-by: Julien Cristau (fd.o #25371) Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d5af2fbf7de4..cc9b49ab1fd0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -329,6 +329,7 @@ #define FBC_CTL_PERIODIC (1<<30) #define FBC_CTL_INTERVAL_SHIFT (16) #define FBC_CTL_UNCOMPRESSIBLE (1<<14) +#define FBC_C3_IDLE (1<<13) #define FBC_CTL_STRIDE_SHIFT (5) #define FBC_CTL_FENCENO (1<<0) #define FBC_COMMAND 0x0320c diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c4b8d2a16d80..2d6f8ba0ba08 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -988,6 +988,8 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) /* enable it... */ fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; + if (IS_I945GM(dev)) + fbc_ctl |= FBC_C3_IDLE; /* 945 needs special SR handling */ fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; if (obj_priv->tiling_mode != I915_TILING_NONE) From 68c12bf53608bceef97da294778dfa10349c7223 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 9 Feb 2010 14:14:36 +0000 Subject: [PATCH 597/670] drm/i915: Increase fb alignment to 64k commit fd2e8ea597222b8f38ae8948776a61ea7958232e upstream. An untiled framebuffer must be aligned to 64k. This is normally handled by intel_pin_and_fence_fb_obj(), but the intelfb_create() likes to be different and do the pinning itself. However, it aligns the buffer object incorrectly for pre-i965 chipsets causing a PGTBL_ERR when it is installed onto the output. Fixes: KMS error message while initializing modesetting - render error detected: EIR: 0x10 [i915] http://bugs.freedesktop.org/show_bug.cgi?id=22936 Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 2b0fe54cd92c..1318ac29e64a 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -148,7 +148,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, mutex_lock(&dev->struct_mutex); - ret = i915_gem_object_pin(fbo, PAGE_SIZE); + ret = i915_gem_object_pin(fbo, 64*1024); if (ret) { DRM_ERROR("failed to pin fb: %d\n", ret); goto out_unref; From a20bc629020fc785f75f6c7051795b5a12b0e932 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 7 Feb 2010 16:20:18 +0100 Subject: [PATCH 598/670] drm/i915: Update write_domains on active list after flush. commit 99fcb766a3a50466fe31d743260a3400c1aee855 upstream. Before changing the status of a buffer with a pending write we will await upon a new flush for that buffer. So we can take advantage of any flushes posted whilst the buffer is active and pending processing by the GPU, by clearing its write_domain and updating its last_rendering_seqno -- thus saving a potential flush in deep queues and improves flushing behaviour upon eviction for both GTT space and fences. In order to reduce the time spent searching the active list for matching write_domains, we move those to a separate list whose elements are the buffers belong to the active/flushing list with pending writes. Orignal patch by Chris Wilson , forward-ported by me. In addition to better performance, this also fixes a real bug. Before this changes, i915_gem_evict_everything didn't work as advertised. When the gpu was actually busy and processing request, the flush and subsequent wait would not move active and dirty buffers to the inactive list, but just to the flushing list. Which triggered the BUG_ON at the end of this function. With the more tight dirty buffer tracking, all currently busy and dirty buffers get moved to the inactive list by one i915_gem_flush operation. I've left the BUG_ON I've used to prove this in there. References: Bug 25911 - 2.10.0 causes kernel oops and system hangs http://bugs.freedesktop.org/show_bug.cgi?id=25911 Bug 26101 - [i915] xf86-video-intel 2.10.0 (and git) triggers kernel oops within seconds after login http://bugs.freedesktop.org/show_bug.cgi?id=26101 Signed-off-by: Daniel Vetter Signed-off-by: Chris Wilson Tested-by: Adam Lantos Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_drv.h | 11 +++++++++++ drivers/gpu/drm/i915/i915_gem.c | 23 +++++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 727724603c48..95c920fa486f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -466,6 +466,15 @@ typedef struct drm_i915_private { */ struct list_head flushing_list; + /** + * List of objects currently pending a GPU write flush. + * + * All elements on this list will belong to either the + * active_list or flushing_list, last_rendering_seqno can + * be used to differentiate between the two elements. + */ + struct list_head gpu_write_list; + /** * LRU list of objects which are not in the ringbuffer and * are ready to unbind, but are still in the GTT. @@ -558,6 +567,8 @@ struct drm_i915_gem_object { /** This object's place on the active/flushing/inactive lists */ struct list_head list; + /** This object's place on GPU write list */ + struct list_head gpu_write_list; /** This object's place on the fenced object LRU */ struct list_head fence_list; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8ad244ae7fa3..07345cacd0cc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1552,6 +1552,8 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) else list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); + BUG_ON(!list_empty(&obj_priv->gpu_write_list)); + obj_priv->last_rendering_seqno = 0; if (obj_priv->active) { obj_priv->active = 0; @@ -1622,7 +1624,8 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, struct drm_i915_gem_object *obj_priv, *next; list_for_each_entry_safe(obj_priv, next, - &dev_priv->mm.flushing_list, list) { + &dev_priv->mm.gpu_write_list, + gpu_write_list) { struct drm_gem_object *obj = obj_priv->obj; if ((obj->write_domain & flush_domains) == @@ -1630,6 +1633,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, uint32_t old_write_domain = obj->write_domain; obj->write_domain = 0; + list_del_init(&obj_priv->gpu_write_list); i915_gem_object_move_to_active(obj, seqno); trace_i915_gem_object_change_domain(obj, @@ -2073,8 +2077,8 @@ static int i915_gem_evict_everything(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - uint32_t seqno; int ret; + uint32_t seqno; bool lists_empty; spin_lock(&dev_priv->mm.active_list_lock); @@ -2096,6 +2100,8 @@ i915_gem_evict_everything(struct drm_device *dev) if (ret) return ret; + BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); + ret = i915_gem_evict_from_inactive_list(dev); if (ret) return ret; @@ -2690,7 +2696,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) old_write_domain = obj->write_domain; i915_gem_flush(dev, 0, obj->write_domain); seqno = i915_add_request(dev, NULL, obj->write_domain); - obj->write_domain = 0; + BUG_ON(obj->write_domain); i915_gem_object_move_to_active(obj, seqno); trace_i915_gem_object_change_domain(obj, @@ -3710,16 +3716,23 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, i915_gem_flush(dev, dev->invalidate_domains, dev->flush_domains); - if (dev->flush_domains) + if (dev->flush_domains & I915_GEM_GPU_DOMAINS) (void)i915_add_request(dev, file_priv, dev->flush_domains); } for (i = 0; i < args->buffer_count; i++) { struct drm_gem_object *obj = object_list[i]; + struct drm_i915_gem_object *obj_priv = obj->driver_private; uint32_t old_write_domain = obj->write_domain; obj->write_domain = obj->pending_write_domain; + if (obj->write_domain) + list_move_tail(&obj_priv->gpu_write_list, + &dev_priv->mm.gpu_write_list); + else + list_del_init(&obj_priv->gpu_write_list); + trace_i915_gem_object_change_domain(obj, obj->read_domains, old_write_domain); @@ -4112,6 +4125,7 @@ int i915_gem_init_object(struct drm_gem_object *obj) obj_priv->obj = obj; obj_priv->fence_reg = I915_FENCE_REG_NONE; INIT_LIST_HEAD(&obj_priv->list); + INIT_LIST_HEAD(&obj_priv->gpu_write_list); INIT_LIST_HEAD(&obj_priv->fence_list); obj_priv->madv = I915_MADV_WILLNEED; @@ -4563,6 +4577,7 @@ i915_gem_load(struct drm_device *dev) spin_lock_init(&dev_priv->mm.active_list_lock); INIT_LIST_HEAD(&dev_priv->mm.active_list); INIT_LIST_HEAD(&dev_priv->mm.flushing_list); + INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list); INIT_LIST_HEAD(&dev_priv->mm.inactive_list); INIT_LIST_HEAD(&dev_priv->mm.request_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); From bb0d31fbf221f50a44ba5d59dfcf54bbf128ac2b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 11 Feb 2010 19:20:48 +0000 Subject: [PATCH 599/670] regulator: Fix display of null constraints for regulators commit 973e9a2795b3b41d8408a0bb6f87b783c5efc88a upstream. If the regulator constraints are empty and there is no voltage reported then nothing will be added to the text displayed for the constraints, leading to random stack data being printed. This is unlikely to happen for practical regulators since most will at least report a voltage but should still be fixed. Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index efe568deda12..1836053c919d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -640,7 +640,7 @@ static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) static void print_constraints(struct regulator_dev *rdev) { struct regulation_constraints *constraints = rdev->constraints; - char buf[80]; + char buf[80] = ""; int count; if (rdev->desc->type == REGULATOR_VOLTAGE) { From 65798849d8abac3b382f6d3c2ef6a3722657cd19 Mon Sep 17 00:00:00 2001 From: Jody Bruchon Date: Sat, 6 Feb 2010 10:46:26 -0500 Subject: [PATCH 600/670] ALSA: hda-intel: Avoid divide by zero crash commit fed08d036f2aabd8d0c684439de37f8ebec2bbc2 upstream. On my AMD780V chipset, hda_intel.c can crash the kernel with a divide by zero for as-yet unknown reasons. A simple check for zero prevents it, though the problem that causes it remains. Since the workaround is harmless and won't affect anyone except victims of this bug, it should be safe; moreover, because this crash can be triggered by a user-mode application, there are denial of service implications on the systems affected by the bug without the patch. Signed-off-by: Jody Bruchon Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_intel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 03784da6cf5d..95c9b9717ba8 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1858,6 +1858,12 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) if (!bdl_pos_adj[chip->dev_index]) return 1; /* no delayed ack */ + if (azx_dev->period_bytes == 0) { + printk(KERN_WARNING + "hda-intel: Divide by zero was avoided " + "in azx_dev->period_bytes.\n"); + return 0; + } if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) return 0; /* NG - it's below the period boundary */ return 1; /* OK, it's fine */ From 344542028e96bd2c105ea5da4330af90db94e2b7 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Mon, 14 Dec 2009 11:44:15 +0100 Subject: [PATCH 601/670] CPUFREQ: Fix use after free of struct powernow_k8_data commit 557a701c16553b0b691dbb64ef30361115a80f64 upstream. Easy fix for a regression introduced in 2.6.31. On managed CPUs the cpufreq.c core will call driver->exit(cpu) on the managed cpus and powernow_k8 will free the core's data. Later driver->get(cpu) function might get called trying to read out the current freq of a managed cpu and the NULL pointer check does not work on the freed object -> better set it to NULL. ->get() is unsigned and must return 0 as invalid frequency. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14391 Signed-off-by: Thomas Renninger Tested-by: Michal Schmidt Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 3f12dabeab52..ab1cd30340f5 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -1351,6 +1351,7 @@ static int __devexit powernowk8_cpu_exit(struct cpufreq_policy *pol) kfree(data->powernow_table); kfree(data); + per_cpu(powernow_data, pol->cpu) = NULL; return 0; } @@ -1370,7 +1371,7 @@ static unsigned int powernowk8_get(unsigned int cpu) int err; if (!data) - return -EINVAL; + return 0; smp_call_function_single(cpu, query_values_on_cpu, &err, true); if (err) From e031c71282e8223cc8fc088e4c1bf86900ce9927 Mon Sep 17 00:00:00 2001 From: Jun'ichi Nomura Date: Fri, 29 Jan 2010 09:56:22 +0900 Subject: [PATCH 602/670] freeze_bdev: don't deactivate successfully frozen MS_RDONLY sb commit 4b06e5b9ad8abb20105b2b25e42c509ebe9b2d76 upstream. Thanks Thomas and Christoph for testing and review. I removed 'smp_wmb()' before up_write from the previous patch, since up_write() should have necessary ordering constraints. (I.e. the change of s_frozen is visible to others after up_write) I'm quite sure the change is harmless but if you are uncomfortable with Tested-by/Reviewed-by on the modified patch, please remove them. If MS_RDONLY, freeze_bdev should just up_write(s_umount) instead of deactivate_locked_super(). Also, keep sb->s_frozen consistent so that remount can check the frozen state. Otherwise a crash reported here can happen: http://lkml.org/lkml/2010/1/16/37 http://lkml.org/lkml/2010/1/28/53 This patch should be applied for 2.6.32 stable series, too. Reviewed-by: Christoph Hellwig Tested-by: Thomas Backlund Signed-off-by: Jun'ichi Nomura Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/block_dev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 8bed0557d88c..34e2d2033765 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -246,7 +246,8 @@ struct super_block *freeze_bdev(struct block_device *bdev) if (!sb) goto out; if (sb->s_flags & MS_RDONLY) { - deactivate_locked_super(sb); + sb->s_frozen = SB_FREEZE_TRANS; + up_write(&sb->s_umount); mutex_unlock(&bdev->bd_fsfreeze_mutex); return sb; } @@ -307,7 +308,7 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb) BUG_ON(sb->s_bdev != bdev); down_write(&sb->s_umount); if (sb->s_flags & MS_RDONLY) - goto out_deactivate; + goto out_unfrozen; if (sb->s_op->unfreeze_fs) { error = sb->s_op->unfreeze_fs(sb); @@ -321,11 +322,11 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb) } } +out_unfrozen: sb->s_frozen = SB_UNFROZEN; smp_wmb(); wake_up(&sb->s_wait_unfrozen); -out_deactivate: if (sb) deactivate_locked_super(sb); out_unlock: From 2b8fcd4ed0db58421d1600ff6e3b01dd68b3ef83 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Fri, 5 Feb 2010 13:14:04 +0100 Subject: [PATCH 603/670] cciss: Make cciss_seq_show handle holes in the h->drv[] array commit 531c2dc70d339c5dfa8c3eb628c3459dc6f3a075 upstream. It is possible (and expected) for there to be holes in the h->drv[] array, that is, some elements may be NULL pointers. cciss_seq_show needs to be made aware of this possibility to avoid an Oops. To reproduce the Oops which this fixes: 1) Create two "arrays" in the Array Configuratino Utility and several logical drives on each array. 2) cat /proc/driver/cciss/cciss* in an infinite loop 3) delete some of the logical drives in the first "array." Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/cciss.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 92b126394fa1..ca9c54870f29 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -339,6 +339,9 @@ static int cciss_seq_show(struct seq_file *seq, void *v) if (*pos > h->highest_lun) return 0; + if (drv == NULL) /* it's possible for h->drv[] to have holes. */ + return 0; + if (drv->heads == 0) return 0; From 27df9c09dd64b05f862d5a05cfb1b1e479a44f0c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 13 Jan 2010 13:33:12 -0700 Subject: [PATCH 604/670] ioat: fix infinite timeout checking in ioat2_quiesce commit 7e55a70c5b9a57c12f49c44b0847c9343d4f54e4 upstream. Fix typo in ioat2_quiesce. check 'tmo' is zero, not 'end'. Also applies to 2.6.32.3 Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/dma/ioat/dma_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 5f7a500e18d0..5cc37afe2bc1 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -249,7 +249,7 @@ int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo) if (is_ioat_active(status) || is_ioat_idle(status)) ioat_suspend(chan); while (is_ioat_active(status) || is_ioat_idle(status)) { - if (end && time_after(jiffies, end)) { + if (tmo && time_after(jiffies, end)) { err = -ETIMEDOUT; break; } From 3d87cb443857acc25dddd3696b6f7a459807d154 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 19 Nov 2009 17:16:37 +0100 Subject: [PATCH 605/670] resource: add helpers for fetching rlimits commit 3e10e716abf3c71bdb5d86b8f507f9e72236c9cd upstream. We want to be sure that compiler fetches the limit variable only once, so add helpers for fetching current and maximal resource limits which do that. Add them to sched.h (instead of resource.h) due to circular dependency sched.h->resource.h->task_struct Alternative would be to create a separate res_access.h or similar. Signed-off-by: Jiri Slaby Cc: James Morris Cc: Heiko Carstens Cc: Andrew Morton Cc: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- include/linux/sched.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index d3dce7db81d6..e48311e8c923 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2583,6 +2583,28 @@ static inline void mm_init_owner(struct mm_struct *mm, struct task_struct *p) #define TASK_STATE_TO_CHAR_STR "RSDTtZX" +static inline unsigned long task_rlimit(const struct task_struct *tsk, + unsigned int limit) +{ + return ACCESS_ONCE(tsk->signal->rlim[limit].rlim_cur); +} + +static inline unsigned long task_rlimit_max(const struct task_struct *tsk, + unsigned int limit) +{ + return ACCESS_ONCE(tsk->signal->rlim[limit].rlim_max); +} + +static inline unsigned long rlimit(unsigned int limit) +{ + return task_rlimit(current, limit); +} + +static inline unsigned long rlimit_max(unsigned int limit) +{ + return task_rlimit_max(current, limit); +} + #endif /* __KERNEL__ */ #endif From 35e2093d5d7b632c083af3578c05876375828314 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 10 Feb 2010 13:56:42 -0800 Subject: [PATCH 606/670] fs/exec.c: restrict initial stack space expansion to rlimit commit 803bf5ec259941936262d10ecc84511b76a20921 upstream. When reserving stack space for a new process, make sure we're not attempting to expand the stack by more than rlimit allows. This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba ("mm: variable length argument support") and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b ("exec: setup_arg_pages() fails to return errors"). This bug means that when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process. To test, do: 'ulimit -s 15; ls' before and after the patch is applied. Before it's applied, 'ls' should be killed. After the patch is applied, 'ls' should no longer be killed. A stack limit of 15KB since it's small enough to trigger 20*PAGE_SIZE. Also 15KB not a multiple of PAGE_SIZE, which is a trickier case to handle correctly with this code. 4K pages should be fine to test with. [kosaki.motohiro@jp.fujitsu.com: cleanup] [akpm@linux-foundation.org: cleanup cleanup] Signed-off-by: Michael Neuling Signed-off-by: KOSAKI Motohiro Cc: Americo Wang Cc: Anton Blanchard Cc: Oleg Nesterov Cc: James Morris Cc: Ingo Molnar Cc: Serge Hallyn Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/exec.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 7fa4efd50425..da36c206f0f1 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -572,6 +572,9 @@ int setup_arg_pages(struct linux_binprm *bprm, struct vm_area_struct *prev = NULL; unsigned long vm_flags; unsigned long stack_base; + unsigned long stack_size; + unsigned long stack_expand; + unsigned long rlim_stack; #ifdef CONFIG_STACK_GROWSUP /* Limit stack size to 1GB */ @@ -628,10 +631,24 @@ int setup_arg_pages(struct linux_binprm *bprm, goto out_unlock; } + stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE; + stack_size = vma->vm_end - vma->vm_start; + /* + * Align this down to a page boundary as expand_stack + * will align it up. + */ + rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK; + rlim_stack = min(rlim_stack, stack_size); #ifdef CONFIG_STACK_GROWSUP - stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE; + if (stack_size + stack_expand > rlim_stack) + stack_base = vma->vm_start + rlim_stack; + else + stack_base = vma->vm_end + stack_expand; #else - stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE; + if (stack_size + stack_expand > rlim_stack) + stack_base = vma->vm_end - rlim_stack; + else + stack_base = vma->vm_start - stack_expand; #endif ret = expand_stack(vma, stack_base); if (ret) From ea332d671c5f6802d85572c2af13b9a671d8ea88 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 5 Feb 2010 13:14:00 -0500 Subject: [PATCH 607/670] cifs: fix length calculation for converted unicode readdir names commit f12f98dba6ea1517cd7fbb912208893b9c014c15 upstream. cifs_from_ucs2 returns the length of the converted name, including the length of the NULL terminator. We don't want to include the NULL terminator in the dentry name length however since that'll throw off the hash calculation for the dentry cache. I believe that this is the root cause of several problems that have cropped up recently that seem to be papered over with the "noserverino" mount option. More confirmation of that would be good, but this is clearly a bug and it fixes at least one reproducible problem that was reported. This patch fixes at least this reproducer in this kernel.org bug: http://bugzilla.kernel.org/show_bug.cgi?id=15088#c12 Reported-by: Bjorn Tore Sund Acked-by: Dave Kleikamp Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/readdir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index f84062f9a985..f5618f8cc462 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -666,6 +666,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, min(len, max_len), nlt, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + pqst->len -= nls_nullsize(nlt); } else { pqst->name = filename; pqst->len = len; From 1f9382ec17cc4fa5344b871658345e569fba8af7 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 26 Jan 2010 15:41:34 -0500 Subject: [PATCH 608/670] NFS: Fix a reference leak in nfs_wb_cancel_page() commit c9edda7140ec6a22accf7f2f86da362dfbfd41fc upstream. Signed-off-by: Trond Myklebust Reviewed-by: Chuck Lever Signed-off-by: Greg Kroah-Hartman --- fs/nfs/write.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 6fc37762c495..cf6c06f66edc 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1542,6 +1542,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) break; } ret = nfs_wait_on_request(req); + nfs_release_request(req); if (ret < 0) goto out; } From 438b9c70b8800b0c12ec6bc784e00bbae24a75ca Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 26 Jan 2010 15:41:53 -0500 Subject: [PATCH 609/670] NFS: Try to commit unstable writes in nfs_release_page() commit 82be934a59ff891cac598727e5a862ba2b9d1fac upstream. If someone calls nfs_release_page(), we presumably already know that the page is clean, however it may be holding an unstable write. Signed-off-by: Trond Myklebust Reviewed-by: Chuck Lever Signed-off-by: Greg Kroah-Hartman --- fs/nfs/file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f5fdd39e037a..393d40fd7eb9 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -486,6 +486,8 @@ static int nfs_release_page(struct page *page, gfp_t gfp) { dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); + if (gfp & __GFP_WAIT) + nfs_wb_page(page->mapping->host, page); /* If PagePrivate() is set, then the page is not freeable */ if (PagePrivate(page)) return 0; From 1236ff906f9d3044cd24d22463c3c943ee92e3a2 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 26 Jan 2010 15:42:30 -0500 Subject: [PATCH 610/670] NFSv4: Don't allow posix locking against servers that don't support it commit 8e469ebd6dc32cbaf620e134d79f740bf0ebab79 upstream. Signed-off-by: Trond Myklebust Reviewed-by: Chuck Lever Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4_fs.h | 1 + fs/nfs/nfs4proc.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 6ea07a3c75d4..b4a6b1a586d6 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -141,6 +141,7 @@ enum { NFS_O_RDWR_STATE, /* OPEN stateid has read/write state */ NFS_STATE_RECLAIM_REBOOT, /* OPEN stateid server rebooted */ NFS_STATE_RECLAIM_NOGRACE, /* OPEN stateid needs to recover state */ + NFS_STATE_POSIX_LOCKS, /* Posix locks are supported */ }; struct nfs4_state { diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 741a562177fc..8dbee6291284 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1573,6 +1573,8 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in status = PTR_ERR(state); if (IS_ERR(state)) goto err_opendata_put; + if ((opendata->o_res.rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) != 0) + set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); nfs4_opendata_put(opendata); nfs4_put_state_owner(sp); *res = state; @@ -4060,8 +4062,11 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock { struct nfs_inode *nfsi = NFS_I(state->inode); unsigned char fl_flags = request->fl_flags; - int status; + int status = -ENOLCK; + if ((fl_flags & FL_POSIX) && + !test_bit(NFS_STATE_POSIX_LOCKS, &state->flags)) + goto out; /* Is this a delegated open? */ status = nfs4_set_lock_state(state, request); if (status != 0) From e7055c2366a5a5b507492905200d4327949b81ce Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 26 Jan 2010 15:42:21 -0500 Subject: [PATCH 611/670] NFSv4: Ensure that the NFSv4 locking can recover from stateid errors commit 2bee72a6aa1e6d0a4f5da56217f0d0bbbdd0d9a3 upstream. In most cases, we just want to mark the lock_stateid sequence id as being uninitialised. Signed-off-by: Trond Myklebust Reviewed-by: Chuck Lever Signed-off-by: Greg Kroah-Hartman --- fs/nfs/nfs4proc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8dbee6291284..6c200595099f 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3978,6 +3978,22 @@ static const struct rpc_call_ops nfs4_lock_ops = { .rpc_release = nfs4_lock_release, }; +static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) +{ + struct nfs_client *clp = server->nfs_client; + struct nfs4_state *state = lsp->ls_state; + + switch (error) { + case -NFS4ERR_ADMIN_REVOKED: + case -NFS4ERR_BAD_STATEID: + case -NFS4ERR_EXPIRED: + if (new_lock_owner != 0 || + (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) + nfs4_state_mark_reclaim_nograce(clp, state); + lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; + }; +} + static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int reclaim) { struct nfs4_lockdata *data; @@ -4013,6 +4029,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f ret = nfs4_wait_for_completion_rpc_task(task); if (ret == 0) { ret = data->rpc_status; + if (ret) + nfs4_handle_setlk_error(data->server, data->lsp, + data->arg.new_lock_owner, ret); } else data->cancelled = 1; rpc_put_task(task); From 04673da74dbd331040fa439bd72963a35f1b67cf Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 3 Feb 2010 08:27:22 -0500 Subject: [PATCH 612/670] NFS: Fix an Oops when truncating a file commit 9f557cd8073104b39528794d44e129331ded649f upstream. The VM/VFS does not allow mapping->a_ops->invalidatepage() to fail. Unfortunately, nfs_wb_page_cancel() may fail if a fatal signal occurs. Since the NFS code assumes that the page stays mapped for as long as the writeback is active, we can end up Oopsing (among other things). The only safe fix here is to convert nfs_wait_on_request(), so as to make it uninterruptible (as is already the case with wait_on_page_writeback()). Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/pagelist.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index e2975939126a..a12c45b65dd4 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -176,6 +176,12 @@ void nfs_release_request(struct nfs_page *req) kref_put(&req->wb_kref, nfs_free_request); } +static int nfs_wait_bit_uninterruptible(void *word) +{ + io_schedule(); + return 0; +} + /** * nfs_wait_on_request - Wait for a request to complete. * @req: request to wait upon. @@ -186,14 +192,9 @@ void nfs_release_request(struct nfs_page *req) int nfs_wait_on_request(struct nfs_page *req) { - int ret = 0; - - if (!test_bit(PG_BUSY, &req->wb_flags)) - goto out; - ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY, - nfs_wait_bit_killable, TASK_KILLABLE); -out: - return ret; + return wait_on_bit(&req->wb_flags, PG_BUSY, + nfs_wait_bit_uninterruptible, + TASK_UNINTERRUPTIBLE); } /** From 16e63ecd5d683fe18d91fcd1e6a7f63468f7d805 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 3 Feb 2010 08:27:35 -0500 Subject: [PATCH 613/670] NFS: Fix a umount race commit 387c149b54b4321cbc790dadbd4f8eedb5a90468 upstream. Ensure that we unregister the bdi before kill_anon_super() calls ida_remove() on our device name. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/super.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index e71f0fdff1da..4bf23f6f93cf 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -241,6 +241,7 @@ static int nfs_show_stats(struct seq_file *, struct vfsmount *); static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); +static void nfs_put_super(struct super_block *); static void nfs_kill_super(struct super_block *); static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); @@ -264,6 +265,7 @@ static const struct super_operations nfs_sops = { .alloc_inode = nfs_alloc_inode, .destroy_inode = nfs_destroy_inode, .write_inode = nfs_write_inode, + .put_super = nfs_put_super, .statfs = nfs_statfs, .clear_inode = nfs_clear_inode, .umount_begin = nfs_umount_begin, @@ -333,6 +335,7 @@ static const struct super_operations nfs4_sops = { .alloc_inode = nfs_alloc_inode, .destroy_inode = nfs_destroy_inode, .write_inode = nfs_write_inode, + .put_super = nfs_put_super, .statfs = nfs_statfs, .clear_inode = nfs4_clear_inode, .umount_begin = nfs_umount_begin, @@ -2195,6 +2198,17 @@ static int nfs_get_sb(struct file_system_type *fs_type, goto out; } +/* + * Ensure that we unregister the bdi before kill_anon_super + * releases the device name + */ +static void nfs_put_super(struct super_block *s) +{ + struct nfs_server *server = NFS_SB(s); + + bdi_unregister(&server->backing_dev_info); +} + /* * Destroy an NFS2/3 superblock */ @@ -2203,7 +2217,6 @@ static void nfs_kill_super(struct super_block *s) struct nfs_server *server = NFS_SB(s); kill_anon_super(s); - bdi_unregister(&server->backing_dev_info); nfs_fscache_release_super_cookie(s); nfs_free_server(server); } From 5ba0facdbeb73ead6fe04d6bc5947e2fb4f29320 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 8 Feb 2010 09:32:27 -0500 Subject: [PATCH 614/670] NFS: Fix a bug in nfs_fscache_release_page() commit 2c1740098c708b465e87637b237feb2fd98f129a upstream. Not having an fscache cookie is perfectly valid if the user didn't mount with the fscache option. This patch fixes http://bugzilla.kernel.org/show_bug.cgi?id=15234 Signed-off-by: Trond Myklebust Acked-by: David Howells Signed-off-by: Greg Kroah-Hartman --- fs/nfs/fscache.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index fa588006588d..237874f1af23 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c @@ -354,12 +354,11 @@ void nfs_fscache_reset_inode_cookie(struct inode *inode) */ int nfs_fscache_release_page(struct page *page, gfp_t gfp) { - struct nfs_inode *nfsi = NFS_I(page->mapping->host); - struct fscache_cookie *cookie = nfsi->fscache; - - BUG_ON(!cookie); - if (PageFsCache(page)) { + struct nfs_inode *nfsi = NFS_I(page->mapping->host); + struct fscache_cookie *cookie = nfsi->fscache; + + BUG_ON(!cookie); dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n", cookie, page, nfsi); From 892faa5a39f6236bccbe6f48a5f736a8aec9b278 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 8 Feb 2010 09:32:40 -0500 Subject: [PATCH 615/670] NFS: Fix the mapping of the NFSERR_SERVERFAULT error commit fdcb45777a3d1689c5541e1f85ee3ebbd197d2c1 upstream. It was recently pointed out that the NFSERR_SERVERFAULT error, which is designed to inform the user of a serious internal error on the server, was being mapped to an error value that is internal to the kernel. This patch maps it to the error EREMOTEIO, which is exported to userland through errno.h. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman --- fs/nfs/mount_clnt.c | 2 +- fs/nfs/nfs2xdr.c | 2 +- fs/nfs/nfs4xdr.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 0adefc40cc89..59047f8d7d72 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -120,7 +120,7 @@ static struct { { .status = MNT3ERR_INVAL, .errno = -EINVAL, }, { .status = MNT3ERR_NAMETOOLONG, .errno = -ENAMETOOLONG, }, { .status = MNT3ERR_NOTSUPP, .errno = -ENOTSUPP, }, - { .status = MNT3ERR_SERVERFAULT, .errno = -ESERVERFAULT, }, + { .status = MNT3ERR_SERVERFAULT, .errno = -EREMOTEIO, }, }; struct mountres { diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 5e078b222b4e..7bc2da8efd4a 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -699,7 +699,7 @@ static struct { { NFSERR_BAD_COOKIE, -EBADCOOKIE }, { NFSERR_NOTSUPP, -ENOTSUPP }, { NFSERR_TOOSMALL, -ETOOSMALL }, - { NFSERR_SERVERFAULT, -ESERVERFAULT }, + { NFSERR_SERVERFAULT, -EREMOTEIO }, { NFSERR_BADTYPE, -EBADTYPE }, { NFSERR_JUKEBOX, -EJUKEBOX }, { -1, -EIO } diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 20b4e30e6c82..a4cd1b79b71d 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -4554,7 +4554,7 @@ static int decode_sequence(struct xdr_stream *xdr, * If the server returns different values for sessionID, slotID or * sequence number, the server is looney tunes. */ - status = -ESERVERFAULT; + status = -EREMOTEIO; if (memcmp(id.data, res->sr_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { @@ -5678,7 +5678,7 @@ static struct { { NFS4ERR_BAD_COOKIE, -EBADCOOKIE }, { NFS4ERR_NOTSUPP, -ENOTSUPP }, { NFS4ERR_TOOSMALL, -ETOOSMALL }, - { NFS4ERR_SERVERFAULT, -ESERVERFAULT }, + { NFS4ERR_SERVERFAULT, -EREMOTEIO }, { NFS4ERR_BADTYPE, -EBADTYPE }, { NFS4ERR_LOCKED, -EAGAIN }, { NFS4ERR_SYMLINK, -ELOOP }, @@ -5705,7 +5705,7 @@ nfs4_stat_to_errno(int stat) } if (stat <= 10000 || stat > 10100) { /* The server is looney tunes. */ - return -ESERVERFAULT; + return -EREMOTEIO; } /* If we cannot translate the error, the recovery routines should * handle it. From 113819bc44213c5b931517f86a1c9c93c22e2f20 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 9 Feb 2010 12:31:47 +1100 Subject: [PATCH 616/670] md: fix 'degraded' calculation when starting a reshape. commit 9eb07c259207d048e3ee8be2a77b2a4680b1edd4 upstream. This code was written long ago when it was not possible to reshape a degraded array. Now it is so the current level of degraded-ness needs to be taken in to account. Also newly addded devices should only reduce degradedness if they are deemed to be in-sync. In particular, if you convert a RAID5 to a RAID6, and increase the number of devices at the same time, then the 5->6 conversion will make the array degraded so the current code will produce a wrong value for 'degraded' - "-1" to be precise. If the reshape runs to completion end_reshape will calculate a correct new value for 'degraded', but if a device fails during the reshape an incorrect decision might be made based on the incorrect value of "degraded". This patch is suitable for 2.6.32-stable and if they are still open, 2.6.31-stable and 2.6.30-stable as well. Reported-by: Michael Evans Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- drivers/md/raid5.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index d29215d966da..431b9b26ca5d 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5432,11 +5432,11 @@ static int raid5_start_reshape(mddev_t *mddev) !test_bit(Faulty, &rdev->flags)) { if (raid5_add_disk(mddev, rdev) == 0) { char nm[20]; - if (rdev->raid_disk >= conf->previous_raid_disks) + if (rdev->raid_disk >= conf->previous_raid_disks) { set_bit(In_sync, &rdev->flags); - else + added_devices++; + } else rdev->recovery_offset = 0; - added_devices++; sprintf(nm, "rd%d", rdev->raid_disk); if (sysfs_create_link(&mddev->kobj, &rdev->kobj, nm)) @@ -5448,9 +5448,12 @@ static int raid5_start_reshape(mddev_t *mddev) break; } + /* When a reshape changes the number of devices, ->degraded + * is measured against the large of the pre and post number of + * devices.*/ if (mddev->delta_disks > 0) { spin_lock_irqsave(&conf->device_lock, flags); - mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) + mddev->degraded += (conf->raid_disks - conf->previous_raid_disks) - added_devices; spin_unlock_irqrestore(&conf->device_lock, flags); } From 134bb65d8d9fa4e8bf3a7637e983e8d01e063544 Mon Sep 17 00:00:00 2001 From: Francesco Lavra Date: Sun, 7 Feb 2010 09:49:58 -0300 Subject: [PATCH 617/670] V4L/DVB: dvb-core: fix initialization of feeds list in demux filter commit 691c9ae099b9bcb5c27125af00a4a90120977458 upstream. A DVB demultiplexer device can be used to set up either a PES filter or a section filter. In the former case, the ts field of the feed union of struct dmxdev_filter is used, in the latter case the sec field of the same union is used. The ts field is a struct list_head, and is currently initialized in the open() method of the demux device. When for a given demuxer a section filter is set up, the sec field is played with, thus if a PES filter needs to be set up after that the ts field will be corrupted, causing a kernel oops. This fix moves the list head initialization to dvb_dmxdev_pes_filter_set(), so that the ts field is properly initialized every time a PES filter is set up. Signed-off-by: Francesco Lavra Reviewed-by: Andy Walls Tested-by: hermann pitton Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/dvb-core/dmxdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index c37790ad92d0..9ddc57909d49 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -761,7 +761,6 @@ static int dvb_demux_open(struct inode *inode, struct file *file) dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); dmxdevfilter->type = DMXDEV_TYPE_NONE; dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); - INIT_LIST_HEAD(&dmxdevfilter->feed.ts); init_timer(&dmxdevfilter->timer); dvbdev->users++; @@ -887,6 +886,7 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, dmxdevfilter->type = DMXDEV_TYPE_PES; memcpy(&dmxdevfilter->params, params, sizeof(struct dmx_pes_filter_params)); + INIT_LIST_HEAD(&dmxdevfilter->feed.ts); dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); From 1c63c20663a84b03a2dc47d1c1998f1883081162 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 27 Jan 2010 19:13:40 +0800 Subject: [PATCH 618/670] Export the symbol of getboottime and mmonotonic_to_bootbased commit c93d89f3dbf0202bf19c07960ca8602b48c2f9a0 upstream. Export getboottime and monotonic_to_bootbased in order to let them could be used by following patch. Signed-off-by: Jason Wang Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- kernel/time/timekeeping.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 66d090e3c70a..8b709dee8e34 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -845,6 +845,7 @@ void getboottime(struct timespec *ts) set_normalized_timespec(ts, -boottime.tv_sec, -boottime.tv_nsec); } +EXPORT_SYMBOL_GPL(getboottime); /** * monotonic_to_bootbased - Convert the monotonic time to boot based. @@ -854,6 +855,7 @@ void monotonic_to_bootbased(struct timespec *ts) { *ts = timespec_add_safe(*ts, total_sleep_time); } +EXPORT_SYMBOL_GPL(monotonic_to_bootbased); unsigned long get_seconds(void) { From aa1dcdd6eb7f457dee130987d5d5229e5a67184c Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 27 Jan 2010 19:13:49 +0800 Subject: [PATCH 619/670] kvmclock: count total_sleep_time when updating guest clock commit 923de3cf5bf12049628019010e36623fca5ef6d1 upstream. Current kvm wallclock does not consider the total_sleep_time which could cause wrong wallclock in guest after host suspend/resume. This patch solve this issue by counting total_sleep_time to get the correct host boot time. Signed-off-by: Jason Wang Acked-by: Glauber Costa Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 145741c979bf..e78d9907e0ee 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -583,7 +583,7 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock) { static int version; struct pvclock_wall_clock wc; - struct timespec now, sys, boot; + struct timespec boot; if (!wall_clock) return; @@ -598,9 +598,7 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock) * wall clock specified here. guest system time equals host * system time for us, thus we must fill in host boot time here. */ - now = current_kernel_time(); - ktime_get_ts(&sys); - boot = ns_to_timespec(timespec_to_ns(&now) - timespec_to_ns(&sys)); + getboottime(&boot); wc.sec = boot.tv_sec; wc.nsec = boot.tv_nsec; @@ -675,6 +673,7 @@ static void kvm_write_guest_time(struct kvm_vcpu *v) local_irq_save(flags); kvm_get_msr(v, MSR_IA32_TSC, &vcpu->hv_clock.tsc_timestamp); ktime_get_ts(&ts); + monotonic_to_bootbased(&ts); local_irq_restore(flags); /* With all the info we got, fill in the values */ From d632dfd88b02f1f89cbb9ec2d595580d1eba03bf Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Fri, 29 Jan 2010 17:28:41 -0200 Subject: [PATCH 620/670] KVM: PIT: control word is write-only commit ee73f656a604d5aa9df86a97102e4e462dd79924 upstream. PIT control word (address 0x43) is write-only, reads are undefined. Signed-off-by: Marcelo Tosatti Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/i8254.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 144e7f60b5e2..88ad1627a89d 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c @@ -465,6 +465,9 @@ static int pit_ioport_read(struct kvm_io_device *this, return -EOPNOTSUPP; addr &= KVM_PIT_CHANNEL_MASK; + if (addr == 3) + return 0; + s = &pit_state->channels[addr]; mutex_lock(&pit_state->lock); From 00510c8f39d7b3501cc7ec79b677186ffbc7ca7e Mon Sep 17 00:00:00 2001 From: Marcel Selhorst Date: Wed, 10 Feb 2010 13:56:32 -0800 Subject: [PATCH 621/670] tpm_infineon: fix suspend/resume handler for pnp_driver commit 93716b9470fbfd9efdc7d0f2445cb34635de3f6d upstream. When suspending, tpm_infineon calls the generic suspend function of the TPM framework. However, the TPM framework does not return and the system hangs upon suspend. When sending the necessary command "TPM_SaveState" directly within the driver, suspending and resuming works fine. Signed-off-by: Marcel Selhorst Cc: OGAWA Hirofumi Cc: Debora Velarde Cc: Rajiv Andrade Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_infineon.c | 79 ++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index ecba4942fc8e..f58440791e65 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -39,12 +39,12 @@ struct tpm_inf_dev { int iotype; - void __iomem *mem_base; /* MMIO ioremap'd addr */ - unsigned long map_base; /* phys MMIO base */ - unsigned long map_size; /* MMIO region size */ - unsigned int index_off; /* index register offset */ + void __iomem *mem_base; /* MMIO ioremap'd addr */ + unsigned long map_base; /* phys MMIO base */ + unsigned long map_size; /* MMIO region size */ + unsigned int index_off; /* index register offset */ - unsigned int data_regs; /* Data registers */ + unsigned int data_regs; /* Data registers */ unsigned int data_size; unsigned int config_port; /* IO Port config index reg */ @@ -406,14 +406,14 @@ static const struct tpm_vendor_specific tpm_inf = { .miscdev = {.fops = &inf_ops,}, }; -static const struct pnp_device_id tpm_pnp_tbl[] = { +static const struct pnp_device_id tpm_inf_pnp_tbl[] = { /* Infineon TPMs */ {"IFX0101", 0}, {"IFX0102", 0}, {"", 0} }; -MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); +MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl); static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) @@ -430,7 +430,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { - tpm_dev.iotype = TPM_INF_IO_PORT; + tpm_dev.iotype = TPM_INF_IO_PORT; tpm_dev.config_port = pnp_port_start(dev, 0); tpm_dev.config_size = pnp_port_len(dev, 0); @@ -459,9 +459,9 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, goto err_last; } } else if (pnp_mem_valid(dev, 0) && - !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) { + !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) { - tpm_dev.iotype = TPM_INF_IO_MEM; + tpm_dev.iotype = TPM_INF_IO_MEM; tpm_dev.map_base = pnp_mem_start(dev, 0); tpm_dev.map_size = pnp_mem_len(dev, 0); @@ -563,11 +563,11 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, "product id 0x%02x%02x" "%s\n", tpm_dev.iotype == TPM_INF_IO_PORT ? - tpm_dev.config_port : - tpm_dev.map_base + tpm_dev.index_off, + tpm_dev.config_port : + tpm_dev.map_base + tpm_dev.index_off, tpm_dev.iotype == TPM_INF_IO_PORT ? - tpm_dev.data_regs : - tpm_dev.map_base + tpm_dev.data_regs, + tpm_dev.data_regs : + tpm_dev.map_base + tpm_dev.data_regs, version[0], version[1], vendorid[0], vendorid[1], productid[0], productid[1], chipname); @@ -607,20 +607,55 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) iounmap(tpm_dev.mem_base); release_mem_region(tpm_dev.map_base, tpm_dev.map_size); } + tpm_dev_vendor_release(chip); tpm_remove_hardware(chip->dev); } } +static int tpm_inf_pnp_suspend(struct pnp_dev *dev, pm_message_t pm_state) +{ + struct tpm_chip *chip = pnp_get_drvdata(dev); + int rc; + if (chip) { + u8 savestate[] = { + 0, 193, /* TPM_TAG_RQU_COMMAND */ + 0, 0, 0, 10, /* blob length (in bytes) */ + 0, 0, 0, 152 /* TPM_ORD_SaveState */ + }; + dev_info(&dev->dev, "saving TPM state\n"); + rc = tpm_inf_send(chip, savestate, sizeof(savestate)); + if (rc < 0) { + dev_err(&dev->dev, "error while saving TPM state\n"); + return rc; + } + } + return 0; +} + +static int tpm_inf_pnp_resume(struct pnp_dev *dev) +{ + /* Re-configure TPM after suspending */ + tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); + tpm_config_out(IOLIMH, TPM_INF_ADDR); + tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA); + tpm_config_out(IOLIML, TPM_INF_ADDR); + tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA); + /* activate register */ + tpm_config_out(TPM_DAR, TPM_INF_ADDR); + tpm_config_out(0x01, TPM_INF_DATA); + tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); + /* disable RESET, LP and IRQC */ + tpm_data_out(RESET_LP_IRQC_DISABLE, CMD); + return tpm_pm_resume(&dev->dev); +} + static struct pnp_driver tpm_inf_pnp_driver = { .name = "tpm_inf_pnp", - .driver = { - .owner = THIS_MODULE, - .suspend = tpm_pm_suspend, - .resume = tpm_pm_resume, - }, - .id_table = tpm_pnp_tbl, + .id_table = tpm_inf_pnp_tbl, .probe = tpm_inf_pnp_probe, - .remove = __devexit_p(tpm_inf_pnp_remove), + .suspend = tpm_inf_pnp_suspend, + .resume = tpm_inf_pnp_resume, + .remove = __devexit_p(tpm_inf_pnp_remove) }; static int __init init_inf(void) @@ -638,5 +673,5 @@ module_exit(cleanup_inf); MODULE_AUTHOR("Marcel Selhorst "); MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); -MODULE_VERSION("1.9"); +MODULE_VERSION("1.9.2"); MODULE_LICENSE("GPL"); From dc5b9893d10ba7132098e7ad991103430227724b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 11 Feb 2010 17:15:57 +0100 Subject: [PATCH 622/670] amd64_edac: Do not falsely trigger kerneloops commit cab4d27764d5a8654212b3e96eb0ae793aec5b94 upstream. An unfortunate "WARNING" in the message amd64_edac dumps when the system doesn't support DRAM ECC or ECC checking is not enabled in the BIOS used to trigger kerneloops which qualified the message as an OOPS thus misleading the users. See, e.g. https://bugs.launchpad.net/ubuntu/+source/linux/+bug/422536 http://bugzilla.kernel.org/show_bug.cgi?id=15238 Downgrade the message level to KERN_NOTICE and fix the formulation. Signed-off-by: Borislav Petkov Acked-by: Doug Thompson Signed-off-by: Greg Kroah-Hartman --- drivers/edac/amd64_edac.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index a0bcfba13d17..01bc8e232456 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2801,10 +2801,11 @@ static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) * the memory system completely. A command line option allows to force-enable * hardware ECC later in amd64_enable_ecc_error_reporting(). */ -static const char *ecc_warning = - "WARNING: ECC is disabled by BIOS. Module will NOT be loaded.\n" - " Either Enable ECC in the BIOS, or set 'ecc_enable_override'.\n" - " Also, use of the override can cause unknown side effects.\n"; +static const char *ecc_msg = + "ECC disabled in the BIOS or no ECC capability, module will not load.\n" + " Either enable ECC checking or force module loading by setting " + "'ecc_enable_override'.\n" + " (Note that use of the override may cause unknown side effects.)\n"; static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) { @@ -2819,7 +2820,7 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) ecc_enabled = !!(value & K8_NBCFG_ECC_ENABLE); if (!ecc_enabled) - amd64_printk(KERN_WARNING, "This node reports that Memory ECC " + amd64_printk(KERN_NOTICE, "This node reports that Memory ECC " "is currently disabled, set F3x%x[22] (%s).\n", K8_NBCFG, pci_name(pvt->misc_f3_ctl)); else @@ -2827,13 +2828,13 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) nb_mce_en = amd64_nb_mce_bank_enabled_on_node(pvt->mc_node_id); if (!nb_mce_en) - amd64_printk(KERN_WARNING, "NB MCE bank disabled, set MSR " + amd64_printk(KERN_NOTICE, "NB MCE bank disabled, set MSR " "0x%08x[4] on node %d to enable.\n", MSR_IA32_MCG_CTL, pvt->mc_node_id); if (!ecc_enabled || !nb_mce_en) { if (!ecc_enable_override) { - amd64_printk(KERN_WARNING, "%s", ecc_warning); + amd64_printk(KERN_NOTICE, "%s", ecc_msg); return -ENODEV; } ecc_enable_override = 0; From de2545859df3c04462ef39bf8056e587a1d2fa17 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 8 Feb 2010 11:16:26 -0800 Subject: [PATCH 623/670] netfilter: nf_conntrack: fix memory corruption with multiple namespaces commit 9edd7ca0a3e3999c260642c92fa008892d82ca6e upstream. As discovered by Jon Masters , the "untracked" conntrack, which is located in the data section, might be accidentally freed when a new namespace is instantiated while the untracked conntrack is attached to a skb because the reference count it re-initialized. The best fix would be to use a seperate untracked conntrack per namespace since it includes a namespace pointer. Unfortunately this is not possible without larger changes since the namespace is not easily available everywhere we need it. For now move the untracked conntrack initialization to the init_net setup function to make sure the reference count is not re-initialized and handle cleanup in the init_net cleanup function to make sure namespaces can exit properly while the untracked conntrack is in use in other namespaces. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_core.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index b9168c1864ca..4489676ab650 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1107,6 +1107,10 @@ static void nf_ct_release_dying_list(struct net *net) static void nf_conntrack_cleanup_init_net(void) { + /* wait until all references to nf_conntrack_untracked are dropped */ + while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1) + schedule(); + nf_conntrack_helper_fini(); nf_conntrack_proto_fini(); kmem_cache_destroy(nf_conntrack_cachep); @@ -1121,9 +1125,6 @@ static void nf_conntrack_cleanup_net(struct net *net) schedule(); goto i_see_dead_people; } - /* wait until all references to nf_conntrack_untracked are dropped */ - while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1) - schedule(); nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc, nf_conntrack_htable_size); @@ -1282,6 +1283,14 @@ static int nf_conntrack_init_init_net(void) if (ret < 0) goto err_helper; + /* Set up fake conntrack: to never be deleted, not in any hashes */ +#ifdef CONFIG_NET_NS + nf_conntrack_untracked.ct_net = &init_net; +#endif + atomic_set(&nf_conntrack_untracked.ct_general.use, 1); + /* - and look it like as a confirmed connection */ + set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status); + return 0; err_helper: @@ -1327,15 +1336,6 @@ static int nf_conntrack_init_net(struct net *net) if (ret < 0) goto err_ecache; - /* Set up fake conntrack: - - to never be deleted, not in any hashes */ -#ifdef CONFIG_NET_NS - nf_conntrack_untracked.ct_net = &init_net; -#endif - atomic_set(&nf_conntrack_untracked.ct_general.use, 1); - /* - and look it like as a confirmed connection */ - set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status); - return 0; err_ecache: From 747edef00c9b2147ca0b3d5bc33e9291a9a6d86e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 8 Feb 2010 11:16:56 -0800 Subject: [PATCH 624/670] netfilter: nf_conntrack: per netns nf_conntrack_cachep commit 5b3501faa8741d50617ce4191c20061c6ef36cb3 upstream. nf_conntrack_cachep is currently shared by all netns instances, but because of SLAB_DESTROY_BY_RCU special semantics, this is wrong. If we use a shared slab cache, one object can instantly flight between one hash table (netns ONE) to another one (netns TWO), and concurrent reader (doing a lookup in netns ONE, 'finding' an object of netns TWO) can be fooled without notice, because no RCU grace period has to be observed between object freeing and its reuse. We dont have this problem with UDP/TCP slab caches because TCP/UDP hashtables are global to the machine (and each object has a pointer to its netns). If we use per netns conntrack hash tables, we also *must* use per netns conntrack slab caches, to guarantee an object can not escape from one namespace to another one. Signed-off-by: Eric Dumazet [Patrick: added unique slab name allocation] Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- include/net/netns/conntrack.h | 2 ++ net/netfilter/nf_conntrack_core.c | 39 ++++++++++++++++++------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index ba1ba0c5efd1..aed23b6c8478 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -11,6 +11,7 @@ struct nf_conntrack_ecache; struct netns_ct { atomic_t count; unsigned int expect_count; + struct kmem_cache *nf_conntrack_cachep; struct hlist_nulls_head *hash; struct hlist_head *expect_hash; struct hlist_nulls_head unconfirmed; @@ -28,5 +29,6 @@ struct netns_ct { #endif int hash_vmalloc; int expect_vmalloc; + char *slabname; }; #endif diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 4489676ab650..1e1df209d6b3 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -63,8 +63,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_max); struct nf_conn nf_conntrack_untracked __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_untracked); -static struct kmem_cache *nf_conntrack_cachep __read_mostly; - static int nf_conntrack_hash_rnd_initted; static unsigned int nf_conntrack_hash_rnd; @@ -566,7 +564,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, * Do not use kmem_cache_zalloc(), as this cache uses * SLAB_DESTROY_BY_RCU. */ - ct = kmem_cache_alloc(nf_conntrack_cachep, gfp); + ct = kmem_cache_alloc(net->ct.nf_conntrack_cachep, gfp); if (ct == NULL) { pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); atomic_dec(&net->ct.count); @@ -605,7 +603,7 @@ void nf_conntrack_free(struct nf_conn *ct) nf_ct_ext_destroy(ct); atomic_dec(&net->ct.count); nf_ct_ext_free(ct); - kmem_cache_free(nf_conntrack_cachep, ct); + kmem_cache_free(net->ct.nf_conntrack_cachep, ct); } EXPORT_SYMBOL_GPL(nf_conntrack_free); @@ -1113,7 +1111,6 @@ static void nf_conntrack_cleanup_init_net(void) nf_conntrack_helper_fini(); nf_conntrack_proto_fini(); - kmem_cache_destroy(nf_conntrack_cachep); } static void nf_conntrack_cleanup_net(struct net *net) @@ -1131,6 +1128,8 @@ static void nf_conntrack_cleanup_net(struct net *net) nf_conntrack_ecache_fini(net); nf_conntrack_acct_fini(net); nf_conntrack_expect_fini(net); + kmem_cache_destroy(net->ct.nf_conntrack_cachep); + kfree(net->ct.slabname); free_percpu(net->ct.stat); } @@ -1266,15 +1265,6 @@ static int nf_conntrack_init_init_net(void) NF_CONNTRACK_VERSION, nf_conntrack_htable_size, nf_conntrack_max); - nf_conntrack_cachep = kmem_cache_create("nf_conntrack", - sizeof(struct nf_conn), - 0, SLAB_DESTROY_BY_RCU, NULL); - if (!nf_conntrack_cachep) { - printk(KERN_ERR "Unable to create nf_conn slab cache\n"); - ret = -ENOMEM; - goto err_cache; - } - ret = nf_conntrack_proto_init(); if (ret < 0) goto err_proto; @@ -1296,8 +1286,6 @@ static int nf_conntrack_init_init_net(void) err_helper: nf_conntrack_proto_fini(); err_proto: - kmem_cache_destroy(nf_conntrack_cachep); -err_cache: return ret; } @@ -1319,6 +1307,21 @@ static int nf_conntrack_init_net(struct net *net) ret = -ENOMEM; goto err_stat; } + + net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%p", net); + if (!net->ct.slabname) { + ret = -ENOMEM; + goto err_slabname; + } + + net->ct.nf_conntrack_cachep = kmem_cache_create(net->ct.slabname, + sizeof(struct nf_conn), 0, + SLAB_DESTROY_BY_RCU, NULL); + if (!net->ct.nf_conntrack_cachep) { + printk(KERN_ERR "Unable to create nf_conn slab cache\n"); + ret = -ENOMEM; + goto err_cache; + } net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, &net->ct.hash_vmalloc, 1); if (!net->ct.hash) { @@ -1346,6 +1349,10 @@ static int nf_conntrack_init_net(struct net *net) nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc, nf_conntrack_htable_size); err_hash: + kmem_cache_destroy(net->ct.nf_conntrack_cachep); +err_cache: + kfree(net->ct.slabname); +err_slabname: free_percpu(net->ct.stat); err_stat: return ret; From 51d3a347944f76bc2f304e0622d61b9b39fec585 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 8 Feb 2010 11:17:22 -0800 Subject: [PATCH 625/670] netfilter: nf_conntrack: restrict runtime expect hashsize modifications commit 13ccdfc2af03e09e60791f7d4bc4ccf53398af7c upstream. Expectation hashtable size was simply glued to a variable with no code to rehash expectations, so it was a bug to allow writing to it. Make "expect_hashsize" readonly. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_conntrack_expect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 2032dfe25ca8..1b8ed66aa0ba 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -569,7 +569,7 @@ static void exp_proc_remove(struct net *net) #endif /* CONFIG_PROC_FS */ } -module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600); +module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400); int nf_conntrack_expect_init(struct net *net) { From d619798aab2394997e0a4b9d2cb362306f221c97 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 8 Feb 2010 11:17:43 -0800 Subject: [PATCH 626/670] netfilter: xtables: compat out of scope fix commit 14c7dbe043d01a83a30633ab6b109ba2ac61d9f7 upstream. As per C99 6.2.4(2) when temporary table data goes out of scope, the behaviour is undefined: if (compat) { struct foo tmp; ... private = &tmp; } [dereference private] Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy Signed-off-by: Greg Kroah-Hartman --- net/ipv4/netfilter/arp_tables.c | 4 ++-- net/ipv4/netfilter/ip_tables.c | 4 ++-- net/ipv6/netfilter/ip6_tables.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 27774c99d888..98442f3063e8 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -925,10 +925,10 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) if (t && !IS_ERR(t)) { struct arpt_getinfo info; const struct xt_table_info *private = t->private; - #ifdef CONFIG_COMPAT + struct xt_table_info tmp; + if (compat) { - struct xt_table_info tmp; ret = compat_table_info(private, &tmp); xt_compat_flush_offsets(NFPROTO_ARP); private = &tmp; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index cde755d5eeab..62aff317a213 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1132,10 +1132,10 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) if (t && !IS_ERR(t)) { struct ipt_getinfo info; const struct xt_table_info *private = t->private; - #ifdef CONFIG_COMPAT + struct xt_table_info tmp; + if (compat) { - struct xt_table_info tmp; ret = compat_table_info(private, &tmp); xt_compat_flush_offsets(AF_INET); private = &tmp; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index cc9f8ef303fd..1de56fdf6f30 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1164,10 +1164,10 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) if (t && !IS_ERR(t)) { struct ip6t_getinfo info; const struct xt_table_info *private = t->private; - #ifdef CONFIG_COMPAT + struct xt_table_info tmp; + if (compat) { - struct xt_table_info tmp; ret = compat_table_info(private, &tmp); xt_compat_flush_offsets(AF_INET6); private = &tmp; From 242a71829e57a4962e43f89cf50d5fa99ff8a3e5 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 8 Feb 2010 11:18:07 -0800 Subject: [PATCH 627/670] netfilter: nf_conntrack: fix hash resizing with namespaces commit d696c7bdaa55e2208e56c6f98e6bc1599f34286d upstream. As noticed by Jon Masters , the conntrack hash size is global and not per namespace, but modifiable at runtime through /sys/module/nf_conntrack/hashsize. Changing the hash size will only resize the hash in the current namespace however, so other namespaces will use an invalid hash size. This can cause crashes when enlarging the hashsize, or false negative lookups when shrinking it. Move the hash size into the per-namespace data and only use the global hash size to initialize the per-namespace value when instanciating a new namespace. Additionally restrict hash resizing to init_net for now as other namespaces are not handled currently. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/netns/conntrack.h | 1 + include/net/netns/ipv4.h | 1 + .../netfilter/nf_conntrack_l3proto_ipv4.c | 2 +- .../nf_conntrack_l3proto_ipv4_compat.c | 4 +- net/ipv4/netfilter/nf_nat_core.c | 22 ++++---- net/netfilter/nf_conntrack_core.c | 54 ++++++++++--------- net/netfilter/nf_conntrack_expect.c | 2 +- net/netfilter/nf_conntrack_helper.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 2 +- net/netfilter/nf_conntrack_standalone.c | 7 +-- 10 files changed, 50 insertions(+), 47 deletions(-) diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index aed23b6c8478..63d449807d9b 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -11,6 +11,7 @@ struct nf_conntrack_ecache; struct netns_ct { atomic_t count; unsigned int expect_count; + unsigned int htable_size; struct kmem_cache *nf_conntrack_cachep; struct hlist_nulls_head *hash; struct hlist_head *expect_hash; diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 2eb3814d6258..9a4b8b714079 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -40,6 +40,7 @@ struct netns_ipv4 { struct xt_table *iptable_security; struct xt_table *nat_table; struct hlist_head *nat_bysource; + unsigned int nat_htable_size; int nat_vmalloced; #endif diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index aa95bb82ee6c..1032a152d5e6 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -213,7 +213,7 @@ static ctl_table ip_ct_sysctl_table[] = { { .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS, .procname = "ip_conntrack_buckets", - .data = &nf_conntrack_htable_size, + .data = &init_net.ct.htable_size, .maxlen = sizeof(unsigned int), .mode = 0444, .proc_handler = proc_dointvec, diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 8668a3defda6..2fb7b76da94f 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c @@ -32,7 +32,7 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq) struct hlist_nulls_node *n; for (st->bucket = 0; - st->bucket < nf_conntrack_htable_size; + st->bucket < net->ct.htable_size; st->bucket++) { n = rcu_dereference(net->ct.hash[st->bucket].first); if (!is_a_nulls(n)) @@ -50,7 +50,7 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq, head = rcu_dereference(head->next); while (is_a_nulls(head)) { if (likely(get_nulls_value(head) == st->bucket)) { - if (++st->bucket >= nf_conntrack_htable_size) + if (++st->bucket >= net->ct.htable_size) return NULL; } head = rcu_dereference(net->ct.hash[st->bucket].first); diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index fe1a64479dd0..26066a2327ad 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -35,9 +35,6 @@ static DEFINE_SPINLOCK(nf_nat_lock); static struct nf_conntrack_l3proto *l3proto __read_mostly; -/* Calculated at init based on memory size */ -static unsigned int nf_nat_htable_size __read_mostly; - #define MAX_IP_NAT_PROTO 256 static const struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO] __read_mostly; @@ -72,7 +69,7 @@ EXPORT_SYMBOL_GPL(nf_nat_proto_put); /* We keep an extra hash for each conntrack, for fast searching. */ static inline unsigned int -hash_by_src(const struct nf_conntrack_tuple *tuple) +hash_by_src(const struct net *net, const struct nf_conntrack_tuple *tuple) { unsigned int hash; @@ -80,7 +77,7 @@ hash_by_src(const struct nf_conntrack_tuple *tuple) hash = jhash_3words((__force u32)tuple->src.u3.ip, (__force u32)tuple->src.u.all, tuple->dst.protonum, 0); - return ((u64)hash * nf_nat_htable_size) >> 32; + return ((u64)hash * net->ipv4.nat_htable_size) >> 32; } /* Is this tuple already taken? (not by us) */ @@ -147,7 +144,7 @@ find_appropriate_src(struct net *net, struct nf_conntrack_tuple *result, const struct nf_nat_range *range) { - unsigned int h = hash_by_src(tuple); + unsigned int h = hash_by_src(net, tuple); const struct nf_conn_nat *nat; const struct nf_conn *ct; const struct hlist_node *n; @@ -330,7 +327,7 @@ nf_nat_setup_info(struct nf_conn *ct, if (have_to_hash) { unsigned int srchash; - srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + srchash = hash_by_src(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); spin_lock_bh(&nf_nat_lock); /* nf_conntrack_alter_reply might re-allocate exntension aera */ nat = nfct_nat(ct); @@ -679,8 +676,10 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct, static int __net_init nf_nat_net_init(struct net *net) { - net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, - &net->ipv4.nat_vmalloced, 0); + /* Leave them the same for the moment. */ + net->ipv4.nat_htable_size = net->ct.htable_size; + net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&net->ipv4.nat_htable_size, + &net->ipv4.nat_vmalloced, 0); if (!net->ipv4.nat_bysource) return -ENOMEM; return 0; @@ -703,7 +702,7 @@ static void __net_exit nf_nat_net_exit(struct net *net) nf_ct_iterate_cleanup(net, &clean_nat, NULL); synchronize_rcu(); nf_ct_free_hashtable(net->ipv4.nat_bysource, net->ipv4.nat_vmalloced, - nf_nat_htable_size); + net->ipv4.nat_htable_size); } static struct pernet_operations nf_nat_net_ops = { @@ -724,9 +723,6 @@ static int __init nf_nat_init(void) return ret; } - /* Leave them the same for the moment. */ - nf_nat_htable_size = nf_conntrack_htable_size; - ret = register_pernet_subsys(&nf_nat_net_ops); if (ret < 0) goto cleanup_extend; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 1e1df209d6b3..1374179bc503 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -84,9 +85,10 @@ static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, return ((u64)h * size) >> 32; } -static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple) +static inline u_int32_t hash_conntrack(const struct net *net, + const struct nf_conntrack_tuple *tuple) { - return __hash_conntrack(tuple, nf_conntrack_htable_size, + return __hash_conntrack(tuple, net->ct.htable_size, nf_conntrack_hash_rnd); } @@ -294,7 +296,7 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_tuple_hash *h; struct hlist_nulls_node *n; - unsigned int hash = hash_conntrack(tuple); + unsigned int hash = hash_conntrack(net, tuple); /* Disable BHs the entire time since we normally need to disable them * at least once for the stats anyway. @@ -364,10 +366,11 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct, void nf_conntrack_hash_insert(struct nf_conn *ct) { + struct net *net = nf_ct_net(ct); unsigned int hash, repl_hash; - hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); - repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); __nf_conntrack_hash_insert(ct, hash, repl_hash); } @@ -395,8 +398,8 @@ __nf_conntrack_confirm(struct sk_buff *skb) if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) return NF_ACCEPT; - hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); - repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); /* We're not in hash table, and we refuse to set up related connections for unconfirmed conns. But packet copies and @@ -466,7 +469,7 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, struct net *net = nf_ct_net(ignored_conntrack); struct nf_conntrack_tuple_hash *h; struct hlist_nulls_node *n; - unsigned int hash = hash_conntrack(tuple); + unsigned int hash = hash_conntrack(net, tuple); /* Disable BHs the entire time since we need to disable them at * least once for the stats anyway. @@ -501,7 +504,7 @@ static noinline int early_drop(struct net *net, unsigned int hash) int dropped = 0; rcu_read_lock(); - for (i = 0; i < nf_conntrack_htable_size; i++) { + for (i = 0; i < net->ct.htable_size; i++) { hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { tmp = nf_ct_tuplehash_to_ctrack(h); @@ -515,7 +518,8 @@ static noinline int early_drop(struct net *net, unsigned int hash) ct = NULL; if (ct || cnt >= NF_CT_EVICTION_RANGE) break; - hash = (hash + 1) % nf_conntrack_htable_size; + + hash = (hash + 1) % net->ct.htable_size; } rcu_read_unlock(); @@ -549,7 +553,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, if (nf_conntrack_max && unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) { - unsigned int hash = hash_conntrack(orig); + unsigned int hash = hash_conntrack(net, orig); if (!early_drop(net, hash)) { atomic_dec(&net->ct.count); if (net_ratelimit()) @@ -1006,7 +1010,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), struct hlist_nulls_node *n; spin_lock_bh(&nf_conntrack_lock); - for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { + for (; *bucket < net->ct.htable_size; (*bucket)++) { hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { ct = nf_ct_tuplehash_to_ctrack(h); if (iter(ct, data)) @@ -1124,7 +1128,7 @@ static void nf_conntrack_cleanup_net(struct net *net) } nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc, - nf_conntrack_htable_size); + net->ct.htable_size); nf_conntrack_ecache_fini(net); nf_conntrack_acct_fini(net); nf_conntrack_expect_fini(net); @@ -1184,10 +1188,12 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) { int i, bucket, vmalloced, old_vmalloced; unsigned int hashsize, old_size; - int rnd; struct hlist_nulls_head *hash, *old_hash; struct nf_conntrack_tuple_hash *h; + if (current->nsproxy->net_ns != &init_net) + return -EOPNOTSUPP; + /* On boot, we can set this without any fancy locking. */ if (!nf_conntrack_htable_size) return param_set_uint(val, kp); @@ -1200,33 +1206,29 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) if (!hash) return -ENOMEM; - /* We have to rehahs for the new table anyway, so we also can - * use a newrandom seed */ - get_random_bytes(&rnd, sizeof(rnd)); - /* Lookups in the old hash might happen in parallel, which means we * might get false negatives during connection lookup. New connections * created because of a false negative won't make it into the hash * though since that required taking the lock. */ spin_lock_bh(&nf_conntrack_lock); - for (i = 0; i < nf_conntrack_htable_size; i++) { + for (i = 0; i < init_net.ct.htable_size; i++) { while (!hlist_nulls_empty(&init_net.ct.hash[i])) { h = hlist_nulls_entry(init_net.ct.hash[i].first, struct nf_conntrack_tuple_hash, hnnode); hlist_nulls_del_rcu(&h->hnnode); - bucket = __hash_conntrack(&h->tuple, hashsize, rnd); + bucket = __hash_conntrack(&h->tuple, hashsize, + nf_conntrack_hash_rnd); hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); } } - old_size = nf_conntrack_htable_size; + old_size = init_net.ct.htable_size; old_vmalloced = init_net.ct.hash_vmalloc; old_hash = init_net.ct.hash; - nf_conntrack_htable_size = hashsize; + init_net.ct.htable_size = nf_conntrack_htable_size = hashsize; init_net.ct.hash_vmalloc = vmalloced; init_net.ct.hash = hash; - nf_conntrack_hash_rnd = rnd; spin_unlock_bh(&nf_conntrack_lock); nf_ct_free_hashtable(old_hash, old_vmalloced, old_size); @@ -1322,7 +1324,9 @@ static int nf_conntrack_init_net(struct net *net) ret = -ENOMEM; goto err_cache; } - net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, + + net->ct.htable_size = nf_conntrack_htable_size; + net->ct.hash = nf_ct_alloc_hashtable(&net->ct.htable_size, &net->ct.hash_vmalloc, 1); if (!net->ct.hash) { ret = -ENOMEM; @@ -1347,7 +1351,7 @@ static int nf_conntrack_init_net(struct net *net) nf_conntrack_expect_fini(net); err_expect: nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc, - nf_conntrack_htable_size); + net->ct.htable_size); err_hash: kmem_cache_destroy(net->ct.nf_conntrack_cachep); err_cache: diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 1b8ed66aa0ba..e73eb04f9598 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -577,7 +577,7 @@ int nf_conntrack_expect_init(struct net *net) if (net_eq(net, &init_net)) { if (!nf_ct_expect_hsize) { - nf_ct_expect_hsize = nf_conntrack_htable_size / 256; + nf_ct_expect_hsize = net->ct.htable_size / 256; if (!nf_ct_expect_hsize) nf_ct_expect_hsize = 1; } diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 65c2a7bc3afc..4b1a56bd074c 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -192,7 +192,7 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, /* Get rid of expecteds, set helpers to NULL. */ hlist_nulls_for_each_entry(h, nn, &net->ct.unconfirmed, hnnode) unhelp(h, me); - for (i = 0; i < nf_conntrack_htable_size; i++) { + for (i = 0; i < net->ct.htable_size; i++) { hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) unhelp(h, me); } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 59d8064eb522..d5217182dbdb 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -594,7 +594,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); last = (struct nf_conn *)cb->args[1]; - for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { + for (; cb->args[0] < init_net.ct.htable_size; cb->args[0]++) { restart: hlist_nulls_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]], hnnode) { diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 193515381970..1a84bf697ec2 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -51,7 +51,7 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq) struct hlist_nulls_node *n; for (st->bucket = 0; - st->bucket < nf_conntrack_htable_size; + st->bucket < net->ct.htable_size; st->bucket++) { n = rcu_dereference(net->ct.hash[st->bucket].first); if (!is_a_nulls(n)) @@ -69,7 +69,7 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq, head = rcu_dereference(head->next); while (is_a_nulls(head)) { if (likely(get_nulls_value(head) == st->bucket)) { - if (++st->bucket >= nf_conntrack_htable_size) + if (++st->bucket >= net->ct.htable_size) return NULL; } head = rcu_dereference(net->ct.hash[st->bucket].first); @@ -358,7 +358,7 @@ static ctl_table nf_ct_sysctl_table[] = { { .ctl_name = NET_NF_CONNTRACK_BUCKETS, .procname = "nf_conntrack_buckets", - .data = &nf_conntrack_htable_size, + .data = &init_net.ct.htable_size, .maxlen = sizeof(unsigned int), .mode = 0444, .proc_handler = proc_dointvec, @@ -429,6 +429,7 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net) goto out_kmemdup; table[1].data = &net->ct.count; + table[2].data = &net->ct.htable_size; table[3].data = &net->ct.sysctl_checksum; table[4].data = &net->ct.sysctl_log_invalid; From 30b1b8f0078eb8ada282f814f47dbecf4283fdfc Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 28 Dec 2009 13:23:36 +0800 Subject: [PATCH 628/670] drm/i915: remove full registers dump debug commit 823f68fd646da6a39a9c0d3eb4c60d69dab5aa13 upstream. This one reverts 9e3a6d155ed0a7636b926a798dd7221ea107b274. As reported by http://bugzilla.kernel.org/show_bug.cgi?id=14485, this dump will cause hang problem on some machine. If something really needs this kind of full registers dump, that could be done within intel-gpu-tools. Cc: Ben Gamari Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_debugfs.c | 30 ----------------------------- 1 file changed, 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index af655e886c6d..7e859d65e291 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -384,37 +384,7 @@ static int i915_error_state(struct seq_file *m, void *unused) return 0; } -static int i915_registers_info(struct seq_file *m, void *data) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - uint32_t reg; - -#define DUMP_RANGE(start, end) \ - for (reg=start; reg < end; reg += 4) \ - seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg)); - - DUMP_RANGE(0x00000, 0x00fff); /* VGA registers */ - DUMP_RANGE(0x02000, 0x02fff); /* instruction, memory, interrupt control registers */ - DUMP_RANGE(0x03000, 0x031ff); /* FENCE and PPGTT control registers */ - DUMP_RANGE(0x03200, 0x03fff); /* frame buffer compression registers */ - DUMP_RANGE(0x05000, 0x05fff); /* I/O control registers */ - DUMP_RANGE(0x06000, 0x06fff); /* clock control registers */ - DUMP_RANGE(0x07000, 0x07fff); /* 3D internal debug registers */ - DUMP_RANGE(0x07400, 0x088ff); /* GPE debug registers */ - DUMP_RANGE(0x0a000, 0x0afff); /* display palette registers */ - DUMP_RANGE(0x10000, 0x13fff); /* MMIO MCHBAR */ - DUMP_RANGE(0x30000, 0x3ffff); /* overlay registers */ - DUMP_RANGE(0x60000, 0x6ffff); /* display engine pipeline registers */ - DUMP_RANGE(0x70000, 0x72fff); /* display and cursor registers */ - DUMP_RANGE(0x73000, 0x73fff); /* performance counters */ - - return 0; -} - - static struct drm_info_list i915_debugfs_list[] = { - {"i915_regs", i915_registers_info, 0}, {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST}, {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, From 47516b77eb1beb5b35c17112284493d008bc7c4a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 15 Sep 2009 22:57:32 +0200 Subject: [PATCH 629/670] drm/i915: add i915_lp_ring_sync helper commit 48764bf43f746113fc77877d7e80f2df23ca4cbb upstream. This just waits until the hw passed the current ring position with cmd execution. This slightly changes the existing i915_wait_request function to make uninterruptible waiting possible - no point in returning to userspace while mucking around with the overlay, that piece of hw is just too fragile. Also replace a magic 0 with the symbolic constant (and kill the then superflous comment) while I was looking at the code. Signed-off-by: Daniel Vetter Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 49 ++++++++++++++++++++++++++------- include/drm/drm_os_linux.h | 2 +- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 95c920fa486f..881eeefb6681 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -825,6 +825,7 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev); int i915_gem_do_init(struct drm_device *dev, unsigned long start, unsigned long end); int i915_gem_idle(struct drm_device *dev); +int i915_lp_ring_sync(struct drm_device *dev); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 07345cacd0cc..838c9d99ead8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1809,12 +1809,8 @@ i915_gem_retire_work_handler(struct work_struct *work) mutex_unlock(&dev->struct_mutex); } -/** - * Waits for a sequence number to be signaled, and cleans up the - * request and object lists appropriately for that event. - */ static int -i915_wait_request(struct drm_device *dev, uint32_t seqno) +i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) { drm_i915_private_t *dev_priv = dev->dev_private; u32 ier; @@ -1841,10 +1837,15 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) dev_priv->mm.waiting_gem_seqno = seqno; i915_user_irq_get(dev); - ret = wait_event_interruptible(dev_priv->irq_queue, - i915_seqno_passed(i915_get_gem_seqno(dev), - seqno) || - atomic_read(&dev_priv->mm.wedged)); + if (interruptible) + ret = wait_event_interruptible(dev_priv->irq_queue, + i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || + atomic_read(&dev_priv->mm.wedged)); + else + wait_event(dev_priv->irq_queue, + i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || + atomic_read(&dev_priv->mm.wedged)); + i915_user_irq_put(dev); dev_priv->mm.waiting_gem_seqno = 0; @@ -1868,6 +1869,34 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) return ret; } +/** + * Waits for a sequence number to be signaled, and cleans up the + * request and object lists appropriately for that event. + */ +static int +i915_wait_request(struct drm_device *dev, uint32_t seqno) +{ + return i915_do_wait_request(dev, seqno, 1); +} + +/** + * Waits for the ring to finish up to the latest request. Usefull for waiting + * for flip events, e.g for the overlay support. */ +int i915_lp_ring_sync(struct drm_device *dev) +{ + uint32_t seqno; + int ret; + + seqno = i915_add_request(dev, NULL, 0); + + if (seqno == 0) + return -ENOMEM; + + ret = i915_do_wait_request(dev, seqno, 0); + BUG_ON(ret == -ERESTARTSYS); + return ret; +} + static void i915_gem_flush(struct drm_device *dev, uint32_t invalidate_domains, @@ -1936,7 +1965,7 @@ i915_gem_flush(struct drm_device *dev, #endif BEGIN_LP_RING(2); OUT_RING(cmd); - OUT_RING(0); /* noop */ + OUT_RING(MI_NOOP); ADVANCE_LP_RING(); } } diff --git a/include/drm/drm_os_linux.h b/include/drm/drm_os_linux.h index 26641e95e0a4..393369147a2d 100644 --- a/include/drm/drm_os_linux.h +++ b/include/drm/drm_os_linux.h @@ -123,5 +123,5 @@ do { \ remove_wait_queue(&(queue), &entry); \ } while (0) -#define DRM_WAKEUP( queue ) wake_up_interruptible( queue ) +#define DRM_WAKEUP( queue ) wake_up( queue ) #define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue ) From 26d415dcf38423cb4c990e82c71e19011a9ad4e6 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 25 Nov 2009 13:09:39 +0800 Subject: [PATCH 630/670] drm/i915: Don't wait interruptible for possible plane buffer flush commit b9241ea31fae4887104e5d1b3b18f4009c25a0c4 upstream. When we setup buffer for display plane, we'll check any pending required GPU flush and possible make interruptible wait for flush complete. But that wait would be most possibly to fail in case of signals received for X process, which will then fail modeset process and put display engine in unconsistent state. The result could be blank screen or CPU hang, and DDX driver would always turn on outputs DPMS after whatever modeset fails or not. So this one creates new helper for setup display plane buffer, and when needing flush using uninterruptible wait for that. This one should fix bug like https://bugs.freedesktop.org/show_bug.cgi?id=24009. Also fixing mode switch stress test on Ironlake. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 51 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 881eeefb6681..f5d49a7ac745 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -829,6 +829,7 @@ int i915_lp_ring_sync(struct drm_device *dev); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); +int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj); int i915_gem_attach_phys_object(struct drm_device *dev, struct drm_gem_object *obj, int id); void i915_gem_detach_phys_object(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 838c9d99ead8..04da731a70ab 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2825,6 +2825,57 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) return 0; } +/* + * Prepare buffer for display plane. Use uninterruptible for possible flush + * wait, as in modesetting process we're not supposed to be interrupted. + */ +int +i915_gem_object_set_to_display_plane(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + uint32_t old_write_domain, old_read_domains; + int ret; + + /* Not valid to be called on unbound objects. */ + if (obj_priv->gtt_space == NULL) + return -EINVAL; + + i915_gem_object_flush_gpu_write_domain(obj); + + /* Wait on any GPU rendering and flushing to occur. */ + if (obj_priv->active) { +#if WATCH_BUF + DRM_INFO("%s: object %p wait for seqno %08x\n", + __func__, obj, obj_priv->last_rendering_seqno); +#endif + ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0); + if (ret != 0) + return ret; + } + + old_write_domain = obj->write_domain; + old_read_domains = obj->read_domains; + + obj->read_domains &= I915_GEM_DOMAIN_GTT; + + i915_gem_object_flush_cpu_write_domain(obj); + + /* It should now be out of any other write domains, and we can update + * the domain values for our changes. + */ + BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + obj->read_domains |= I915_GEM_DOMAIN_GTT; + obj->write_domain = I915_GEM_DOMAIN_GTT; + obj_priv->dirty = 1; + + trace_i915_gem_object_change_domain(obj, + old_read_domains, + old_write_domain); + + return 0; +} + /** * Moves a single object to the CPU read, and possibly write domain. * diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2d6f8ba0ba08..b00a1aaf0d71 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1253,7 +1253,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - ret = i915_gem_object_set_to_gtt_domain(obj, 1); + ret = i915_gem_object_set_to_display_plane(obj); if (ret != 0) { i915_gem_object_unpin(obj); mutex_unlock(&dev->struct_mutex); From fe42d89779a0c5639afe0e543aac1f7d1d7d9582 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Mon, 7 Dec 2009 12:51:52 +0100 Subject: [PATCH 631/670] dasd: remove strings from s390dbf commit b8ed5dd54895647c2690575aad6f07748c2c618a upstream. Remove strings from s390 debugfeature entries that could lead to a crash when the data is read from dbf because the strings do not exist any more. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- drivers/s390/block/dasd.c | 22 ++++++++--------- drivers/s390/block/dasd_eckd.c | 44 +++++++++++++++------------------- drivers/s390/block/dasd_fba.c | 10 ++++---- drivers/s390/block/dasd_int.h | 10 ++++++++ 4 files changed, 44 insertions(+), 42 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 513dec940384..d0ef15af23aa 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -994,10 +994,9 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, return; cqr = (struct dasd_ccw_req *) intparm; if (cqr->status != DASD_CQR_IN_IO) { - DBF_EVENT(DBF_DEBUG, - "invalid status in handle_killed_request: " - "bus_id %s, status %02x", - dev_name(&cdev->dev), cqr->status); + DBF_EVENT_DEVID(DBF_DEBUG, cdev, + "invalid status in handle_killed_request: " + "%02x", cqr->status); return; } @@ -1045,12 +1044,13 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, case -EIO: break; case -ETIMEDOUT: - DBF_EVENT(DBF_WARNING, "%s(%s): request timed out\n", - __func__, dev_name(&cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: " + "request timed out\n", __func__); break; default: - DBF_EVENT(DBF_WARNING, "%s(%s): unknown error %ld\n", - __func__, dev_name(&cdev->dev), PTR_ERR(irb)); + DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: " + "unknown error %ld\n", __func__, + PTR_ERR(irb)); } dasd_handle_killed_request(cdev, intparm); return; @@ -2217,9 +2217,9 @@ int dasd_generic_probe(struct ccw_device *cdev, } ret = dasd_add_sysfs_files(cdev); if (ret) { - DBF_EVENT(DBF_WARNING, - "dasd_generic_probe: could not add sysfs entries " - "for %s\n", dev_name(&cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s", + "dasd_generic_probe: could not add " + "sysfs entries"); return ret; } cdev->handler = &dasd_int_handler; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 80c205bb95ac..678bb946cd39 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -88,9 +88,9 @@ dasd_eckd_probe (struct ccw_device *cdev) /* set ECKD specific ccw-device options */ ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE); if (ret) { - DBF_EVENT(DBF_WARNING, - "dasd_eckd_probe: could not set ccw-device options " - "for %s\n", dev_name(&cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s", + "dasd_eckd_probe: could not set " + "ccw-device options"); return ret; } ret = dasd_generic_probe(cdev, &dasd_eckd_discipline); @@ -885,16 +885,15 @@ static int dasd_eckd_read_conf(struct dasd_device *device) rc = dasd_eckd_read_conf_lpm(device, &conf_data, &conf_len, lpm); if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ - DBF_EVENT(DBF_WARNING, + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "Read configuration data returned " - "error %d for device: %s", rc, - dev_name(&device->cdev->dev)); + "error %d", rc); return rc; } if (conf_data == NULL) { - DBF_EVENT(DBF_WARNING, "No configuration " - "data retrieved for device: %s", - dev_name(&device->cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", + "No configuration data " + "retrieved"); continue; /* no error */ } /* save first valid configuration data */ @@ -941,9 +940,8 @@ static int dasd_eckd_read_features(struct dasd_device *device) sizeof(struct dasd_rssd_features)), device); if (IS_ERR(cqr)) { - DBF_EVENT(DBF_WARNING, "Could not allocate initialization " - "request for device: %s", - dev_name(&device->cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", "Could not " + "allocate initialization request"); return PTR_ERR(cqr); } cqr->startdev = device; @@ -1071,10 +1069,8 @@ static int dasd_eckd_validate_server(struct dasd_device *device) /* may be requested feature is not available on server, * therefore just report error and go ahead */ private = (struct dasd_eckd_private *) device->private; - DBF_EVENT(DBF_WARNING, "PSF-SSC on storage subsystem %s.%s.%04x " - "returned rc=%d for device: %s", - private->uid.vendor, private->uid.serial, - private->uid.ssid, rc, dev_name(&device->cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " + "returned rc=%d", private->uid.ssid, rc); /* RE-Read Configuration Data */ return dasd_eckd_read_conf(device); } @@ -1123,9 +1119,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) if (private->uid.type == UA_BASE_DEVICE) { block = dasd_alloc_block(); if (IS_ERR(block)) { - DBF_EVENT(DBF_WARNING, "could not allocate dasd " - "block structure for device: %s", - dev_name(&device->cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", + "could not allocate dasd " + "block structure"); rc = PTR_ERR(block); goto out_err1; } @@ -1153,9 +1149,8 @@ dasd_eckd_check_characteristics(struct dasd_device *device) rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC, &private->rdc_data, 64); if (rc) { - DBF_EVENT(DBF_WARNING, - "Read device characteristics failed, rc=%d for " - "device: %s", rc, dev_name(&device->cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, + "Read device characteristic failed, rc=%d", rc); goto out_err3; } /* find the vaild cylinder size */ @@ -3253,9 +3248,8 @@ int dasd_eckd_restore_device(struct dasd_device *device) rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC, &temp_rdc_data, 64); if (rc) { - DBF_EVENT(DBF_WARNING, - "Read device characteristics failed, rc=%d for " - "device: %s", rc, dev_name(&device->cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, device->cdev, + "Read device characteristic failed, rc=%d", rc); goto out_err; } spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index f245377e8e27..227b4e91b18e 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -141,9 +141,8 @@ dasd_fba_check_characteristics(struct dasd_device *device) } block = dasd_alloc_block(); if (IS_ERR(block)) { - DBF_EVENT(DBF_WARNING, "could not allocate dasd block " - "structure for device: %s", - dev_name(&device->cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s", "could not allocate " + "dasd block structure"); device->private = NULL; kfree(private); return PTR_ERR(block); @@ -155,9 +154,8 @@ dasd_fba_check_characteristics(struct dasd_device *device) rc = dasd_generic_read_dev_chars(device, DASD_FBA_MAGIC, &private->rdc_data, 32); if (rc) { - DBF_EVENT(DBF_WARNING, "Read device characteristics returned " - "error %d for device: %s", - rc, dev_name(&device->cdev->dev)); + DBF_EVENT_DEVID(DBF_WARNING, cdev, "Read device " + "characteristics returned error %d", rc); device->block = NULL; dasd_free_block(block); device->private = NULL; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 8afd9fa00875..b19f309f3abe 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -108,6 +108,16 @@ do { \ d_data); \ } while(0) +#define DBF_EVENT_DEVID(d_level, d_cdev, d_str, d_data...) \ +do { \ + struct ccw_dev_id __dev_id; \ + ccw_device_get_id(d_cdev, &__dev_id); \ + debug_sprintf_event(dasd_debug_area, \ + d_level, \ + "0.%x.%04x " d_str "\n", \ + __dev_id.ssid, __dev_id.devno, d_data); \ +} while (0) + #define DBF_EXC(d_level, d_str, d_data...)\ do { \ debug_sprintf_exception(dasd_debug_area, \ From fa56c7eaeca469055d79d1a2fe66a67829e44bf0 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 1 Feb 2010 09:17:56 +1100 Subject: [PATCH 632/670] crypto: padlock-sha - Add import/export support commit a8d7ac279743077965afeca0c9ed748507b68e89 upstream. As the padlock driver for SHA uses a software fallback to perform partial hashing, it must implement custom import/export functions. Otherwise hmac which depends on import/export for prehashing will not work with padlock-sha. Reported-by: Wolfgang Walter Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/padlock-sha.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c index 0af80577dc7b..d3a27e0119bc 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c @@ -57,6 +57,23 @@ static int padlock_sha_update(struct shash_desc *desc, return crypto_shash_update(&dctx->fallback, data, length); } +static int padlock_sha_export(struct shash_desc *desc, void *out) +{ + struct padlock_sha_desc *dctx = shash_desc_ctx(desc); + + return crypto_shash_export(&dctx->fallback, out); +} + +static int padlock_sha_import(struct shash_desc *desc, const void *in) +{ + struct padlock_sha_desc *dctx = shash_desc_ctx(desc); + struct padlock_sha_ctx *ctx = crypto_shash_ctx(desc->tfm); + + dctx->fallback.tfm = ctx->fallback; + dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; + return crypto_shash_import(&dctx->fallback, in); +} + static inline void padlock_output_block(uint32_t *src, uint32_t *dst, size_t count) { @@ -235,7 +252,10 @@ static struct shash_alg sha1_alg = { .update = padlock_sha_update, .finup = padlock_sha1_finup, .final = padlock_sha1_final, + .export = padlock_sha_export, + .import = padlock_sha_import, .descsize = sizeof(struct padlock_sha_desc), + .statesize = sizeof(struct sha1_state), .base = { .cra_name = "sha1", .cra_driver_name = "sha1-padlock", @@ -256,7 +276,10 @@ static struct shash_alg sha256_alg = { .update = padlock_sha_update, .finup = padlock_sha256_finup, .final = padlock_sha256_final, + .export = padlock_sha_export, + .import = padlock_sha_import, .descsize = sizeof(struct padlock_sha_desc), + .statesize = sizeof(struct sha256_state), .base = { .cra_name = "sha256", .cra_driver_name = "sha256-padlock", From 9f835c304f14fe5ad4f435c58e9c1e08fda71886 Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Sat, 30 Jan 2010 18:00:17 -0500 Subject: [PATCH 633/670] wmi: Free the allocated acpi objects through wmi_get_event_data commit 3e9b988e4edf065d39c1343937f717319b1c1065 upstream [ backported to 2.6.32 ] These function allocate an acpi object by calling wmi_get_event_data, which then calls acpi_evaluate_object, and it is not freed afterwards. And kernel doc is fixed for parameters of wmi_get_event_data. Signed-off-by: Anisse Astier Acked-by: Randy Dunlap Acked-by: Carlos Corbacho Signed-off-by: Len Brown Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/dell-wmi.c | 1 + drivers/platform/x86/hp-wmi.c | 2 ++ drivers/platform/x86/wmi.c | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 0f900cc9fa7a..f235a9835330 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -180,6 +180,7 @@ static void dell_wmi_notify(u32 value, void *context) printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n", buffer[1] & 0xFFFF); } + kfree(obj); } static int __init dell_wmi_input_setup(void) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index c2842171cec6..36109e19f349 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -377,6 +377,8 @@ static void hp_wmi_notify(u32 value, void *context) eventcode); } else printk(KERN_INFO "HP WMI: Unknown response received\n"); + + kfree(obj); } static int __init hp_wmi_input_setup(void) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 177f8d767df4..87f4c97f2a77 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -510,8 +510,8 @@ EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); /** * wmi_get_event_data - Get WMI data associated with an event * - * @event - Event to find - * &out - Buffer to hold event data + * @event: Event to find + * @out: Buffer to hold event data. out->pointer should be freed with kfree() * * Returns extra data associated with an event in WMI. */ From 06eeea406c93680a55dd333971638af7289f8f7b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 30 Jan 2010 18:01:42 -0500 Subject: [PATCH 634/670] dell-wmi, hp-wmi, msi-wmi: check wmi_get_event_data() return value commit fda11e61ff8a4e3a8ebbd434e46560b67cc0ca9d upstream [ backport to 2.6.32 ] When acpi_evaluate_object() is passed ACPI_ALLOCATE_BUFFER, the caller must kfree the returned buffer if AE_OK is returned. The callers of wmi_get_event_data() pass ACPI_ALLOCATE_BUFFER, and thus must check its return value before accessing or kfree() on the buffer. Signed-off-by: Len Brown Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/dell-wmi.c | 7 ++++++- drivers/platform/x86/hp-wmi.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index f235a9835330..6dec7cc7475f 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -158,8 +158,13 @@ static void dell_wmi_notify(u32 value, void *context) struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; static struct key_entry *key; union acpi_object *obj; + acpi_status status; - wmi_get_event_data(value, &response); + status = wmi_get_event_data(value, &response); + if (status != AE_OK) { + printk(KERN_INFO "dell-wmi: bad event status 0x%x\n", status); + return; + } obj = (union acpi_object *)response.pointer; diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 36109e19f349..deb53b55a41f 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -334,8 +334,13 @@ static void hp_wmi_notify(u32 value, void *context) struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; static struct key_entry *key; union acpi_object *obj; + acpi_status status; - wmi_get_event_data(value, &response); + status = wmi_get_event_data(value, &response); + if (status != AE_OK) { + printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status); + return; + } obj = (union acpi_object *)response.pointer; From 0e1104ada32d242bc6169a2ce4eb19ec4febb813 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 5 Feb 2010 15:00:52 -0500 Subject: [PATCH 635/670] /dev/mem: introduce size_inside_page() commit f222318e9c3a315723e3524fb9d6566b2430db44 upstream /dev/mem: introduce size_inside_page() [ cebbert@redhat.com : backport to 2.6.32 ] [ subset of original patch, for just /dev/kmem ] Introduce size_inside_page() to replace duplicate /dev/mem code. Also apply it to /dev/kmem, whose alignment logic was buggy. Signed-off-by: Wu Fengguang Acked-by: Andi Kleen Cc: Marcelo Tosatti Cc: Greg Kroah-Hartman Cc: Mark Brown Cc: Johannes Berg Cc: Avi Kivity Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- drivers/char/mem.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index a074fceb67d3..1ffb6dd3eae4 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -35,6 +35,19 @@ # include #endif +static inline unsigned long size_inside_page(unsigned long start, + unsigned long size) +{ + unsigned long sz; + + if (-start & (PAGE_SIZE - 1)) + sz = -start & (PAGE_SIZE - 1); + else + sz = PAGE_SIZE; + + return min_t(unsigned long, sz, size); +} + /* * Architectures vary in how they handle caching for addresses * outside of main memory. @@ -430,15 +443,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf, } #endif while (low_count > 0) { - /* - * Handle first page in case it's not aligned - */ - if (-p & (PAGE_SIZE - 1)) - sz = -p & (PAGE_SIZE - 1); - else - sz = PAGE_SIZE; - - sz = min_t(unsigned long, sz, low_count); + sz = size_inside_page(p, low_count); /* * On ia64 if a page has been mapped somewhere as @@ -462,10 +467,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf, if (!kbuf) return -ENOMEM; while (count > 0) { - int len = count; + int len = size_inside_page(p, count); - if (len > PAGE_SIZE) - len = PAGE_SIZE; len = vread(kbuf, (char *)p, len); if (!len) break; @@ -510,15 +513,8 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf, while (count > 0) { char *ptr; - /* - * Handle first page in case it's not aligned - */ - if (-realp & (PAGE_SIZE - 1)) - sz = -realp & (PAGE_SIZE - 1); - else - sz = PAGE_SIZE; - sz = min_t(unsigned long, sz, count); + sz = size_inside_page(realp, count); /* * On ia64 if a page has been mapped somewhere as @@ -578,10 +574,8 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, if (!kbuf) return wrote ? wrote : -ENOMEM; while (count > 0) { - int len = count; + int len = size_inside_page(p, count); - if (len > PAGE_SIZE) - len = PAGE_SIZE; if (len) { written = copy_from_user(kbuf, buf, len); if (written) { From 6b344d83ca458327faa0e1f6afd45c39cceab2a6 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Fri, 5 Feb 2010 15:01:09 -0500 Subject: [PATCH 636/670] devmem: check vmalloc address on kmem read/write commit 325fda71d0badc1073dc59f12a948f24ff05796a [ cebbert@redhat.com : backport to 2.6.32 ] devmem: check vmalloc address on kmem read/write Otherwise vmalloc_to_page() will BUG(). This also makes the kmem read/write implementation aligned with mem(4): "References to nonexistent locations cause errors to be returned." Here we return -ENXIO (inspired by Hugh) if no bytes have been transfered to/from user space, otherwise return partial read/write results. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Wu Fengguang Cc: Greg Kroah-Hartman Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- drivers/char/mem.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 1ffb6dd3eae4..96b2586d2bec 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -421,6 +421,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf, unsigned long p = *ppos; ssize_t low_count, read, sz; char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ + int err = 0; read = 0; if (p < (unsigned long) high_memory) { @@ -469,12 +470,16 @@ static ssize_t read_kmem(struct file *file, char __user *buf, while (count > 0) { int len = size_inside_page(p, count); + if (!is_vmalloc_or_module_addr((void *)p)) { + err = -ENXIO; + break; + } len = vread(kbuf, (char *)p, len); if (!len) break; if (copy_to_user(buf, kbuf, len)) { - free_page((unsigned long)kbuf); - return -EFAULT; + err = -EFAULT; + break; } count -= len; buf += len; @@ -483,8 +488,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf, } free_page((unsigned long)kbuf); } - *ppos = p; - return read; + *ppos = p; + return read ? read : err; } @@ -553,6 +558,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, ssize_t virtr = 0; ssize_t written; char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ + int err = 0; if (p < (unsigned long) high_memory) { @@ -576,13 +582,15 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, while (count > 0) { int len = size_inside_page(p, count); + if (!is_vmalloc_or_module_addr((void *)p)) { + err = -ENXIO; + break; + } if (len) { written = copy_from_user(kbuf, buf, len); if (written) { - if (wrote + virtr) - break; - free_page((unsigned long)kbuf); - return -EFAULT; + err = -EFAULT; + break; } } len = vwrite(kbuf, (char *)p, len); @@ -594,8 +602,8 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, free_page((unsigned long)kbuf); } - *ppos = p; - return virtr + wrote; + *ppos = p; + return virtr + wrote ? : err; } #endif From 483d7142396f0d8b8f8748a4069b71c13ca662e5 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 5 Feb 2010 15:02:13 -0500 Subject: [PATCH 637/670] devmem: fix kmem write bug on memory holes commit c85e9a97c4102ce2e83112da850d838cfab5ab13 upstream devmem: fix kmem write bug on memory holes [ cebbert@redhat.com : backport to 2.6.32 ] write_kmem() used to assume vwrite() always return the full buffer length. However now vwrite() could return 0 to indicate memory hole. This creates a bug that "buf" is not advanced accordingly. Fix it to simply ignore the return value, hence the memory hole. Signed-off-by: Wu Fengguang Cc: Andi Kleen Cc: Benjamin Herrenschmidt Cc: Christoph Lameter Cc: Ingo Molnar Cc: Tejun Heo Cc: Nick Piggin Cc: KAMEZAWA Hiroyuki Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Chuck Ebbert Signed-off-by: Greg Kroah-Hartman --- drivers/char/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 96b2586d2bec..aef3fb42150e 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -593,7 +593,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, break; } } - len = vwrite(kbuf, (char *)p, len); + vwrite(kbuf, (char *)p, len); count -= len; buf += len; virtr += len; From 36a508e6c61a3c49680ee349149a8f5f1fb5acd8 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Mon, 25 Jan 2010 16:20:52 +0530 Subject: [PATCH 638/670] SCSI: mptfusion : mptscsih_abort return value should be SUCCESS instead of value 0. commit 9858ae38011d699d4c2fa7f3493a47accf43a0f5 upstream. retval should be SUCCESS/FAILED which is defined at scsi.h retval = 0 is directing wrong return value. It must be retval = SUCCESS. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/message/fusion/mptscsih.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index c29578614504..6cea7181ed73 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1720,7 +1720,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: " "Command not in the active list! (sc=%p)\n", ioc->name, SCpnt)); - retval = 0; + retval = SUCCESS; goto out; } From 473e685ee12ccd50d626b58c455dde6bbb51df61 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 11 Dec 2009 22:58:17 +0000 Subject: [PATCH 639/670] sh: Couple kernel and user write page perm bits for CONFIG_X2TLB commit fcb4ebd678858850e8b029909064175cb627868d upstream. pte_write() should check whether the permissions include either the user or kernel write permission bits. Likewise, pte_wrprotect() needs to remove both the kernel and user write bits. Without this patch handle_tlbmiss() doesn't handle faulting in pages from the P3 area (our vmalloc space) because of a write. Mappings of the P3 space have the _PAGE_EXT_KERN_WRITE bit but not _PAGE_EXT_USER_WRITE. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt Signed-off-by: Greg Kroah-Hartman --- arch/sh/include/asm/pgtable_32.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h index c0d359ce337b..ba64e7f5e39b 100644 --- a/arch/sh/include/asm/pgtable_32.h +++ b/arch/sh/include/asm/pgtable_32.h @@ -344,7 +344,8 @@ static inline void set_pte(pte_t *ptep, pte_t pte) #define pte_special(pte) ((pte).pte_low & _PAGE_SPECIAL) #ifdef CONFIG_X2TLB -#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE) +#define pte_write(pte) \ + ((pte).pte_high & (_PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE)) #else #define pte_write(pte) ((pte).pte_low & _PAGE_RW) #endif @@ -358,7 +359,7 @@ static inline pte_t pte_##fn(pte_t pte) { pte.pte_##h op; return pte; } * individually toggled (and user permissions are entirely decoupled from * kernel permissions), we attempt to couple them a bit more sanely here. */ -PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE); +PTE_BIT_FUNC(high, wrprotect, &= ~(_PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE)); PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE); PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE); #else From 1393ad25685ec7f91137160dc482e7bb00cb27d2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 12 Feb 2010 18:17:06 +0100 Subject: [PATCH 640/670] ALSA: hda - use WARN_ON_ONCE() for zero-division detection commit d6d8bf549393484e906913f02fa3c9518a2819b6 upstream. Replace the zero-division warning message with WARN_ON_ONCE() per the advice by Linus. This shouldn't happen, but if it happens, it's possible that the bug happens often due to buggy IRQs. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/hda_intel.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 95c9b9717ba8..fec8724b9125 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1858,12 +1858,9 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) if (!bdl_pos_adj[chip->dev_index]) return 1; /* no delayed ack */ - if (azx_dev->period_bytes == 0) { - printk(KERN_WARNING - "hda-intel: Divide by zero was avoided " - "in azx_dev->period_bytes.\n"); - return 0; - } + if (WARN_ONCE(!azx_dev->period_bytes, + "hda-intel: zero azx_dev->period_bytes")) + return 0; /* this shouldn't happen! */ if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) return 0; /* NG - it's below the period boundary */ return 1; /* OK, it's fine */ From b49b8e39e9c06a4d07c215de211279a91c42abc7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 8 Feb 2010 15:00:39 -0800 Subject: [PATCH 641/670] dst: call cond_resched() in dst_gc_task() commit 2fc1b5dd99f66d93ffc23fd8df82d384c1a354c8 upstream. Kernel bugzilla #15239 On some workloads, it is quite possible to get a huge dst list to process in dst_gc_task(), and trigger soft lockup detection. Fix is to call cond_resched(), as we run in process context. Reported-by: Pawel Staszewski Tested-by: Pawel Staszewski Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dst.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/dst.c b/net/core/dst.c index 57bc4d5b8d08..cb1b3488b739 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -79,6 +80,7 @@ static void dst_gc_task(struct work_struct *work) while ((dst = next) != NULL) { next = dst->next; prefetch(&next->next); + cond_resched(); if (likely(atomic_read(&dst->__refcnt))) { last->next = dst; last = dst; From a63123d12b7ced1d75b548379251982ad2583fbe Mon Sep 17 00:00:00 2001 From: Alex Murray Date: Wed, 13 Jan 2010 23:15:03 +1030 Subject: [PATCH 642/670] ALSA: hda - Improved MacBook (Pro) 5,1 / 5,2 support commit a76221d47ef2b73ff16c0fef00a784026308ea02 upstream. This patch adds support for automatically muting the speakers when headphones are inserted, as well as relabelling the headphone widgets from the non-standard "HP" to the standard "Headphone" for the mb5 model. Signed-off-by: Alex Murray Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c2e937038412..911dd1fec22e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7042,8 +7042,8 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = { HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT), HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("HP Playback Volume", 0x0f, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("HP Playback Switch", 0x0f, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), + HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), @@ -7430,6 +7430,7 @@ static struct hda_verb alc885_mb5_init_verbs[] = { {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x14, AC_VERB_SET_CONNECT_SEL, 0x03}, + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, /* Front Mic pin: input vref at 80% */ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, @@ -7554,6 +7555,27 @@ static void alc885_mbp3_setup(struct hda_codec *codec) spec->autocfg.speaker_pins[0] = 0x14; } +static void alc885_mb5_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x14, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0, + HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); + snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0, + HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); + +} + +static void alc885_mb5_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + /* Headphone insertion or removal. */ + if ((res >> 26) == ALC880_HP_EVENT) + alc885_mb5_automute(codec); +} + static struct hda_verb alc882_targa_verbs[] = { {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -8996,6 +9018,8 @@ static struct alc_config_preset alc882_presets[] = { .input_mux = &mb5_capture_source, .dig_out_nid = ALC882_DIGOUT_NID, .dig_in_nid = ALC882_DIGIN_NID, + .unsol_event = alc885_mb5_unsol_event, + .init_hook = alc885_mb5_automute, }, [ALC885_MACPRO] = { .mixers = { alc882_macpro_mixer }, From c5fc9aa0845fa2920e0f9d70844151832bfd9d1a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 28 Jan 2010 22:11:38 -0500 Subject: [PATCH 643/670] befs: fix leak commit 8dd5ca532c2d2c2b85f16bc038ebfff05b8853e1 upstream. Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman --- fs/befs/linuxvfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 33baf27fac78..34ddda888e63 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -873,6 +873,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent) brelse(bh); unacquire_priv_sbp: + kfree(befs_sb->mount_opts.iocharset); kfree(sb->s_fs_info); unacquire_none: From c74c819eabc8b9ccfc91eafc8c253bce57661dae Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 2 Feb 2010 13:43:59 -0800 Subject: [PATCH 644/670] rtc-fm3130: add missing braces commit f4b5162820de60204afa5c8639335f4931b7fb0c upstream. Add missing braces for multiline 'if' statements in fm3130_probe. Signed-off-by: Sergey Matyukevich Signed-off-by: Alessandro Zummo Cc: Sergey Lapin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-fm3130.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 3a7be11cc6b9..812c66755083 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -376,20 +376,22 @@ static int __devinit fm3130_probe(struct i2c_client *client, } /* Disabling calibration mode */ - if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) { i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] & ~(FM3130_RTC_CONTROL_BIT_CAL)); dev_warn(&client->dev, "Disabling calibration mode!\n"); + } /* Disabling read and write modes */ if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE || - fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) + fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) { i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] & ~(FM3130_RTC_CONTROL_BIT_READ | FM3130_RTC_CONTROL_BIT_WRITE)); dev_warn(&client->dev, "Disabling READ or WRITE mode!\n"); + } /* oscillator off? turn it on, so clock can tick. */ if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN) From 2c494f553a2c3c9dc155fc5bb0eff27e3a0fbef2 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 4 Feb 2010 01:04:50 -0500 Subject: [PATCH 645/670] Call flush_dcache_page after PIO data transfers in libata-sff.c commit 2d68b7fe55d9e19a8a868224ed0dfd6526568521 upstream. flush_dcache_page() must be called after (!ATA_TFLAG_WRITE) the data copying to avoid D-cache aliasing with user space or I-D cache coherency issues (when reading data from an ATA device using PIO, the kernel dirties the D-cache but there is no flush_dcache_page() required on Harvard architectures). Signed-off-by: Catalin Marinas Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-sff.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index bbbb1fab1755..2ae15c3b22a7 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -893,6 +893,9 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) do_write); } + if (!do_write) + flush_dcache_page(page); + qc->curbytes += qc->sect_size; qc->cursg_ofs += qc->sect_size; From e045288ec2a2274dc26eaba6b21cf2770b48e0ed Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Jan 2010 16:04:15 +0900 Subject: [PATCH 646/670] ahci: add Acer G725 to broken suspend list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit cedc9bf906dae044443d403371c887affdb44168 upstream. Acer G725 shares the same suspend problem with the HP laptops which lose ATA devices on resume. New firmware which fixes the problem is already available. Add G725 with old firmwares to the broken suspend list. This problem has been reported in bko#15104. http://bugzilla.kernel.org/show_bug.cgi?id=15104 Signed-off-by: Tejun Heo Reported-by: Jani-Matti Hätinen Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/ata/ahci.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 9519c777af83..9b375028318a 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -2868,6 +2868,21 @@ static bool ahci_broken_suspend(struct pci_dev *pdev) }, .driver_data = "F.23", /* cutoff BIOS version */ }, + /* + * Acer eMachines G725 has the same problem. BIOS + * V1.03 is known to be broken. V3.04 is known to + * work. Inbetween, there are V1.06, V2.06 and V3.03 + * that we don't have much idea about. For now, + * blacklist anything older than V3.04. + */ + { + .ident = "G725", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "eMachines"), + DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"), + }, + .driver_data = "V3.04", /* cutoff BIOS version */ + }, { } /* terminate list */ }; const struct dmi_system_id *dmi = dmi_first_match(sysids); From 6d14e6b46af551e2551594ab5ab9356fb4cebbe7 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 4 Feb 2010 14:00:41 -0800 Subject: [PATCH 647/670] pktgen: Fix freezing problem commit 1b3f720bf033fde1fbb6231f9b156b918c5f68d8 upstream. Add missing try_to_freeze() to one of the pktgen_thread_worker() code paths so that it doesn't block suspend/hibernation. Fixes http://bugzilla.kernel.org/show_bug.cgi?id=15006 Signed-off-by: Rafael J. Wysocki Reported-and-tested-by: Ciprian Dorin Craciun Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/pktgen.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 6e79e96cb4f2..6a993b17ae3f 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3516,6 +3516,7 @@ static int pktgen_thread_worker(void *arg) wait_event_interruptible_timeout(t->queue, t->control != 0, HZ/10); + try_to_freeze(); continue; } From 16ecf8a237415fac700d6c227f763a2be566c92a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 3 Feb 2010 16:13:08 +0100 Subject: [PATCH 648/670] x86/amd-iommu: Fix IOMMU-API initialization for iommu=pt commit f5325094379158e6b876ea0010c807bf7890ec8f upstream This patch moves the initialization of the iommu-api out of the dma-ops initialization code. This ensures that the iommu-api is initialized even with iommu=pt. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/amd_iommu.h | 1 + arch/x86/kernel/amd_iommu.c | 7 +++++-- arch/x86/kernel/amd_iommu_init.c | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/amd_iommu.h b/arch/x86/include/asm/amd_iommu.h index 4b180897e6b5..18aa3f8e0821 100644 --- a/arch/x86/include/asm/amd_iommu.h +++ b/arch/x86/include/asm/amd_iommu.h @@ -32,6 +32,7 @@ extern void amd_iommu_flush_all_domains(void); extern void amd_iommu_flush_all_devices(void); extern void amd_iommu_shutdown(void); extern void amd_iommu_apply_erratum_63(u16 devid); +extern void amd_iommu_init_api(void); #else static inline int amd_iommu_init(void) { return -ENODEV; } static inline void amd_iommu_detect(void) { } diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index e3f85feaae2e..ff964960e065 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -2083,6 +2083,11 @@ static struct dma_map_ops amd_iommu_dma_ops = { .dma_supported = amd_iommu_dma_supported, }; +void __init amd_iommu_init_api(void) +{ + register_iommu(&amd_iommu_ops); +} + /* * The function which clues the AMD IOMMU driver into dma_ops. */ @@ -2124,8 +2129,6 @@ int __init amd_iommu_init_dma_ops(void) /* Make the driver finally visible to the drivers */ dma_ops = &amd_iommu_dma_ops; - register_iommu(&amd_iommu_ops); - bus_register_notifier(&pci_bus_type, &device_nb); amd_iommu_stats_init(); diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index c8243f04e62d..362ab88c73ac 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -1288,9 +1288,12 @@ int __init amd_iommu_init(void) ret = amd_iommu_init_passthrough(); else ret = amd_iommu_init_dma_ops(); + if (ret) goto free; + amd_iommu_init_api(); + enable_iommus(); if (iommu_pass_through) From 314a4e5441e5402e16c5e810f33a4ed842d0a473 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 3 Feb 2010 16:13:41 +0100 Subject: [PATCH 649/670] x86/amd-iommu: Fix deassignment of a device from the pt_domain commit d3ad9373b7c29b63d5e8460a69453718d200cc3b upstream. Deassigning a device from the passthrough domain does not work and breaks device assignment to kvm guests. This patch fixes the issue. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/amd_iommu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index ff964960e065..23fc9fe1625f 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1230,9 +1230,10 @@ static void __detach_device(struct protection_domain *domain, u16 devid) /* * If we run in passthrough mode the device must be assigned to the - * passthrough domain if it is detached from any other domain + * passthrough domain if it is detached from any other domain. + * Make sure we can deassign from the pt_domain itself. */ - if (iommu_pass_through) { + if (iommu_pass_through && domain != pt_domain) { struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; __attach_device(iommu, pt_domain, devid); } From 5a863d4181b7d028e19868211c12169babbee39f Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sat, 21 Nov 2009 00:23:37 -0800 Subject: [PATCH 650/670] x86: Re-get cfg_new in case reuse/move irq_desc commit 37ef2a3029fde884808ff1b369677abc7dd9a79a upstream. When irq_desc is moved, we need to make sure to use the right cfg_new. Signed-off-by: Yinghai Lu LKML-Reference: <4B07A739.3030104@kernel.org> Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/apic/io_apic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index dc69f28489f5..c107e837ed7d 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3157,6 +3157,7 @@ unsigned int create_irq_nr(unsigned int irq_want, int node) continue; desc_new = move_irq_desc(desc_new, node); + cfg_new = desc_new->chip_data; if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0) irq = new; From 98baa75bcbacb200b7e4e0ee01b508f4d459d8ce Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 17 Dec 2009 01:16:00 +0200 Subject: [PATCH 651/670] Staging: fix rtl8187se compilation errors with mac80211 commit df574b8ecfb3a84af96229f336a6be88ca4a7055 upstream. This patch fixes compilation problems that were caused by function naming conflicts between the rtl8187se driver and the mac80211 stack. Signed-off-by: George Kadianakis Cc: maximilian attems Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211.h | 10 +++++----- drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c | 2 +- .../rtl8187se/ieee80211/ieee80211_softmac.c | 14 +++++++------- drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c | 2 +- drivers/staging/rtl8187se/r8180_core.c | 10 +++++----- drivers/staging/rtl8187se/r8180_wx.c | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h index 3222c22152fb..0d490c164db6 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h @@ -1318,13 +1318,13 @@ extern int ieee80211_encrypt_fragment( struct sk_buff *frag, int hdr_len); -extern int ieee80211_xmit(struct sk_buff *skb, +extern int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev); extern void ieee80211_txb_free(struct ieee80211_txb *); /* ieee80211_rx.c */ -extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, +extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, struct ieee80211_hdr_4addr *header, @@ -1376,8 +1376,8 @@ extern void ieee80211_stop_protocol(struct ieee80211_device *ieee); extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); extern void ieee80211_reset_queue(struct ieee80211_device *ieee); -extern void ieee80211_wake_queue(struct ieee80211_device *ieee); -extern void ieee80211_stop_queue(struct ieee80211_device *ieee); +extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee); +extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee); extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); @@ -1385,7 +1385,7 @@ extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct extern void notify_wx_assoc_event(struct ieee80211_device *ieee); extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success); extern void SendDisassociation(struct ieee80211_device *ieee,u8* asSta,u8 asRsn); -extern void ieee80211_start_scan(struct ieee80211_device *ieee); +extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee); //Add for RF power on power off by lizhaoming 080512 extern void SendDisassociation(struct ieee80211_device *ieee, diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c index 5e2e79b1e341..7ad305b6eb13 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c @@ -470,7 +470,7 @@ static int is_duplicate_packet(struct ieee80211_device *ieee, /* All received frames are sent to this function. @skb contains the frame in * IEEE 802.11 format, i.e., in the format it was sent over air. * This function is called only as a tasklet (software IRQ). */ -int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, +int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats) { struct net_device *dev = ieee->dev; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 334e4c7ec61b..a2fa9a9c7297 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -689,7 +689,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee) } /* called with ieee->lock held */ -void ieee80211_start_scan(struct ieee80211_device *ieee) +void ieee80211_rtl_start_scan(struct ieee80211_device *ieee) { if(IS_DOT11D_ENABLE(ieee) ) { @@ -1196,7 +1196,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee) } } -void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) +void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) { u8 *c; struct sk_buff *skb; @@ -1898,7 +1898,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, ieee80211_associate_step2(ieee); }else{ - ieee80211_auth_challenge(ieee, challenge, chlen); + ieee80211_rtl_auth_challenge(ieee, challenge, chlen); } }else{ ieee->softmac_stats.rx_auth_rs_err++; @@ -2047,7 +2047,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee) } -void ieee80211_wake_queue(struct ieee80211_device *ieee) +void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) { unsigned long flags; @@ -2089,7 +2089,7 @@ exit : } -void ieee80211_stop_queue(struct ieee80211_device *ieee) +void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) { //unsigned long flags; //spin_lock_irqsave(&ieee->lock,flags); @@ -2301,7 +2301,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee) //#else if (ieee->state == IEEE80211_NOLINK){ ieee->actscanning = true; - ieee80211_start_scan(ieee); + ieee80211_rtl_start_scan(ieee); } //#endif spin_unlock_irqrestore(&ieee->lock, flags); @@ -2357,7 +2357,7 @@ void ieee80211_associate_retry_wq(struct work_struct *work) if(ieee->state == IEEE80211_NOLINK){ ieee->beinretry = false; ieee->actscanning = true; - ieee80211_start_scan(ieee); + ieee80211_rtl_start_scan(ieee); } //YJ,add,080828, notify os here if(ieee->state == IEEE80211_NOLINK) diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c index e2945db61795..c7996eab40ca 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c @@ -305,7 +305,7 @@ ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network) } /* SKBs are added to the ieee->tx_queue. */ -int ieee80211_xmit(struct sk_buff *skb, +int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_device *ieee = netdev_priv(dev); diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 53e654d0d4fa..3f191431671f 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -1830,7 +1830,7 @@ void rtl8180_rx(struct net_device *dev) if(priv->rx_skb->len > 4) skb_trim(priv->rx_skb,priv->rx_skb->len-4); #ifndef RX_DONT_PASS_UL - if(!ieee80211_rx(priv->ieee80211, + if(!ieee80211_rtl_rx(priv->ieee80211, priv->rx_skb, &stats)){ #endif // RX_DONT_PASS_UL @@ -1936,11 +1936,11 @@ rate) if (!check_nic_enought_desc(dev, priority)){ DMESGW("Error: no descriptor left by previous TX (avail %d) ", get_curr_tx_free_desc(dev, priority)); - ieee80211_stop_queue(priv->ieee80211); + ieee80211_rtl_stop_queue(priv->ieee80211); } rtl8180_tx(dev, skb->data, skb->len, priority, morefrag,0,rate); if (!check_nic_enought_desc(dev, priority)) - ieee80211_stop_queue(priv->ieee80211); + ieee80211_rtl_stop_queue(priv->ieee80211); spin_unlock_irqrestore(&priv->tx_lock,flags); } @@ -3846,7 +3846,7 @@ static const struct net_device_ops rtl8180_netdev_ops = { .ndo_set_mac_address = r8180_set_mac_adr, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, - .ndo_start_xmit = ieee80211_xmit, + .ndo_start_xmit = ieee80211_rtl_xmit, }; static int __devinit rtl8180_pci_probe(struct pci_dev *pdev, @@ -4066,7 +4066,7 @@ void rtl8180_try_wake_queue(struct net_device *dev, int pri) spin_unlock_irqrestore(&priv->tx_lock,flags); if(enough_desc) - ieee80211_wake_queue(priv->ieee80211); + ieee80211_rtl_wake_queue(priv->ieee80211); } void rtl8180_tx_isr(struct net_device *dev, int pri,short error) diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c index 766892e31f52..637ee8e01806 100644 --- a/drivers/staging/rtl8187se/r8180_wx.c +++ b/drivers/staging/rtl8187se/r8180_wx.c @@ -377,7 +377,7 @@ static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a, // queue_work(priv->ieee80211->wq, &priv->ieee80211->wx_sync_scan_wq); //printk("start scan============================>\n"); ieee80211_softmac_ips_scan_syncro(priv->ieee80211); -//ieee80211_start_scan(priv->ieee80211); +//ieee80211_rtl_start_scan(priv->ieee80211); /* intentionally forget to up sem */ // up(&priv->ieee80211->wx_sem); ret = 0; From d13e7a58664e0e35db5e524176cb70143c7c07c2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 28 Dec 2009 12:24:22 +0100 Subject: [PATCH 652/670] ALSA: usb-audio - Avoid Oops after disconnect commit 78b8d5d2ee280c463908fd75f3bdf246bcb6ac8d upstream. As the release of substreams may be done asynchronously from the disconnection, close callback needs to check the shutdown flag before actually accessing the usb interface. Reference: Novell bnc#505027 http://bugzilla.novell.com/show_bug.cgi?id=565027 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/usbaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8803d9d93f84..f26a1254b0bb 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1936,7 +1936,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_usb_substream *subs = &as->substream[direction]; - if (subs->interface >= 0) { + if (!as->chip->shutdown && subs->interface >= 0) { usb_set_interface(subs->dev, subs->interface, 0); subs->interface = -1; } From 458c2928268392756c01fafebbebc31403968c2c Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Wed, 9 Dec 2009 12:31:34 -0800 Subject: [PATCH 653/670] serial: 8250: add serial transmitter fully empty test commit bca476139d2ded86be146dae09b06e22548b67f3 upstream. When controlling an industrial radio modem it can be necessary to manipulate the handshake lines in order to control the radio modem's transmitter, from userspace. The transmitter should not be turned off before all characters have been transmitted. serial8250_tx_empty() was reporting that all characters were transmitted before they actually were. === Discovered in parallel with more testing and analysis by Kees Schoenmakers as follows: I ran into an NetMos 9835 serial pci board which behaves a little different than the standard. This type of expansion board is very common. "Standard" 8250 compatible devices clear the 'UART_LST_TEMT" bit together with the "UART_LSR_THRE" bit when writing data to the device. The NetMos device does it slightly different I believe that the TEMT bit is coupled to the shift register. The problem is that after writing data to the device and very quickly after that one does call serial8250_tx_empty, it returns the wrong information. My patch makes the test more robust (and solves the problem) and it does not affect the already correct devices. Alan: We may yet need to quirk this but now we know which chips we have a way to do that should we find this breaks some other 8250 clone with dodgy THRE. Signed-off-by: Dick Hollenbeck Signed-off-by: Alan Cox Cc: Kees Schoenmakers Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 807042b14882..5ed1b828a7ca 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -83,6 +83,9 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */ #define PASS_LIMIT 256 +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + + /* * We default to IRQ0 for the "no irq" hack. Some * machine types want others as well - they're free @@ -1792,7 +1795,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; spin_unlock_irqrestore(&up->port.lock, flags); - return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0; + return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0; } static unsigned int serial8250_get_mctrl(struct uart_port *port) @@ -1850,8 +1853,6 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&up->port.lock, flags); } -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - /* * Wait for transmitter & holding register to empty */ From 0f102935a606e13e923905451c097acf8e87e4cd Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 3 Feb 2010 23:13:24 -0800 Subject: [PATCH 654/670] sysfs: sysfs_sd_setattr set iattrs unconditionally commit 7c0ff870d1ed287504a61ed865f3d728c757436b upstream. There is currently a bug in sysfs_sd_setattr inherited from sysfs_setattr in 2.6.32 where the first time we set the attributes on a sysfs file we allocate backing store but do not set the backing store attributes. Resulting in overly restrictive permissions on sysfs files. The fix is to simply modify the code so that it always executes when we update the sysfs attributes, as we did in 2.6.31 and earlier. Signed-off-by: Eric W. Biederman Tested-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/inode.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index e28cecf179f5..02a022a3d473 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -94,30 +94,29 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) if (!sd_attrs) return -ENOMEM; sd->s_iattr = sd_attrs; - } else { - /* attributes were changed at least once in past */ - iattrs = &sd_attrs->ia_iattr; + } + /* attributes were changed at least once in past */ + iattrs = &sd_attrs->ia_iattr; - if (ia_valid & ATTR_UID) - iattrs->ia_uid = iattr->ia_uid; - if (ia_valid & ATTR_GID) - iattrs->ia_gid = iattr->ia_gid; - if (ia_valid & ATTR_ATIME) - iattrs->ia_atime = timespec_trunc(iattr->ia_atime, - inode->i_sb->s_time_gran); - if (ia_valid & ATTR_MTIME) - iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime, - inode->i_sb->s_time_gran); - if (ia_valid & ATTR_CTIME) - iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime, - inode->i_sb->s_time_gran); - if (ia_valid & ATTR_MODE) { - umode_t mode = iattr->ia_mode; + if (ia_valid & ATTR_UID) + iattrs->ia_uid = iattr->ia_uid; + if (ia_valid & ATTR_GID) + iattrs->ia_gid = iattr->ia_gid; + if (ia_valid & ATTR_ATIME) + iattrs->ia_atime = timespec_trunc(iattr->ia_atime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_MTIME) + iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_CTIME) + iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_MODE) { + umode_t mode = iattr->ia_mode; - if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) - mode &= ~S_ISGID; - iattrs->ia_mode = sd->s_mode = mode; - } + if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) + mode &= ~S_ISGID; + iattrs->ia_mode = sd->s_mode = mode; } return error; } From a206591bd37f7f63d1ccaabf73cbaff25b29f51d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 10 Feb 2010 13:32:49 +0100 Subject: [PATCH 655/670] class: Free the class private data in class_release commit 18d19c96457d172d913510c083bc7411ed40cb10 upstream. Fix a memory leak by freeing the memory allocated in __class_register for the class private data. Signed-off-by: Laurent Pinchart Acked-by: Artem Bityutskiy Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/class.c b/drivers/base/class.c index 161746deab4b..6e2c3b064f53 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -59,6 +59,8 @@ static void class_release(struct kobject *kobj) else pr_debug("class '%s' does not have a release() function, " "be careful\n", class->name); + + kfree(cp); } static struct sysfs_ops class_sysfs_ops = { From 2bac497bb2f16f1c01a61a0132d2f7a8dabd0e2a Mon Sep 17 00:00:00 2001 From: Greg KH Date: Mon, 15 Feb 2010 09:37:46 -0800 Subject: [PATCH 656/670] USB: usbfs: only copy the actual data received commit d4a4683ca054ed9917dfc9e3ff0f7ecf74ad90d6 upstream. We need to only copy the data received by the device to userspace, not the whole kernel buffer, which can contain "stale" data. Thanks to Marcus Meissner for pointing this out and testing the fix. Reported-by: Marcus Meissner Tested-by: Marcus Meissner Cc: Alan Stern Cc: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 181f78c84105..bff195859e14 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1312,9 +1312,9 @@ static int processcompl(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer) + if (as->userbuffer && urb->actual_length) if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->transfer_buffer_length)) + urb->actual_length)) goto err_out; if (put_user(as->status, &userurb->status)) goto err_out; @@ -1435,9 +1435,9 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer) + if (as->userbuffer && urb->actual_length) if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->transfer_buffer_length)) + urb->actual_length)) return -EFAULT; if (put_user(as->status, &userurb->status)) return -EFAULT; From fda9759364aea7d1acc8f278e26c98894f5ef52e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 16 Feb 2010 12:35:07 -0800 Subject: [PATCH 657/670] USB: usbfs: properly clean up the as structure on error paths commit ddeee0b2eec2a51b0712b04de4b39e7bec892a53 upstream. I notice that the processcompl_compat() function seems to be leaking the 'struct async *as' in the error paths. I think that the calling convention is fundamentally buggered. The caller is the one that did the "reap_as()" to get the as thing, the caller should be the one to free it too. Freeing it in the caller also means that it very clearly always gets freed, and avoids the need for any "free in the error case too". From: Linus Torvalds Cc: Alan Stern Cc: Marcus Meissner Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index bff195859e14..24120db005a2 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1334,14 +1334,11 @@ static int processcompl(struct async *as, void __user * __user *arg) } } - free_async(as); - if (put_user(addr, (void __user * __user *)arg)) return -EFAULT; return 0; err_out: - free_async(as); return -EFAULT; } @@ -1371,8 +1368,11 @@ static struct async *reap_as(struct dev_state *ps) static int proc_reapurb(struct dev_state *ps, void __user *arg) { struct async *as = reap_as(ps); - if (as) - return processcompl(as, (void __user * __user *)arg); + if (as) { + int retval = processcompl(as, (void __user * __user *)arg); + free_async(as); + return retval; + } if (signal_pending(current)) return -EINTR; return -EIO; @@ -1380,11 +1380,16 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg) static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) { + int retval; struct async *as; - if (!(as = async_getcompleted(ps))) - return -EAGAIN; - return processcompl(as, (void __user * __user *)arg); + as = async_getcompleted(ps); + retval = -EAGAIN; + if (as) { + retval = processcompl(as, (void __user * __user *)arg); + free_async(as); + } + return retval; } #ifdef CONFIG_COMPAT @@ -1457,7 +1462,6 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) } } - free_async(as); if (put_user(ptr_to_compat(addr), (u32 __user *)arg)) return -EFAULT; return 0; @@ -1466,8 +1470,11 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) { struct async *as = reap_as(ps); - if (as) - return processcompl_compat(as, (void __user * __user *)arg); + if (as) { + int retval = processcompl_compat(as, (void __user * __user *)arg); + free_async(as); + return retval; + } if (signal_pending(current)) return -EINTR; return -EIO; @@ -1475,11 +1482,16 @@ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) { + int retval; struct async *as; - if (!(as = async_getcompleted(ps))) - return -EAGAIN; - return processcompl_compat(as, (void __user * __user *)arg); + retval = -EAGAIN; + as = async_getcompleted(ps); + if (as) { + retval = processcompl_compat(as, (void __user * __user *)arg); + free_async(as); + } + return retval; } #endif From ea658ff1d6314ed206393dd23d2cd45b22f8f6b4 Mon Sep 17 00:00:00 2001 From: Jelle Martijn Kok Date: Wed, 10 Feb 2010 09:34:09 -0600 Subject: [PATCH 658/670] rtl8187: Add new device ID commit 174b24963eaf96dc5e093502ee09639aed13eb2f upstream. Add new RTL8187B device. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index ea49918a63de..9921147edc29 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -65,6 +65,7 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { /* Sitecom */ {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, + {USB_DEVICE(0x0df6, 0x0029), .driver_info = DEVICE_RTL8187B}, /* Sphairon Access Systems GmbH */ {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, /* Dick Smith Electronics */ From c51bfb22f31d384833e82a66872cccbab7c593df Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 29 Jan 2010 17:48:51 +0100 Subject: [PATCH 659/670] ACPI: Add NULL pointer check in acpi_bus_start commit d2f6650a950dadd20667a04a9dc785f240d43695 upstream. If acpi_bus_add does not return a device and it's passed to acpi_bus_start, bad things will happen: BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 IP: [] acpi_bus_start+0x14/0x24 ... [] acpiphp_bus_add+0xba/0x130 [acpiphp] [] enable_device+0x132/0x2ff [acpiphp] [] acpiphp_enable_slot+0xb8/0x130 [acpiphp] [] handle_hotplug_event_func+0x87/0x190 [acpiphp] Next patch would make this NULL pointer check obsolete, but better having one more than one missing... Signed-off-by: Thomas Renninger Acked-by: Bjorn Helgaas Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/scan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 14a7481c97d7..0b09703f06fc 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1357,6 +1357,9 @@ int acpi_bus_start(struct acpi_device *device) { struct acpi_bus_ops ops; + if (!device) + return -EINVAL; + memset(&ops, 0, sizeof(ops)); ops.acpi_op_start = 1; From 498a84db834a62eef2e5cb2fb85d051c39f89fff Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 27 Jan 2010 15:25:39 -0800 Subject: [PATCH 660/670] ACPI: fix High cpu temperature with 2.6.32 commit 370d5cd88509b93b76eb2f5f97efbd71c25061cb upstream. Since the rewrite of the CPU idle governor in 2.6.32, two laptops have surfaced where the BIOS advertises a C2 power state, but for some reason this state is not functioning (as verified in both cases by powertop before the patch in .32). The old governor had the accidental behavior that if a non-working state was chosen too many times, it would end up falling back to C1. The new governor works differently and this accidental behavior is no longer there; the result is a high temperature on these two machines. This patch adds these 2 machines to the DMI table for C state anomalies; by just not using C2 both these machines are better off (the TSC can be used instead of the pm timer, giving a performance boost for example). Addresses http://bugzilla.kernel.org/show_bug.cgi?id=14742 Signed-off-by: Arjan van de Ven Reported-by: Signed-off-by: Andrew Morton Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/processor_idle.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index a8f3ca6f2e1f..d9f78f6cbda3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -110,6 +110,14 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, (void *)2}, + { set_max_cstate, "Pavilion zv5000", { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME,"Pavilion zv5000 (DS502A#ABA)")}, + (void *)1}, + { set_max_cstate, "Asus L8400B", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")}, + (void *)1}, {}, }; From 2acc8d9f806fad17c81c91b3266775b78894f252 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 31 Jan 2010 07:07:14 +1000 Subject: [PATCH 661/670] drm/radeon/kms: use udelay for short delays commit 01d4503968f471f876fb44335800d2cf8dc5a2ce upstream. For usec delays use udelay instead of scheduling, this should allow reclocking to happen faster. This also was the cause of reported 33s delays at bootup on certain systems. fixes: freedesktop.org bug 25506 Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/atom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index d67c42555ab9..fed2291139c1 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -607,7 +607,7 @@ static void atom_op_delay(atom_exec_context *ctx, int *ptr, int arg) uint8_t count = U8((*ptr)++); SDEBUG(" count: %d\n", count); if (arg == ATOM_UNIT_MICROSEC) - schedule_timeout_uninterruptible(usecs_to_jiffies(count)); + udelay(count); else schedule_timeout_uninterruptible(msecs_to_jiffies(count)); } From be6520201bc0c80ec869ec035607ace48a5f78c4 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 15 Feb 2010 12:19:53 -0500 Subject: [PATCH 662/670] NFS: Too many GETATTR and ACCESS calls after direct I/O commit 65d269538a1129495ac45a14a777cd11cfe881d8 upstream. The cached read and write paths initialize fattr->time_start in their setup procedures. The value of fattr->time_start is propagated to read_cache_jiffies by nfs_update_inode(). Subsequent calls to nfs_attribute_timeout() will then use a good time stamp when computing the attribute cache timeout, and squelch unneeded GETATTR calls. Since the direct I/O paths erroneously leave the inode's fattr->time_start field set to zero, read_cache_jiffies for that inode is set to zero after any direct read or write operation. This triggers an otw GETATTR or ACCESS call to update the file's attribute and access caches properly, even when the NFS READ or WRITE replies have usable post-op attributes. Make sure the direct read and write setup code performs the same fattr initialization as the cached I/O paths to prevent unnecessary GETATTR calls. This was likely introduced by commit 0e574af1 in 2.6.15, which appears to add new nfs_fattr_init() call sites in the cached read and write paths, but not in the equivalent places in fs/nfs/direct.c. A subsequent commit in the same series, 33801147, introduces the fattr->time_start field. Interestingly, the direct write reschedule path already has a call to nfs_fattr_init() in the right place. Reported-by: Quentin Barnes Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/nfs/direct.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index e1d415e97849..0d289823e856 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -342,6 +342,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, data->res.fattr = &data->fattr; data->res.eof = 0; data->res.count = bytes; + nfs_fattr_init(&data->fattr); msg.rpc_argp = &data->args; msg.rpc_resp = &data->res; @@ -575,6 +576,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) data->res.count = 0; data->res.fattr = &data->fattr; data->res.verf = &data->verf; + nfs_fattr_init(&data->fattr); NFS_PROTO(data->inode)->commit_setup(data, &msg); @@ -766,6 +768,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, data->res.fattr = &data->fattr; data->res.count = bytes; data->res.verf = &data->verf; + nfs_fattr_init(&data->fattr); task_setup_data.task = &data->task; task_setup_data.callback_data = data; From 081312e8c147a85df0f37dcc45d7e2fbaf79dfb2 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 4 Nov 2009 02:48:01 -0600 Subject: [PATCH 663/670] eCryptfs: Add getattr function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f8f484d1b6677dd5cd5e7e605db747e8c30bbd47 upstream. The i_blocks field of an eCryptfs inode cannot be trusted, but generic_fillattr() uses it to instantiate the blocks field of a stat() syscall when a filesystem doesn't implement its own getattr(). Users have noticed that the output of du is incorrect on newly created files. This patch creates ecryptfs_getattr() which calls into the lower filesystem's getattr() so that eCryptfs can use its kstat.blocks value after calling generic_fillattr(). It is important to note that the block count includes the eCryptfs metadata stored in the beginning of the lower file plus any padding used to fill an extent before encryption. https://bugs.launchpad.net/ecryptfs/+bug/390833 Reported-by: Dominic Sacré Signed-off-by: Tyler Hicks Cc: Tim Gardner Signed-off-by: Greg Kroah-Hartman --- fs/ecryptfs/inode.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 056fed62d0de..728f07ebc593 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -971,6 +971,21 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) return rc; } +int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat) +{ + struct kstat lower_stat; + int rc; + + rc = vfs_getattr(ecryptfs_dentry_to_lower_mnt(dentry), + ecryptfs_dentry_to_lower(dentry), &lower_stat); + if (!rc) { + generic_fillattr(dentry->d_inode, stat); + stat->blocks = lower_stat.blocks; + } + return rc; +} + int ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) @@ -1100,6 +1115,7 @@ const struct inode_operations ecryptfs_dir_iops = { const struct inode_operations ecryptfs_main_iops = { .permission = ecryptfs_permission, .setattr = ecryptfs_setattr, + .getattr = ecryptfs_getattr, .setxattr = ecryptfs_setxattr, .getxattr = ecryptfs_getxattr, .listxattr = ecryptfs_listxattr, From 51a53302d168c9c6089cb931acebfbc5a2e81a48 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 2 Feb 2010 10:08:19 -0600 Subject: [PATCH 664/670] b43: Fix throughput regression commit b6c3f5be7c6ac3375f44de4545c1ffe216b34022 upstream. Commit c7ab5ef9bcd281135c21b4732c9be779585181be entitled "b43: implement short slot and basic rate handling" reduced the transmit throughput for my BCM4311 device from 18 Mb/s to 0.7 Mb/s. The basic rate handling portion is OK, the problem is in the short slot handling. Prior to this change, the short slot enable/disable routines were never called. Experimentation showed that the critical part was changing the value at offset 0x0010 in the shared memory. This is supposed to contain the 802.11 Slot Time in usec, but if it is changed from its initial value of zero, performance is destroyed. On the other hand, changing the value in the MMIO register corresponding to the Interframe Slot Time increased performance from 18 to 22 Mb/s. A BCM4306/3 also shows dramatic improvement of the transmit rate from 5.3 to 19.0 Mb/s. Other changes in the patch include removal of the magic number for the MMIO register, and allowing the slot time to be set for any PHY operating in the 2.4 GHz band. Previously, the routine was executed only for G PHYs. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/main.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 660716214d49..0e6b15454d39 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -117,6 +117,7 @@ #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ #define B43_MMIO_RNG 0x65A +#define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */ #define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ #define B43_MMIO_IFSCTL_USE_EDCF 0x0004 #define B43_MMIO_POWERUP_DELAY 0x6A8 diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 098dda1a67c1..9ca253e40bd5 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -628,10 +628,17 @@ static void b43_upload_card_macaddress(struct b43_wldev *dev) static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time) { /* slot_time is in usec. */ - if (dev->phy.type != B43_PHYTYPE_G) + /* This test used to exit for all but a G PHY. */ + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) return; - b43_write16(dev, 0x684, 510 + slot_time); - b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time); + b43_write16(dev, B43_MMIO_IFSSLOT, 510 + slot_time); + /* Shared memory location 0x0010 is the slot time and should be + * set to slot_time; however, this register is initially 0 and changing + * the value adversely affects the transmit rate for BCM4311 + * devices. Until this behavior is unterstood, delete this step + * + * b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time); + */ } static void b43_short_slot_timing_enable(struct b43_wldev *dev) From 20f774c4adc1f0690b300103b3f046c79d82ed99 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 9 Feb 2010 10:07:00 +0530 Subject: [PATCH 665/670] ath9k: Fix sequence numbers for PAE frames commit 6c8afef551fef87a3bf24f8a74c69a7f2f72fc82 upstream. Currently, PAE frames are not assigned proper sequence numbers. Since sending PAE frames as part of aggregates breaks crupto with several APs, they are sent as normal MPDUs. Fix the seqeuence number issue by updating the frame with the internal sequence number. Tested-by: Felix Fietkau Signed-off-by: Sujith Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/xmit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2c6b06343333..9009bac9207d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1563,7 +1563,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); - if (conf_is_ht(&sc->hw->conf) && !is_pae(skb)) + if (conf_is_ht(&sc->hw->conf)) bf->bf_state.bf_type |= BUF_HT; bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); @@ -1648,7 +1648,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, goto tx_done; } - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && !is_pae(skb)) { /* * Try aggregation if it's a unicast data frame * and the destination is HT capable. From de30e10d0080bccca8fe56f8dcb75171fffdb695 Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Fri, 5 Feb 2010 01:21:03 +0100 Subject: [PATCH 666/670] mac80211: Fix probe request filtering in IBSS mode commit 0da780c269957783d341fc3559e6b4c9912af7b4 upstream. We only reply to probe request if either the requested SSID is the broadcast SSID or if the requested SSID matches our own SSID. This latter case was not properly handled since we were replying to different SSID with the same length as our own SSID. Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ibss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index fbffce90edbc..07600a6871a8 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -643,7 +643,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, } if (pos[1] != 0 && (pos[1] != ifibss->ssid_len || - !memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) { + memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) { /* Ignore ProbeReq for foreign SSID */ return; } From 98d7938431c181dea6a03f5f89b550f081ad6220 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 5 Feb 2010 11:40:00 -0800 Subject: [PATCH 667/670] iwlwifi: Fix to set correct ht configuration commit 098dfded5b1b09927995e89c6d689f85a0f53384 upstream. iwl_set_rxon_ht() only get called in iwl_post_associate(); which cause possible incorrect ht configuration. Adding the call in iwl_mac_config() if IEEE80211_CONF_CHANGE_CHANNEL flag is set to re-configure and send rxon command. Fixes http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2146 Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2dc928755454..0cd4ec40a7d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2645,6 +2645,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) priv->staging_rxon.flags = 0; + iwl_set_rxon_ht(priv, ht_conf); iwl_set_rxon_channel(priv, conf->channel); iwl_set_flags_for_band(priv, conf->channel->band); From 7607864c43f7d2559153179fabd9dc8ade6b70a0 Mon Sep 17 00:00:00 2001 From: Nikanth Karthikesan Date: Tue, 16 Feb 2010 18:42:47 +0000 Subject: [PATCH 668/670] dm stripe: avoid divide by zero with invalid stripe count commit 781248c1b50c776a9ef4be1130f84ced1cba42fe upstream. If a table containing zero as stripe count is passed into stripe_ctr the code attempts to divide by zero. This patch changes DM_TABLE_LOAD to return -EINVAL if the stripe count is zero. We now get the following error messages: device-mapper: table: 253:0: striped: Invalid stripe count device-mapper: ioctl: error adding target to table Signed-off-by: Nikanth Karthikesan Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-stripe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index e0efc1adcaff..bd58703ee8f6 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -110,7 +110,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) } stripes = simple_strtoul(argv[0], &end, 10); - if (*end) { + if (!stripes || *end) { ti->error = "Invalid stripe count"; return -EINVAL; } From c7f14122d1c633d5d6d9c999235d7f6778510b26 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Tue, 16 Feb 2010 18:42:53 +0000 Subject: [PATCH 669/670] dm log: userspace fix overhead_size calcuations commit ebfd32bba9b518d684009d9d21a56742337ca1b3 upstream. This patch fixes two bugs that revolve around the miscalculation and misuse of the variable 'overhead_size'. 'overhead_size' is the size of the various header structures used during communication. The first bug is the use of 'sizeof' with the pointer of a structure instead of the structure itself - resulting in the wrong size being computed. This is then used in a check to see if the payload (data_size) would be to large for the preallocated structure. Since the bug produces a smaller value for the overhead, it was possible for the structure to be breached. (Although the current users of the code do not currently send enough data to trigger this bug.) The second bug is that the 'overhead_size' value is used to compute how much of the preallocated space should be cleared before populating it with fresh data. This should have simply been 'sizeof(struct cn_msg)' not overhead_size. The fact that 'overhead_size' was computed incorrectly made this problem "less bad" - leaving only a pointer's worth of space at the end uncleared. Thus, this bug was never producing a bad result, but still needs to be fixed - especially now that the value is computed correctly. Signed-off-by: Jonathan Brassow Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-log-userspace-transfer.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c index 54abf9e303b7..f1c8cae70b4b 100644 --- a/drivers/md/dm-log-userspace-transfer.c +++ b/drivers/md/dm-log-userspace-transfer.c @@ -172,11 +172,15 @@ int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type, { int r = 0; size_t dummy = 0; - int overhead_size = - sizeof(struct dm_ulog_request *) + sizeof(struct cn_msg); + int overhead_size = sizeof(struct dm_ulog_request) + sizeof(struct cn_msg); struct dm_ulog_request *tfr = prealloced_ulog_tfr; struct receiving_pkg pkg; + /* + * Given the space needed to hold the 'struct cn_msg' and + * 'struct dm_ulog_request' - do we have enough payload + * space remaining? + */ if (data_size > (DM_ULOG_PREALLOCED_SIZE - overhead_size)) { DMINFO("Size of tfr exceeds preallocated size"); return -EINVAL; @@ -191,7 +195,7 @@ int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type, */ mutex_lock(&dm_ulog_lock); - memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - overhead_size); + memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - sizeof(struct cn_msg)); memcpy(tfr->uuid, uuid, DM_UUID_LEN); tfr->luid = luid; tfr->seq = dm_ulog_seq++; From 7f5e918e62cbc9ac27c2f47d3c3dd4b86f67ff0e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Feb 2010 07:38:51 -0800 Subject: [PATCH 670/670] Linux 2.6.32.9 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f282cab90dc4..ec932b2155b5 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 -EXTRAVERSION = .8 +EXTRAVERSION = .9 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION*