From d0cd5d482b8a6dc92c6c69a5387baf72ea84f23a Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 14 Nov 2011 17:51:39 -0800 Subject: [PATCH 001/380] xhci: Fix USB 3.0 device restart on resume. The xHCI hub port code gets passed a zero-based port number by the USB core. It then adds one to in order to find a device slot by port number and device speed by calling xhci_find_slot_id_by_port. That function clearly states it requires a one-based port number. The xHCI port status change event handler was using a zero-based port number that it got from find_faked_portnum_from_hw_portnum, not a one-based port number. This lead to the doorbells never being rung for a device after a resume, or worse, a different device with the same speed having its doorbell rung (which could lead to bad power management in the xHCI host controller). This patch should be backported to kernels as old as 2.6.39. Signed-off-by: Sarah Sharp Acked-by: Andiry Xu Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-ring.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b90e1386418b..5a818cbbab44 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1204,6 +1204,7 @@ static void handle_vendor_event(struct xhci_hcd *xhci, * * Returns a zero-based port number, which is suitable for indexing into each of * the split roothubs' port arrays and bus state arrays. + * Add one to it in order to call xhci_find_slot_id_by_port. */ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd, struct xhci_hcd *xhci, u32 port_id) @@ -1324,7 +1325,7 @@ static void handle_port_status(struct xhci_hcd *xhci, xhci_set_link_state(xhci, port_array, faked_port_index, XDEV_U0); slot_id = xhci_find_slot_id_by_port(hcd, xhci, - faked_port_index); + faked_port_index + 1); if (!slot_id) { xhci_dbg(xhci, "slot_id is zero\n"); goto cleanup; From 12183a20a8baf009bf570ab3db45a27fd6b1fd03 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 21 Dec 2011 23:01:20 +0100 Subject: [PATCH 002/380] mtd: nand: fix typo in comment Funny one :) "Heck" fits somehow, too, but I am sure it was meant to be "Check". Signed-off-by: Wolfram Sang Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/nand/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 35b4565050f1..8a393f9e6027 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2588,7 +2588,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, instr->state = MTD_ERASING; while (len) { - /* Heck if we have a bad block, we do not erase bad blocks! */ + /* Check if we have a bad block, we do not erase bad blocks! */ if (nand_block_checkbad(mtd, ((loff_t) page) << chip->page_shift, 0, allowbbt)) { pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", From 9398d1ce09b9009996f7d2468e1d3c785fa6feda Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 4 Jan 2012 11:18:46 +0800 Subject: [PATCH 003/380] mtd: gpmi-nand bugfix: reset the BCH module when it is not MX23 In MX28, if we do not reset the BCH module. The BCH module may becomes unstable when the board reboots for several thousands times. This bug has been catched in customer's production. The patch adds some comments (some from Wolfram Sang), and fixes it now. Also change gpmi_reset_block() to static. Signed-off-by: Huang Shijie Acked-by: Marek Vasut Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Cc: stable@kernel.org [3.1+] --- drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 2a56fc6f399a..c56f8e021b90 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask) * [1] enable the module. * [2] reset the module. * - * In most of the cases, it's ok. But there is a hardware bug in the BCH block. + * In most of the cases, it's ok. + * But in MX23, there is a hardware bug in the BCH block (see erratum #2847). * If you try to soft reset the BCH block, it becomes unusable until * the next hard reset. This case occurs in the NAND boot mode. When the board * boots by NAND, the ROM of the chip will initialize the BCH blocks itself. * So If the driver tries to reset the BCH again, the BCH will not work anymore. - * You will see a DMA timeout in this case. + * You will see a DMA timeout in this case. The bug has been fixed + * in the following chips, such as MX28. * * To avoid this bug, just add a new parameter `just_enable` for * the mxs_reset_block(), and rewrite it here. */ -int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) +static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) { int ret; int timeout = 0x400; @@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this) if (ret) goto err_out; - ret = gpmi_reset_block(r->bch_regs, true); + /* + * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this + * chip, otherwise it will lock up. So we skip resetting BCH on the MX23. + * On the other hand, the MX28 needs the reset, because one case has been + * seen where the BCH produced ECC errors constantly after 10000 + * consecutive reboots. The latter case has not been seen on the MX23 yet, + * still we don't know if it could happen there as well. + */ + ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); if (ret) goto err_out; From bce41d601e58af12cee1398fe836e6b9a8fb5396 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 10 Jan 2012 15:32:29 +0200 Subject: [PATCH 004/380] jffs2: do not initialize variable unnecessarily Remove unnecessary initializer for a local variable. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- fs/jffs2/erase.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a01cdad6aad1..eafb8d37a6fb 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -335,7 +335,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl void *ebuf; uint32_t ofs; size_t retlen; - int ret = -EIO; + int ret; unsigned long *wordebuf; ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen, From 48cfe37cc03f616e6c139796962e7ec677cde8a9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 21 Dec 2011 14:20:23 -0500 Subject: [PATCH 005/380] target: don't allocate bio headroom in iblock We never embedd the bio into a structure, so there is no need to allocate 64 bytes of headroom per bio. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_iblock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index cc8e6b58ef20..628e877381d8 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -129,7 +129,7 @@ static struct se_device *iblock_create_virtdevice( /* * These settings need to be made tunable.. */ - ib_dev->ibd_bio_set = bioset_create(32, 64); + ib_dev->ibd_bio_set = bioset_create(32, 0); if (!ib_dev->ibd_bio_set) { pr_err("IBLOCK: Unable to create bioset()\n"); return ERR_PTR(-ENOMEM); From 9e08e34e3735ae057eb3834da3570995811b7eb9 Mon Sep 17 00:00:00 2001 From: Marco Sanvido Date: Tue, 3 Jan 2012 17:12:57 -0800 Subject: [PATCH 006/380] target: Use correct preempted registration sense code The comments quote the right parts of the spec: * d) Establish a unit attention condition for the * initiator port associated with every I_T nexus * that lost its registration other than the I_T * nexus on which the PERSISTENT RESERVE OUT command * was received, with the additional sense code set * to REGISTRATIONS PREEMPTED. and * e) Establish a unit attention condition for the initiator * port associated with every I_T nexus that lost its * persistent reservation and/or registration, with the * additional sense code set to REGISTRATIONS PREEMPTED; but the actual code accidentally uses ASCQ_2AH_RESERVATIONS_PREEMPTED instead of ASCQ_2AH_REGISTRATIONS_PREEMPTED. Fix this. Signed-off-by: Marco Sanvido Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 429ad7291664..d14860ff2508 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3120,7 +3120,7 @@ static int core_scsi3_pro_preempt( if (!calling_it_nexus) core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A, - ASCQ_2AH_RESERVATIONS_PREEMPTED); + ASCQ_2AH_REGISTRATIONS_PREEMPTED); } spin_unlock(&pr_tmpl->registration_lock); /* @@ -3233,7 +3233,7 @@ static int core_scsi3_pro_preempt( * additional sense code set to REGISTRATIONS PREEMPTED; */ core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A, - ASCQ_2AH_RESERVATIONS_PREEMPTED); + ASCQ_2AH_REGISTRATIONS_PREEMPTED); } spin_unlock(&pr_tmpl->registration_lock); /* From 6816966a8418b980481b4dced7eddd1796b145e8 Mon Sep 17 00:00:00 2001 From: Marco Sanvido Date: Tue, 3 Jan 2012 17:12:58 -0800 Subject: [PATCH 007/380] target: Allow PERSISTENT RESERVE IN for non-reservation holder Initiators that aren't the active reservation holder should be able to do a PERSISTENT RESERVE IN command in all cases, so add it to the list of allowed CDBs in core_scsi3_pr_seq_non_holder(). Signed-off-by: Marco Sanvido Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index d14860ff2508..68c71cd7a88e 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -478,6 +478,7 @@ static int core_scsi3_pr_seq_non_holder( case READ_MEDIA_SERIAL_NUMBER: case REPORT_LUNS: case REQUEST_SENSE: + case PERSISTENT_RESERVE_IN: ret = 0; /*/ Allowed CDBs */ break; default: From 9db9da332250dbe662995703a4dcdd692112f0c3 Mon Sep 17 00:00:00 2001 From: "roland@purestorage.com" Date: Wed, 4 Jan 2012 15:59:58 -0800 Subject: [PATCH 008/380] target: Don't zero pages used for data buffers Doing alloc_page(GFP_KERNEL | __GFP_ZERO) to get pages used for data buffers wastes a lot of CPU clearing pages that will be quickly be overwritten by the actual data. However, for emulated control commands such as INQUIRY and so on, the code does assume that the buffer is zeroed. To avoid this CPU overhead, skip the __GFP_ZERO for commands that are actually moving data, ie cmds that have SCF_SCSI_DATA_SG_IO_CDB set. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d3ddd1361949..289bc0f125f9 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3516,6 +3516,7 @@ transport_generic_get_mem(struct se_cmd *cmd) u32 length = cmd->data_length; unsigned int nents; struct page *page; + gfp_t zero_flag; int i = 0; nents = DIV_ROUND_UP(length, PAGE_SIZE); @@ -3526,9 +3527,11 @@ transport_generic_get_mem(struct se_cmd *cmd) cmd->t_data_nents = nents; sg_init_table(cmd->t_data_sg, nents); + zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO; + while (length) { u32 page_len = min_t(u32, length, PAGE_SIZE); - page = alloc_page(GFP_KERNEL | __GFP_ZERO); + page = alloc_page(GFP_KERNEL | zero_flag); if (!page) goto out; From 9fbc8909876a2160044e71d376848973b9bfdc3f Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 9 Jan 2012 17:54:00 -0800 Subject: [PATCH 009/380] target: Correct sense key for INVALID FIELD IN {PARAMETER LIST,CDB} According to SPC-4, the sense key for commands that are failed with INVALID FIELD IN PARAMETER LIST and INVALID FIELD IN CDB should be ILLEGAL REQUEST (5h) rather than ABORTED COMMAND (Bh). Without this patch, a tcm_loop LUN incorrectly gives: # sg_raw -r 1 -v /dev/sda 3 1 0 0 ff 0 Sense Information: Fixed format, current; Sense key: Aborted Command Additional sense: Invalid field in cdb Raw sense data (in hex): 70 00 0b 00 00 00 00 0a 00 00 00 00 24 00 00 00 00 00 While a real SCSI disk gives: Sense Information: Fixed format, current; Sense key: Illegal Request Additional sense: Invalid field in cdb Raw sense data (in hex): 70 00 05 00 00 00 00 18 00 00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 with the main point being that the real disk gives a sense key of ILLEGAL REQUEST (5h). Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 289bc0f125f9..2869fb7d2c05 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -4451,8 +4451,8 @@ int transport_send_check_condition_and_sense( /* CURRENT ERROR */ buffer[offset] = 0x70; buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ABORTED COMMAND */ - buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; + /* ILLEGAL REQUEST */ + buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; /* INVALID FIELD IN CDB */ buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24; break; @@ -4460,8 +4460,8 @@ int transport_send_check_condition_and_sense( /* CURRENT ERROR */ buffer[offset] = 0x70; buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ABORTED COMMAND */ - buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; + /* ILLEGAL REQUEST */ + buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; /* INVALID FIELD IN PARAMETER LIST */ buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26; break; From 91ec1d3535b2acf12c599045cc19ad9be3c6a47b Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 13 Jan 2012 12:01:34 -0800 Subject: [PATCH 010/380] target: Add workaround for zero-length control CDB handling This patch adds a work-around for handling zero allocation length control CDBs (type SCF_SCSI_CONTROL_SG_IO_CDB) that was causing an OOPs with the following raw calls: # sg_raw -v /dev/sdd 3 0 0 0 0 0 # sg_raw -v /dev/sdd 0x1a 0 1 0 0 0 This patch will follow existing zero-length handling for data I/O and silently return with GOOD status. This addresses the zero length issue, but the proper long-term resolution for handling arbitary allocation lengths will be to refactor out data-phase handling in individual CDB emulation logic within target_core_cdb.c Reported-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 2869fb7d2c05..50d6911d4120 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3759,6 +3759,11 @@ transport_allocate_control_task(struct se_cmd *cmd) struct se_task *task; unsigned long flags; + /* Workaround for handling zero-length control CDBs */ + if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && + !cmd->data_length) + return 0; + task = transport_generic_get_task(cmd, cmd->data_direction); if (!task) return -ENOMEM; @@ -3830,6 +3835,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd) else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) { cmd->t_state = TRANSPORT_COMPLETE; atomic_set(&cmd->t_transport_active, 1); + + if (cmd->t_task_cdb[0] == REQUEST_SENSE) { + u8 ua_asc = 0, ua_ascq = 0; + + core_scsi3_ua_clear_for_request_sense(cmd, + &ua_asc, &ua_ascq); + } + INIT_WORK(&cmd->work, target_complete_ok_work); queue_work(target_completion_wq, &cmd->work); return 0; From e59a41b69a8e116d5ac8c95c4222f5a971f66bbd Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 10 Jan 2012 14:16:57 +0100 Subject: [PATCH 011/380] target: avoid multiple outputs in scsi_dump_inquiry() The multiple calls to pr_debug() each with one letter results in a new line. This patch merges the multiple requests into one call per line so we don't have the multiple line cuts. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 50d6911d4120..e186f7db3860 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1255,32 +1255,34 @@ static void core_setup_task_attr_emulation(struct se_device *dev) static void scsi_dump_inquiry(struct se_device *dev) { struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn; + char buf[17]; int i, device_type; /* * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer */ - pr_debug(" Vendor: "); for (i = 0; i < 8; i++) if (wwn->vendor[i] >= 0x20) - pr_debug("%c", wwn->vendor[i]); + buf[i] = wwn->vendor[i]; else - pr_debug(" "); + buf[i] = ' '; + buf[i] = '\0'; + pr_debug(" Vendor: %s\n", buf); - pr_debug(" Model: "); for (i = 0; i < 16; i++) if (wwn->model[i] >= 0x20) - pr_debug("%c", wwn->model[i]); + buf[i] = wwn->model[i]; else - pr_debug(" "); + buf[i] = ' '; + buf[i] = '\0'; + pr_debug(" Model: %s\n", buf); - pr_debug(" Revision: "); for (i = 0; i < 4; i++) if (wwn->revision[i] >= 0x20) - pr_debug("%c", wwn->revision[i]); + buf[i] = wwn->revision[i]; else - pr_debug(" "); - - pr_debug("\n"); + buf[i] = ' '; + buf[i] = '\0'; + pr_debug(" Revision: %s\n", buf); device_type = dev->transport->get_device_type(dev); pr_debug(" Type: %s ", scsi_device_type(device_type)); From 1dd0a0674530da61cdbfadd88c96949b483a7c19 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 10 Jan 2012 14:16:58 +0100 Subject: [PATCH 012/380] target: use save/restore lock primitive in core_dec_lacl_count() It may happen that uasp will free the request in irq conntext, the callchain: uasp_cmd_release() -> transport_generic_free_cmd() -> core_dec_lacl_count() where the last function enables the IRQ. Those irqs are re-disabled later (due to the spin.*irq_restore) but in between we could get hurt. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 0c5992f0d946..00159a4e781f 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -320,11 +320,12 @@ int core_free_device_list_for_node( void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd) { struct se_dev_entry *deve; + unsigned long flags; - spin_lock_irq(&se_nacl->device_list_lock); + spin_lock_irqsave(&se_nacl->device_list_lock, flags); deve = &se_nacl->device_list[se_cmd->orig_fe_lun]; deve->deve_cmds--; - spin_unlock_irq(&se_nacl->device_list_lock); + spin_unlock_irqrestore(&se_nacl->device_list_lock, flags); } void core_update_device_list_access( From 8d9efe539cf78f6a90947d47100e4a86d907750f Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 11 Jan 2012 21:43:38 +0100 Subject: [PATCH 013/380] target: fix return code of core_tpg_.*_lun - core_tpg_pre_addlun() returns always ERR_PTR() or the pointer, never NULL. The additional check for NULL in core_dev_add_lun() is not required. - core_tpg_pre_dellun() returns always ERR_PTR() or the pointer, never NULL. The check for NULL in core_dev_del_lun() is wrong. The third argument (int *) is never used, remove it. - core_dev_add_lun() returns always NULL or the pointer, never ERR_PTR. The check for IS_ERR() is not required. (nab: Convert core_dev_add_lun() use err.h macros for failure handling to be consistent with the rest of target_core_fabric_configfs.c callers) Signed-off-by: Sebastian Andrzej Siewior Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 19 ++++++++++--------- drivers/target/target_core_fabric_configfs.c | 4 ++-- drivers/target/target_core_internal.h | 2 +- drivers/target/target_core_tpg.c | 3 +-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 00159a4e781f..de5f4fea7f62 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1295,24 +1295,26 @@ struct se_lun *core_dev_add_lun( { struct se_lun *lun_p; u32 lun_access = 0; + int rc; if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) { pr_err("Unable to export struct se_device while dev_access_obj: %d\n", atomic_read(&dev->dev_access_obj.obj_access_count)); - return NULL; + return ERR_PTR(-EACCES); } lun_p = core_tpg_pre_addlun(tpg, lun); - if ((IS_ERR(lun_p)) || !lun_p) - return NULL; + if (IS_ERR(lun_p)) + return lun_p; if (dev->dev_flags & DF_READ_ONLY) lun_access = TRANSPORT_LUNFLAGS_READ_ONLY; else lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; - if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0) - return NULL; + rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev); + if (rc < 0) + return ERR_PTR(rc); pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from" " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(), @@ -1349,11 +1351,10 @@ int core_dev_del_lun( u32 unpacked_lun) { struct se_lun *lun; - int ret = 0; - lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret); - if (!lun) - return ret; + lun = core_tpg_pre_dellun(tpg, unpacked_lun); + if (IS_ERR(lun)) + return PTR_ERR(lun); core_tpg_post_dellun(tpg, lun); diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 4f77cce22646..9a2ce11e1a6e 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -766,9 +766,9 @@ static int target_fabric_port_link( lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev, lun->unpacked_lun); - if (IS_ERR(lun_p) || !lun_p) { + if (IS_ERR(lun_p)) { pr_err("core_dev_add_lun() failed\n"); - ret = -EINVAL; + ret = PTR_ERR(lun_p); goto out; } diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 26f135e94f6e..45001364788a 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -90,7 +90,7 @@ void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *); struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32); int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *, u32, void *); -struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32, int *); +struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun); int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *); /* target_core_transport.c */ diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index b7668029bb31..06336ecd872d 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -807,8 +807,7 @@ static void core_tpg_shutdown_lun( struct se_lun *core_tpg_pre_dellun( struct se_portal_group *tpg, - u32 unpacked_lun, - int *ret) + u32 unpacked_lun) { struct se_lun *lun; From c1ce4bd56f2846de55043374598fd929ad3b711b Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 16 Jan 2012 16:04:15 -0800 Subject: [PATCH 014/380] iscsi-target: Fix reject release handling in iscsit_free_cmd() This patch addresses a bug where iscsit_free_cmd() was incorrectly calling iscsit_release_cmd() for ISCSI_OP_REJECT because iscsi_add_reject*() will overwrite the original iscsi_cmd->iscsi_opcode assignment. This bug was introduced with the following commit: commit 0be67f2ed8f577d2c72d917928394c5885fa9134 Author: Nicholas Bellinger Date: Sun Oct 9 01:48:14 2011 -0700 iscsi-target: Remove SCF_SE_LUN_CMD flag abuses and was manifesting itself as list corruption with the following: [ 131.191092] ------------[ cut here ]------------ [ 131.191092] WARNING: at lib/list_debug.c:53 __list_del_entry+0x8d/0x98() [ 131.191092] Hardware name: VMware Virtual Platform [ 131.191092] list_del corruption. prev->next should be ffff880022d3c100, but was 6b6b6b6b6b6b6b6b [ 131.191092] Modules linked in: tcm_vhost ib_srpt ib_cm ib_sa ib_mad ib_core tcm_qla2xxx qla2xxx tcm_loop tcm_fc libfc scsi_transport_fc crc32c iscsi_target_mod target_core_stgt scsi_tgt target_core_pscsi target_core_file target_core_iblock target_core_mod configfs ipv6 iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi sr_mod cdrom sd_mod e1000 ata_piix libata mptspi mptscsih mptbase [last unloaded: scsi_wait_scan] [ 131.191092] Pid: 2250, comm: iscsi_ttx Tainted: G W 3.2.0-rc4+ #42 [ 131.191092] Call Trace: [ 131.191092] [] warn_slowpath_common+0x80/0x98 [ 131.191092] [] warn_slowpath_fmt+0x41/0x43 [ 131.191092] [] __list_del_entry+0x8d/0x98 [ 131.191092] [] transport_lun_remove_cmd+0x9b/0xb7 [target_core_mod] [ 131.191092] [] transport_generic_free_cmd+0x5d/0x71 [target_core_mod] [ 131.191092] [] iscsit_free_cmd+0x1e/0x27 [iscsi_target_mod] [ 131.191092] [] iscsit_close_connection+0x14d/0x5b2 [iscsi_target_mod] [ 131.191092] [] iscsit_take_action_for_connection_exit+0xdb/0xe0 [iscsi_target_mod] [ 131.191092] [] iscsi_target_tx_thread+0x15cb/0x1608 [iscsi_target_mod] [ 131.191092] [] ? check_preempt_wakeup+0x121/0x185 [ 131.191092] [] ? __dequeue_entity+0x2e/0x33 [ 131.191092] [] ? iscsit_send_text_rsp+0x25f/0x25f [iscsi_target_mod] [ 131.191092] [] ? iscsit_send_text_rsp+0x25f/0x25f [iscsi_target_mod] [ 131.191092] [] ? schedule+0x55/0x57 [ 131.191092] [] kthread+0x7d/0x85 [ 131.191092] [] kernel_thread_helper+0x4/0x10 [ 131.191092] [] ? kthread_worker_fn+0x16d/0x16d [ 131.191092] [] ? gs_change+0x13/0x13 Reported-by: Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_util.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index a05ca1c4f01c..11287e1ece13 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -849,6 +849,17 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd) case ISCSI_OP_SCSI_TMFUNC: transport_generic_free_cmd(&cmd->se_cmd, 1); break; + case ISCSI_OP_REJECT: + /* + * Handle special case for REJECT when iscsi_add_reject*() has + * overwritten the original iscsi_opcode assignment, and the + * associated cmd->se_cmd needs to be released. + */ + if (cmd->se_cmd.se_tfo != NULL) { + transport_generic_free_cmd(&cmd->se_cmd, 1); + break; + } + /* Fall-through */ default: iscsit_release_cmd(cmd); break; From cd931ee62fd0258fc85c76a7c5499fe85e0f3436 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 16 Jan 2012 17:11:54 -0800 Subject: [PATCH 015/380] iscsi-target: Fix double list_add with iscsit_alloc_buffs reject This patch fixes a bug where the iscsit_add_reject_from_cmd() call from a failure to iscsit_alloc_buffs() was incorrectly passing add_to_conn=1 and causing a double list_add after iscsi_cmd->i_list had already been added in iscsit_handle_scsi_cmd(). Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index ac44af165b27..6e070e0a8393 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1061,7 +1061,7 @@ attach_cmd: if (ret < 0) return iscsit_add_reject_from_cmd( ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + 1, 0, buf, cmd); /* * Check the CmdSN against ExpCmdSN/MaxCmdSN here if * the Immediate Bit is not set, and no Immediate From f8d48ae52eeec906d7fb42485eb26a5d305bab0a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 15 Jan 2012 14:30:24 +0300 Subject: [PATCH 016/380] iscsi-target: make one-bit bitfields unsigned Signed bitfields are a problem because instead of being 1 or 0 like you'd expect they are 0 and -1. It doesn't cause a problem in this case but sparse complains: drivers/target/iscsi/iscsi_target_core.h:564:56: error: dubious one-bit signed bitfield Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index f1a02dad05a0..ebf81fdbb5c5 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -561,8 +561,8 @@ struct iscsi_conn { struct hash_desc conn_tx_hash; /* Used for scheduling TX and RX connection kthreads */ cpumask_var_t conn_cpumask; - int conn_rx_reset_cpumask:1; - int conn_tx_reset_cpumask:1; + unsigned int conn_rx_reset_cpumask:1; + unsigned int conn_tx_reset_cpumask:1; /* list_head of struct iscsi_cmd for this connection */ struct list_head conn_cmd_list; struct list_head immed_queue_list; From e8904dc5008ef92f0f62391d6557f03f921eeb32 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 15 Jan 2012 19:33:30 +0100 Subject: [PATCH 017/380] iscsi-target: Fix up a few assignments A statement such as struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); has undefined behaviour since there are two assignments to 'na', strictly speaking (the order in which side-effects from the assignments take place is undefined since there's no intervening sequence point), and it looks unintentional in any case. Signed-off-by: Jesper Juhl Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_erl1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 255c0d67e898..27901e37c125 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -1238,7 +1238,7 @@ void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd) { struct iscsi_conn *conn = cmd->conn; struct iscsi_session *sess = conn->sess; - struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); + struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess); spin_lock_bh(&cmd->dataout_timeout_lock); if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) { @@ -1261,7 +1261,7 @@ void iscsit_start_dataout_timer( struct iscsi_conn *conn) { struct iscsi_session *sess = conn->sess; - struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); + struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess); if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING) return; From 4949314c7283ea4f9ade182ca599583b89f7edd6 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Mon, 16 Jan 2012 16:57:08 -0800 Subject: [PATCH 018/380] target: Allow control CDBs with data > 1 page We need to handle >1 page control cdbs, so extend the code to do a vmap if bigger than 1 page. It seems like kmap() is still preferable if just a page, fewer TLB shootdowns(?), so keep using that when possible. Rename function pair for their new scope. Signed-off-by: Andy Grover Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_alua.c | 8 ++--- drivers/target/target_core_cdb.c | 28 +++++++-------- drivers/target/target_core_device.c | 4 +-- drivers/target/target_core_pr.c | 38 ++++++++++---------- drivers/target/target_core_pscsi.c | 4 +-- drivers/target/target_core_transport.c | 49 +++++++++++++++++++------- include/target/target_core_backend.h | 4 +-- include/target/target_core_base.h | 1 + 8 files changed, 80 insertions(+), 56 deletions(-) diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 1b1edd14f4bf..01a2691dfb47 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -78,7 +78,7 @@ int target_emulate_report_target_port_groups(struct se_task *task) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, @@ -163,7 +163,7 @@ int target_emulate_report_target_port_groups(struct se_task *task) buf[2] = ((rd_len >> 8) & 0xff); buf[3] = (rd_len & 0xff); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); @@ -194,7 +194,7 @@ int target_emulate_set_target_port_groups(struct se_task *task) cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); /* * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed @@ -351,7 +351,7 @@ int target_emulate_set_target_port_groups(struct se_task *task) } out: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); return 0; diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 2f2235edefff..07a3025d0622 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -83,7 +83,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); if (dev == tpg->tpg_virt_lun0.lun_se_dev) { buf[0] = 0x3f; /* Not connected */ @@ -134,7 +134,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd) buf[4] = 31; /* Set additional length to 31 */ out: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } @@ -716,7 +716,7 @@ int target_emulate_inquiry(struct se_task *task) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = dev->transport->get_device_type(dev); @@ -733,7 +733,7 @@ int target_emulate_inquiry(struct se_task *task) ret = -EINVAL; out_unmap: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); out: if (!ret) { task->task_scsi_status = GOOD; @@ -755,7 +755,7 @@ int target_emulate_readcapacity(struct se_task *task) else blocks = (u32)blocks_long; - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = (blocks >> 24) & 0xff; buf[1] = (blocks >> 16) & 0xff; @@ -771,7 +771,7 @@ int target_emulate_readcapacity(struct se_task *task) if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) put_unaligned_be32(0xFFFFFFFF, &buf[0]); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); @@ -785,7 +785,7 @@ int target_emulate_readcapacity_16(struct se_task *task) unsigned char *buf; unsigned long long blocks = dev->transport->get_blocks(dev); - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = (blocks >> 56) & 0xff; buf[1] = (blocks >> 48) & 0xff; @@ -806,7 +806,7 @@ int target_emulate_readcapacity_16(struct se_task *task) if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) buf[14] = 0x80; - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); @@ -1019,9 +1019,9 @@ int target_emulate_modesense(struct se_task *task) offset = cmd->data_length; } - rbuf = transport_kmap_first_data_page(cmd); + rbuf = transport_kmap_data_sg(cmd); memcpy(rbuf, buf, offset); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); @@ -1043,7 +1043,7 @@ int target_emulate_request_sense(struct se_task *task) return -ENOSYS; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { /* @@ -1089,7 +1089,7 @@ int target_emulate_request_sense(struct se_task *task) } end: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); return 0; @@ -1123,7 +1123,7 @@ int target_emulate_unmap(struct se_task *task) dl = get_unaligned_be16(&cdb[0]); bd_dl = get_unaligned_be16(&cdb[2]); - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); ptr = &buf[offset]; pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" @@ -1147,7 +1147,7 @@ int target_emulate_unmap(struct se_task *task) } err: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); if (!ret) { task->task_scsi_status = GOOD; transport_complete_task(task, 1); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index de5f4fea7f62..edbcabbf85f7 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -657,7 +657,7 @@ int target_report_luns(struct se_task *se_task) unsigned char *buf; u32 cdb_offset = 0, lun_count = 0, offset = 8, i; - buf = transport_kmap_first_data_page(se_cmd); + buf = (unsigned char *) transport_kmap_data_sg(se_cmd); /* * If no struct se_session pointer is present, this struct se_cmd is @@ -695,7 +695,7 @@ int target_report_luns(struct se_task *se_task) * See SPC3 r07, page 159. */ done: - transport_kunmap_first_data_page(se_cmd); + transport_kunmap_data_sg(se_cmd); lun_count *= 8; buf[0] = ((lun_count >> 24) & 0xff); buf[1] = ((lun_count >> 16) & 0xff); diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 68c71cd7a88e..b7c779389eea 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1535,7 +1535,7 @@ static int core_scsi3_decode_spec_i_port( tidh_new->dest_local_nexus = 1; list_add_tail(&tidh_new->dest_list, &tid_dest_list); - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); /* * For a PERSISTENT RESERVE OUT specify initiator ports payload, * first extract TransportID Parameter Data Length, and make sure @@ -1786,7 +1786,7 @@ static int core_scsi3_decode_spec_i_port( } - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); /* * Go ahead and create a registrations from tid_dest_list for the @@ -1834,7 +1834,7 @@ static int core_scsi3_decode_spec_i_port( return 0; out: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); /* * For the failure case, release everything from tid_dest_list * including *dest_pr_reg and the configfs dependances.. @@ -3411,14 +3411,14 @@ static int core_scsi3_emulate_pro_register_and_move( * will be moved to for the TransportID containing SCSI initiator WWN * information. */ - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); rtpi = (buf[18] & 0xff) << 8; rtpi |= buf[19] & 0xff; tid_len = (buf[20] & 0xff) << 24; tid_len |= (buf[21] & 0xff) << 16; tid_len |= (buf[22] & 0xff) << 8; tid_len |= buf[23] & 0xff; - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); buf = NULL; if ((tid_len + 24) != cmd->data_length) { @@ -3470,7 +3470,7 @@ static int core_scsi3_emulate_pro_register_and_move( return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); proto_ident = (buf[24] & 0x0f); #if 0 pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" @@ -3504,7 +3504,7 @@ static int core_scsi3_emulate_pro_register_and_move( goto out; } - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); buf = NULL; pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s" @@ -3769,13 +3769,13 @@ after_iport_check: " REGISTER_AND_MOVE\n"); } - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); core_scsi3_put_pr_reg(dest_pr_reg); return 0; out: if (buf) - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); if (dest_se_deve) core_scsi3_lunacl_undepend_item(dest_se_deve); if (dest_node_acl) @@ -3849,7 +3849,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task) scope = (cdb[2] & 0xf0); type = (cdb[2] & 0x0f); - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); /* * From PERSISTENT_RESERVE_OUT parameter list (payload) */ @@ -3867,7 +3867,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task) aptpl = (buf[17] & 0x01); unreg = (buf[17] & 0x02); } - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); buf = NULL; /* @@ -3967,7 +3967,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); @@ -4001,7 +4001,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) buf[6] = ((add_len >> 8) & 0xff); buf[7] = (add_len & 0xff); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } @@ -4027,7 +4027,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); @@ -4086,7 +4086,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) err: spin_unlock(&se_dev->dev_reservation_lock); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } @@ -4110,7 +4110,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = ((add_len << 8) & 0xff); buf[1] = (add_len & 0xff); @@ -4142,7 +4142,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */ buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } @@ -4172,7 +4172,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); @@ -4293,7 +4293,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) buf[6] = ((add_len >> 8) & 0xff); buf[7] = (add_len & 0xff); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index d35467d42e12..8d4def30e9e8 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -693,7 +693,7 @@ static int pscsi_transport_complete(struct se_task *task) if (task->task_se_cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { - unsigned char *buf = transport_kmap_first_data_page(task->task_se_cmd); + unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd); if (cdb[0] == MODE_SENSE_10) { if (!(buf[3] & 0x80)) @@ -703,7 +703,7 @@ static int pscsi_transport_complete(struct se_task *task) buf[2] |= 0x80; } - transport_kunmap_first_data_page(task->task_se_cmd); + transport_kunmap_data_sg(task->task_se_cmd); } } after_mode_sense: diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index e186f7db3860..cf996d81cfcb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3084,11 +3084,6 @@ static int transport_generic_cmd_sequencer( (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))) goto out_unsupported_cdb; - /* Let's limit control cdbs to a page, for simplicity's sake. */ - if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && - size > PAGE_SIZE) - goto out_invalid_cdb_field; - transport_set_supported_SAM_opcode(cmd); return ret; @@ -3492,9 +3487,11 @@ int transport_generic_map_mem_to_cmd( } EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); -void *transport_kmap_first_data_page(struct se_cmd *cmd) +void *transport_kmap_data_sg(struct se_cmd *cmd) { struct scatterlist *sg = cmd->t_data_sg; + struct page **pages; + int i; BUG_ON(!sg); /* @@ -3502,15 +3499,41 @@ void *transport_kmap_first_data_page(struct se_cmd *cmd) * tcm_loop who may be using a contig buffer from the SCSI midlayer for * control CDBs passed as SGLs via transport_generic_map_mem_to_cmd() */ - return kmap(sg_page(sg)) + sg->offset; -} -EXPORT_SYMBOL(transport_kmap_first_data_page); + if (!cmd->t_data_nents) + return NULL; + else if (cmd->t_data_nents == 1) + return kmap(sg_page(sg)) + sg->offset; -void transport_kunmap_first_data_page(struct se_cmd *cmd) -{ - kunmap(sg_page(cmd->t_data_sg)); + /* >1 page. use vmap */ + pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); + if (!pages) + return NULL; + + /* convert sg[] to pages[] */ + for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { + pages[i] = sg_page(sg); + } + + cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); + kfree(pages); + if (!cmd->t_data_vmap) + return NULL; + + return cmd->t_data_vmap + cmd->t_data_sg[0].offset; } -EXPORT_SYMBOL(transport_kunmap_first_data_page); +EXPORT_SYMBOL(transport_kmap_data_sg); + +void transport_kunmap_data_sg(struct se_cmd *cmd) +{ + if (!cmd->t_data_nents) + return; + else if (cmd->t_data_nents == 1) + kunmap(sg_page(cmd->t_data_sg)); + + vunmap(cmd->t_data_vmap); + cmd->t_data_vmap = NULL; +} +EXPORT_SYMBOL(transport_kunmap_data_sg); static int transport_generic_get_mem(struct se_cmd *cmd) diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 4866499bdeeb..e5e6ff98f0fa 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -59,7 +59,7 @@ int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *); int transport_set_vpd_ident(struct t10_vpd *, unsigned char *); /* core helpers also used by command snooping in pscsi */ -void *transport_kmap_first_data_page(struct se_cmd *); -void transport_kunmap_first_data_page(struct se_cmd *); +void *transport_kmap_data_sg(struct se_cmd *); +void transport_kunmap_data_sg(struct se_cmd *); #endif /* TARGET_CORE_BACKEND_H */ diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index daf532bc721a..dc4e345a0163 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -582,6 +582,7 @@ struct se_cmd { struct scatterlist *t_data_sg; unsigned int t_data_nents; + void *t_data_vmap; struct scatterlist *t_bidi_data_sg; unsigned int t_bidi_data_nents; From 2f9bc894c67dbacae5a6a9875818d2a18a918d18 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 16 Jan 2012 23:33:48 -0800 Subject: [PATCH 019/380] iscsi-target: Fix discovery with INADDR_ANY and IN6ADDR_ANY_INIT This patch addresses a bug with sendtargets discovery where INADDR_ANY (0.0.0.0) + IN6ADDR_ANY_INIT ([0:0:0:0:0:0:0:0]) network portals where incorrectly being reported back to initiators instead of the address of the connecting interface. To address this, save local socket ->getname() output during iscsi login setup, and makes iscsit_build_sendtargets_response() return these TargetAddress keys when INADDR_ANY or IN6ADDR_ANY_INIT portals are in use. Reported-by: Dax Kelson Reported-by: Andy Grover Cc: David S. Miller Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 37 ++++++++++++++++++++--- drivers/target/iscsi/iscsi_target_core.h | 2 ++ drivers/target/iscsi/iscsi_target_login.c | 31 ++++++++++++++++--- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 6e070e0a8393..44262908def5 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3164,6 +3164,30 @@ static int iscsit_send_task_mgt_rsp( return 0; } +static bool iscsit_check_inaddr_any(struct iscsi_np *np) +{ + bool ret = false; + + if (np->np_sockaddr.ss_family == AF_INET6) { + const struct sockaddr_in6 sin6 = { + .sin6_addr = IN6ADDR_ANY_INIT }; + struct sockaddr_in6 *sock_in6 = + (struct sockaddr_in6 *)&np->np_sockaddr; + + if (!memcmp(sock_in6->sin6_addr.s6_addr, + sin6.sin6_addr.s6_addr, 16)) + ret = true; + } else { + struct sockaddr_in * sock_in = + (struct sockaddr_in *)&np->np_sockaddr; + + if (sock_in->sin_addr.s_addr == INADDR_ANY) + ret = true; + } + + return ret; +} + static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) { char *payload = NULL; @@ -3213,12 +3237,17 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) spin_lock(&tpg->tpg_np_lock); list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) { + struct iscsi_np *np = tpg_np->tpg_np; + bool inaddr_any = iscsit_check_inaddr_any(np); + len = sprintf(buf, "TargetAddress=" "%s%s%s:%hu,%hu", - (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ? - "[" : "", tpg_np->tpg_np->np_ip, - (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ? - "]" : "", tpg_np->tpg_np->np_port, + (np->np_sockaddr.ss_family == AF_INET6) ? + "[" : "", (inaddr_any == false) ? + np->np_ip : conn->local_ip, + (np->np_sockaddr.ss_family == AF_INET6) ? + "]" : "", (inaddr_any == false) ? + np->np_port : conn->local_port, tpg->tpgt); len += 1; diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index ebf81fdbb5c5..0ec3b77a0c27 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -508,6 +508,7 @@ struct iscsi_conn { u16 cid; /* Remote TCP Port */ u16 login_port; + u16 local_port; int net_size; u32 auth_id; #define CONNFLAG_SCTP_STRUCT_FILE 0x01 @@ -527,6 +528,7 @@ struct iscsi_conn { unsigned char bad_hdr[ISCSI_HDR_LEN]; #define IPV6_ADDRESS_SPACE 48 unsigned char login_ip[IPV6_ADDRESS_SPACE]; + unsigned char local_ip[IPV6_ADDRESS_SPACE]; int conn_usage_count; int conn_waiting_on_uc; atomic_t check_immediate_queue; diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 373b0cc6abd8..ec47a7c5966e 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -615,8 +615,8 @@ static int iscsi_post_login_handler( } pr_debug("iSCSI Login successful on CID: %hu from %s to" - " %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip, - np->np_port, tpg->tpgt); + " %s:%hu,%hu\n", conn->cid, conn->login_ip, + conn->local_ip, conn->local_port, tpg->tpgt); list_add_tail(&conn->conn_list, &sess->sess_conn_list); atomic_inc(&sess->nconn); @@ -658,7 +658,8 @@ static int iscsi_post_login_handler( sess->session_state = TARG_SESS_STATE_LOGGED_IN; pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n", - conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt); + conn->cid, conn->login_ip, conn->local_ip, conn->local_port, + tpg->tpgt); spin_lock_bh(&sess->conn_lock); list_add_tail(&conn->conn_list, &sess->sess_conn_list); @@ -1020,6 +1021,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", &sock_in6.sin6_addr.in6_u); conn->login_port = ntohs(sock_in6.sin6_port); + + if (conn->sock->ops->getname(conn->sock, + (struct sockaddr *)&sock_in6, &err, 0) < 0) { + pr_err("sock_ops->getname() failed.\n"); + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, + ISCSI_LOGIN_STATUS_TARGET_ERROR); + goto new_sess_out; + } + snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c", + &sock_in6.sin6_addr.in6_u); + conn->local_port = ntohs(sock_in6.sin6_port); + } else { memset(&sock_in, 0, sizeof(struct sockaddr_in)); @@ -1032,6 +1045,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) } sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr); conn->login_port = ntohs(sock_in.sin_port); + + if (conn->sock->ops->getname(conn->sock, + (struct sockaddr *)&sock_in, &err, 0) < 0) { + pr_err("sock_ops->getname() failed.\n"); + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, + ISCSI_LOGIN_STATUS_TARGET_ERROR); + goto new_sess_out; + } + sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr); + conn->local_port = ntohs(sock_in.sin_port); } conn->network_transport = np->np_network_transport; @@ -1039,7 +1062,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) pr_debug("Received iSCSI login request from %s on %s Network" " Portal %s:%hu\n", conn->login_ip, (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP", - np->np_ip, np->np_port); + conn->local_ip, conn->local_port); pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n"); conn->conn_state = TARG_CONN_STATE_IN_LOGIN; From bb1acb2ee038a6c13ee99e0b9fb44dacb4a9de84 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 17 Jan 2012 18:00:56 -0800 Subject: [PATCH 020/380] target: Return correct ASC for unimplemented VPD pages My draft of SPC-4 says: If the device server does not implement the requested vital product data page, then the command shall be terminated with CHECK CONDITION status, with the sense key set to ILLEGAL REQUEST, and the additional sense code set to INVALID FIELD IN CDB. Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_cdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 07a3025d0622..370ad13930a4 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -729,7 +729,7 @@ int target_emulate_inquiry(struct se_task *task) } pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; ret = -EINVAL; out_unmap: From bf0053550aebe56f3bb5dd793e9de69238b5b945 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 17 Jan 2012 18:00:57 -0800 Subject: [PATCH 021/380] target: Fail INQUIRY commands with EVPD==0 but PAGE CODE!=0 My draft of SPC-4 says: If the PAGE CODE field is not set to zero when the EVPD bit is set to zero, the command shall be terminated with CHECK CONDITION status, with the sense key set to ILLEGAL REQUEST, and the additional sense code set to INVALID FIELD IN CDB. Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_cdb.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 370ad13930a4..a9bbf5a5cc27 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -698,6 +698,13 @@ int target_emulate_inquiry(struct se_task *task) int p, ret; if (!(cdb[1] & 0x1)) { + if (cdb[2]) { + pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", + cdb[2]); + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; + } + ret = target_emulate_inquiry_std(cmd); goto out; } From e0a15d5bf4e2fc46a867c43c41b6a41622f673ad Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 18 Jan 2012 18:03:39 +0100 Subject: [PATCH 022/380] [S390] cleanup entry point definition The vmlinux file for s390 contains a currently unused entry point, which is specified in two different locations: the linker script and the makefile. As it happens both definitions are different and the linker file is broken (_start does not exist) and the makefile specifies an entry point which makes no sense (the SALIPL loader entry point). So lets get rid of one definition (the makefile) and use the entry point of all other ipl methods (0x10000 -> startup) to be consistent. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/Makefile | 1 - arch/s390/kernel/vmlinux.lds.S | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/s390/Makefile b/arch/s390/Makefile index e9f353341693..0ad2f1e1ce9e 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -88,7 +88,6 @@ KBUILD_CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare KBUILD_AFLAGS += $(aflags-y) OBJCOPYFLAGS := -O binary -LDFLAGS_vmlinux := -e start head-y := arch/s390/kernel/head.o head-y += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o) diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index e4c79ebb40e6..21109c63eb12 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -9,12 +9,12 @@ #ifndef CONFIG_64BIT OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") OUTPUT_ARCH(s390) -ENTRY(_start) +ENTRY(startup) jiffies = jiffies_64 + 4; #else OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") OUTPUT_ARCH(s390:64-bit) -ENTRY(_start) +ENTRY(startup) jiffies = jiffies_64; #endif From f9f8d02fae0dc47d8868fd069bb88d12f8d1d71f Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Wed, 18 Jan 2012 18:03:40 +0100 Subject: [PATCH 023/380] [S390] dasd: revert LCU optimization Remove the optimization that validate server is only called once per LCU. If a device is set online we only know that we already know the LCU. But if the pathgroup was lost in between we have to do a validate server again to activate some features. Since we have no indication when a pathgroup gets lost we have to do a validate server every time a device is set online. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_alias.c | 64 +-------------------------------- drivers/s390/block/dasd_eckd.c | 41 ++++++++------------- 2 files changed, 16 insertions(+), 89 deletions(-) diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 553b3c5abb0a..b3beed5434e4 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -189,14 +189,12 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) unsigned long flags; struct alias_server *server, *newserver; struct alias_lcu *lcu, *newlcu; - int is_lcu_known; struct dasd_uid uid; private = (struct dasd_eckd_private *) device->private; device->discipline->get_uid(device, &uid); spin_lock_irqsave(&aliastree.lock, flags); - is_lcu_known = 1; server = _find_server(&uid); if (!server) { spin_unlock_irqrestore(&aliastree.lock, flags); @@ -208,7 +206,6 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) if (!server) { list_add(&newserver->server, &aliastree.serverlist); server = newserver; - is_lcu_known = 0; } else { /* someone was faster */ _free_server(newserver); @@ -226,12 +223,10 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) if (!lcu) { list_add(&newlcu->lcu, &server->lculist); lcu = newlcu; - is_lcu_known = 0; } else { /* someone was faster */ _free_lcu(newlcu); } - is_lcu_known = 0; } spin_lock(&lcu->lock); list_add(&device->alias_list, &lcu->inactive_devices); @@ -239,64 +234,7 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) spin_unlock(&lcu->lock); spin_unlock_irqrestore(&aliastree.lock, flags); - return is_lcu_known; -} - -/* - * The first device to be registered on an LCU will have to do - * some additional setup steps to configure that LCU on the - * storage server. All further devices should wait with their - * initialization until the first device is done. - * To synchronize this work, the first device will call - * dasd_alias_lcu_setup_complete when it is done, and all - * other devices will wait for it with dasd_alias_wait_for_lcu_setup. - */ -void dasd_alias_lcu_setup_complete(struct dasd_device *device) -{ - unsigned long flags; - struct alias_server *server; - struct alias_lcu *lcu; - struct dasd_uid uid; - - device->discipline->get_uid(device, &uid); - lcu = NULL; - spin_lock_irqsave(&aliastree.lock, flags); - server = _find_server(&uid); - if (server) - lcu = _find_lcu(server, &uid); - spin_unlock_irqrestore(&aliastree.lock, flags); - if (!lcu) { - DBF_EVENT_DEVID(DBF_ERR, device->cdev, - "could not find lcu for %04x %02x", - uid.ssid, uid.real_unit_addr); - WARN_ON(1); - return; - } - complete_all(&lcu->lcu_setup); -} - -void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) -{ - unsigned long flags; - struct alias_server *server; - struct alias_lcu *lcu; - struct dasd_uid uid; - - device->discipline->get_uid(device, &uid); - lcu = NULL; - spin_lock_irqsave(&aliastree.lock, flags); - server = _find_server(&uid); - if (server) - lcu = _find_lcu(server, &uid); - spin_unlock_irqrestore(&aliastree.lock, flags); - if (!lcu) { - DBF_EVENT_DEVID(DBF_ERR, device->cdev, - "could not find lcu for %04x %02x", - uid.ssid, uid.real_unit_addr); - WARN_ON(1); - return; - } - wait_for_completion(&lcu->lcu_setup); + return 0; } /* diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index bbcd5e9206ee..1b6e7ea9347f 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1534,6 +1534,10 @@ static void dasd_eckd_validate_server(struct dasd_device *device) struct dasd_eckd_private *private; int enable_pav; + private = (struct dasd_eckd_private *) device->private; + if (private->uid.type == UA_BASE_PAV_ALIAS || + private->uid.type == UA_HYPER_PAV_ALIAS) + return; if (dasd_nopav || MACHINE_IS_VM) enable_pav = 0; else @@ -1542,7 +1546,6 @@ static void 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_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " "returned rc=%d", private->uid.ssid, rc); } @@ -1588,7 +1591,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) struct dasd_eckd_private *private; struct dasd_block *block; struct dasd_uid temp_uid; - int is_known, rc, i; + int rc, i; int readonly; unsigned long value; @@ -1651,22 +1654,12 @@ dasd_eckd_check_characteristics(struct dasd_device *device) block->base = device; } - /* register lcu with alias handling, enable PAV if this is a new lcu */ - is_known = dasd_alias_make_device_known_to_lcu(device); - if (is_known < 0) { - rc = is_known; + /* register lcu with alias handling, enable PAV */ + rc = dasd_alias_make_device_known_to_lcu(device); + if (rc) goto out_err2; - } - /* - * dasd_eckd_validate_server is done on the first device that - * is found for an LCU. All later other devices have to wait - * for it, so they will read the correct feature codes. - */ - if (!is_known) { - dasd_eckd_validate_server(device); - dasd_alias_lcu_setup_complete(device); - } else - dasd_alias_wait_for_lcu_setup(device); + + dasd_eckd_validate_server(device); /* device may report different configuration data after LCU setup */ rc = dasd_eckd_read_conf(device); @@ -4098,7 +4091,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device) { struct dasd_eckd_private *private; struct dasd_eckd_characteristics temp_rdc_data; - int is_known, rc; + int rc; struct dasd_uid temp_uid; unsigned long flags; @@ -4121,14 +4114,10 @@ static int dasd_eckd_restore_device(struct dasd_device *device) goto out_err; /* register lcu with alias handling, enable PAV if this is a new lcu */ - is_known = dasd_alias_make_device_known_to_lcu(device); - if (is_known < 0) - return is_known; - if (!is_known) { - dasd_eckd_validate_server(device); - dasd_alias_lcu_setup_complete(device); - } else - dasd_alias_wait_for_lcu_setup(device); + rc = dasd_alias_make_device_known_to_lcu(device); + if (rc) + return rc; + dasd_eckd_validate_server(device); /* RE-Read Configuration Data */ rc = dasd_eckd_read_conf(device); From f16330316321d1c388d13096f6858f5d2dac29dc Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Wed, 18 Jan 2012 18:03:41 +0100 Subject: [PATCH 024/380] [S390] dasd: revalidate server for new pathgroup If a pathgroup is established we get an event and have to revalidate the server to propagate supported features like PAV and enable them. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 6 ++++++ drivers/s390/block/dasd_eckd.c | 22 ++++++++++++++++++++++ drivers/s390/block/dasd_int.h | 2 ++ 3 files changed, 30 insertions(+) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index eef27a197c00..110137e7ec81 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3261,6 +3261,12 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event) device->path_data.tbvpm |= eventlpm; dasd_schedule_device_bh(device); } + if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "Pathgroup re-established\n"); + if (device->discipline->kick_validate) + device->discipline->kick_validate(device); + } } dasd_put_device(device); } diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 1b6e7ea9347f..70880be26015 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1550,6 +1550,24 @@ static void dasd_eckd_validate_server(struct dasd_device *device) "returned rc=%d", private->uid.ssid, rc); } +/* + * worker to do a validate server in case of a lost pathgroup + */ +static void dasd_eckd_do_validate_server(struct work_struct *work) +{ + struct dasd_device *device = container_of(work, struct dasd_device, + kick_validate); + dasd_eckd_validate_server(device); + dasd_put_device(device); +} + +static void dasd_eckd_kick_validate_server(struct dasd_device *device) +{ + dasd_get_device(device); + /* queue call to do_validate_server to the kernel event daemon. */ + schedule_work(&device->kick_validate); +} + static u32 get_fcx_max_data(struct dasd_device *device) { #if defined(CONFIG_64BIT) @@ -1595,6 +1613,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) int readonly; unsigned long value; + /* setup work queue for validate server*/ + INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server); + if (!ccw_device_is_pathgroup(device->cdev)) { dev_warn(&device->cdev->dev, "A channel path group could not be established\n"); @@ -4259,6 +4280,7 @@ static struct dasd_discipline dasd_eckd_discipline = { .restore = dasd_eckd_restore_device, .reload = dasd_eckd_reload_device, .get_uid = dasd_eckd_get_uid, + .kick_validate = dasd_eckd_kick_validate_server, }; static int __init diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index afe8c33422ed..33a6743ddc55 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -355,6 +355,7 @@ struct dasd_discipline { int (*reload) (struct dasd_device *); int (*get_uid) (struct dasd_device *, struct dasd_uid *); + void (*kick_validate) (struct dasd_device *); }; extern struct dasd_discipline *dasd_diag_discipline_pointer; @@ -455,6 +456,7 @@ struct dasd_device { struct work_struct kick_work; struct work_struct restore_device; struct work_struct reload_device; + struct work_struct kick_validate; struct timer_list timer; debug_info_t *debug_area; From eacb6ec9ae5932ea02a44268684a56e4b5996ccf Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 19 Jan 2012 12:37:13 +0100 Subject: [PATCH 025/380] microblaze: generic atomic64 support This tiny patch adds generic atomic64 support for the Microblaze architecture. The patch is against the latest linux-2.6-microblaze tree. It also fixes the kernel build for microblaze: Error log: CC kernel/trace/trace_clock.o kernel/trace/trace_clock.c:117: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'trace_counter' kernel/trace/trace_clock.c: In function 'trace_clock_counter': kernel/trace/trace_clock.c:126: error: implicit declaration of function 'atomic64_add_return' kernel/trace/trace_clock.c:126: error: 'trace_counter' undeclared (first use in this function) kernel/trace/trace_clock.c:126: error: (Each undeclared identifier is reported only once kernel/trace/trace_clock.c:126: error: for each function it appears in.) make[2]: *** [kernel/trace/trace_clock.o] Error 1 make[1]: *** [kernel/trace] Error 2 make: *** [kernel] Error 2 Signed-off-by: Ariane Keller Signed-off-by: Daniel Borkmann Signed-off-by: Michal Simek --- arch/microblaze/Kconfig | 1 + arch/microblaze/include/asm/atomic.h | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 74f23a460ba2..c8d6efb99dbf 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -19,6 +19,7 @@ config MICROBLAZE select GENERIC_IRQ_SHOW select GENERIC_PCI_IOMAP select GENERIC_CPU_DEVICES + select GENERIC_ATOMIC64 config SWAP def_bool n diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h index 6d2e1d418be7..615f53992c65 100644 --- a/arch/microblaze/include/asm/atomic.h +++ b/arch/microblaze/include/asm/atomic.h @@ -2,6 +2,7 @@ #define _ASM_MICROBLAZE_ATOMIC_H #include +#include /* * Atomically test *v and decrement if it is greater than 0. From b469d4329cf949043f9b93a6644f2c64015ef8cd Mon Sep 17 00:00:00 2001 From: Tiejun Chen Date: Wed, 11 Jan 2012 05:51:10 +0000 Subject: [PATCH 026/380] kmemleak: Only scan non-zero-size areas Kmemleak should only track valid scan areas with a non-zero size. Otherwise, such area may reside just at the end of an object and kmemleak would report "Adding scan area to unknown object". Signed-off-by: Tiejun Chen Signed-off-by: Catalin Marinas --- mm/kmemleak.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index c833addd94d7..f9f7310f0fdb 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1036,7 +1036,7 @@ void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) { pr_debug("%s(0x%p)\n", __func__, ptr); - if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr)) + if (atomic_read(&kmemleak_enabled) && ptr && size && !IS_ERR(ptr)) add_scan_area((unsigned long)ptr, size, gfp); else if (atomic_read(&kmemleak_early_log)) log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0); From 546edd83abe4f03472d721c60011c5ff95e25474 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 6 Jan 2012 13:38:31 -0700 Subject: [PATCH 027/380] pinctrl: fix pinconf_pins_show iteration Commit 706e852 "pinctrl: correct a offset while enumerating pins" modified the variable used by pinconf_pin_show()'s for loop, but didn't update the for loop test expression. Signed-off-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 1259872b0a1d..1892a3794b99 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -236,7 +236,7 @@ static int pinconf_pins_show(struct seq_file *s, void *what) seq_puts(s, "Format: pin (name): pinmux setting array\n"); /* The pin number can be retrived from the pin controller descriptor */ - for (i = 0; pin < pctldev->desc->npins; i++) { + for (i = 0; i < pctldev->desc->npins; i++) { struct pin_desc *desc; pin = pctldev->desc->pins[i].number; From b370d29ea7565a638ccf85389488364b5abb39fa Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 20 Jan 2012 10:42:40 +0000 Subject: [PATCH 028/380] kmemleak: Disable early logging when kmemleak is off by default Commit b6693005 (kmemleak: When the early log buffer is exceeded, report the actual number) deferred the disabling of the early logging to kmemleak_init(). However, when CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y, the early logging was no longer disabled causing __init kmemleak functions to be called even after the kernel freed the init memory. This patch disables the early logging during kmemleak_init() if kmemleak is left disabled. Reported-by: Dirk Gouders Tested-by: Dirk Gouders Tested-by: Josh Boyer Signed-off-by: Catalin Marinas --- mm/kmemleak.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index f9f7310f0fdb..45eb6217bf38 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1757,6 +1757,7 @@ void __init kmemleak_init(void) #ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF if (!kmemleak_skip_disable) { + atomic_set(&kmemleak_early_log, 0); kmemleak_disable(); return; } From 86b2bbfdbd1fcc4a3aa62ccd3f245c40c5ad5b85 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 20 Jan 2012 10:09:23 -0500 Subject: [PATCH 029/380] hwmon: (f71805f) Fix clamping of temperature limits Properly clamp temperature limits set by the user. Without this fix, attempts to write temperature limits above the maximum supported by the chip (255 degrees Celsius) would arbitrarily and unexpectedly result in the limit being set to 0 degree Celsius. Signed-off-by: Jean Delvare Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck --- drivers/hwmon/f71805f.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 92f949767ece..6dbfd3e516e4 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -283,11 +283,11 @@ static inline long temp_from_reg(u8 reg) static inline u8 temp_to_reg(long val) { - if (val < 0) - val = 0; - else if (val > 1000 * 0xff) - val = 0xff; - return ((val + 500) / 1000); + if (val <= 0) + return 0; + if (val >= 1000 * 0xff) + return 0xff; + return (val + 500) / 1000; } /* From 95120d5d1bc17bdec29085186b6ab3d90e92d6f3 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Sun, 22 Jan 2012 18:57:57 +0100 Subject: [PATCH 030/380] Correct bad gpio naming One of the GPIO names in drivers/gpio/gpio-lpc32xx.c was bad. Renaming gpi000 -> gpio00 Signed-off-by: Roland Stigge Signed-off-by: Grant Likely --- drivers/gpio/gpio-lpc32xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 5b6948081f8f..ddfacc5ce56d 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -96,7 +96,7 @@ static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = { }; static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = { - "gpi000", "gpio01", "gpio02", "gpio03", + "gpio00", "gpio01", "gpio02", "gpio03", "gpio04", "gpio05" }; From e9c688a3272fd4b659228f3880de8109a94540e2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 22 Jan 2012 14:31:15 -0700 Subject: [PATCH 031/380] driver core: remove drivers/base/sys.c and include/linux/sysdev.h Now that all users of 'struct sysdev' are removed from the kernel, we can safely remove the .h and .c files for this code, to ensure that no one accidentally starts to use it again. Many thanks for Kay who did all the hard work here on making this happen. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/Makefile | 2 +- drivers/base/sys.c | 383 ----------------------------------------- include/linux/sysdev.h | 164 ------------------ 3 files changed, 1 insertion(+), 548 deletions(-) delete mode 100644 drivers/base/sys.c delete mode 100644 include/linux/sysdev.h diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 2c8272dd93c4..610f9997a403 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -1,6 +1,6 @@ # Makefile for the Linux device tree -obj-y := core.o sys.o bus.o dd.o syscore.o \ +obj-y := core.o bus.o dd.o syscore.o \ driver.o class.o platform.o \ cpu.o firmware.o init.o map.o devres.o \ attribute_container.o transport_class.o \ diff --git a/drivers/base/sys.c b/drivers/base/sys.c deleted file mode 100644 index 409f5ce78829..000000000000 --- a/drivers/base/sys.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * sys.c - pseudo-bus for system 'devices' (cpus, PICs, timers, etc) - * - * Copyright (c) 2002-3 Patrick Mochel - * 2002-3 Open Source Development Lab - * - * This file is released under the GPLv2 - * - * This exports a 'system' bus type. - * By default, a 'sys' bus gets added to the root of the system. There will - * always be core system devices. Devices can use sysdev_register() to - * add themselves as children of the system bus. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base.h" - -#define to_sysdev(k) container_of(k, struct sys_device, kobj) -#define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr) - - -static ssize_t -sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer) -{ - struct sys_device *sysdev = to_sysdev(kobj); - struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr); - - if (sysdev_attr->show) - return sysdev_attr->show(sysdev, sysdev_attr, buffer); - return -EIO; -} - - -static ssize_t -sysdev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) -{ - struct sys_device *sysdev = to_sysdev(kobj); - struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr); - - if (sysdev_attr->store) - return sysdev_attr->store(sysdev, sysdev_attr, buffer, count); - return -EIO; -} - -static const struct sysfs_ops sysfs_ops = { - .show = sysdev_show, - .store = sysdev_store, -}; - -static struct kobj_type ktype_sysdev = { - .sysfs_ops = &sysfs_ops, -}; - - -int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a) -{ - return sysfs_create_file(&s->kobj, &a->attr); -} - - -void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a) -{ - sysfs_remove_file(&s->kobj, &a->attr); -} - -EXPORT_SYMBOL_GPL(sysdev_create_file); -EXPORT_SYMBOL_GPL(sysdev_remove_file); - -#define to_sysdev_class(k) container_of(k, struct sysdev_class, kset.kobj) -#define to_sysdev_class_attr(a) container_of(a, \ - struct sysdev_class_attribute, attr) - -static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, - char *buffer) -{ - struct sysdev_class *class = to_sysdev_class(kobj); - struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); - - if (class_attr->show) - return class_attr->show(class, class_attr, buffer); - return -EIO; -} - -static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) -{ - struct sysdev_class *class = to_sysdev_class(kobj); - struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); - - if (class_attr->store) - return class_attr->store(class, class_attr, buffer, count); - return -EIO; -} - -static const struct sysfs_ops sysfs_class_ops = { - .show = sysdev_class_show, - .store = sysdev_class_store, -}; - -static struct kobj_type ktype_sysdev_class = { - .sysfs_ops = &sysfs_class_ops, -}; - -int sysdev_class_create_file(struct sysdev_class *c, - struct sysdev_class_attribute *a) -{ - return sysfs_create_file(&c->kset.kobj, &a->attr); -} -EXPORT_SYMBOL_GPL(sysdev_class_create_file); - -void sysdev_class_remove_file(struct sysdev_class *c, - struct sysdev_class_attribute *a) -{ - sysfs_remove_file(&c->kset.kobj, &a->attr); -} -EXPORT_SYMBOL_GPL(sysdev_class_remove_file); - -extern struct kset *system_kset; - -int sysdev_class_register(struct sysdev_class *cls) -{ - int retval; - - pr_debug("Registering sysdev class '%s'\n", cls->name); - - INIT_LIST_HEAD(&cls->drivers); - memset(&cls->kset.kobj, 0x00, sizeof(struct kobject)); - cls->kset.kobj.parent = &system_kset->kobj; - cls->kset.kobj.ktype = &ktype_sysdev_class; - cls->kset.kobj.kset = system_kset; - - retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name); - if (retval) - return retval; - - retval = kset_register(&cls->kset); - if (!retval && cls->attrs) - retval = sysfs_create_files(&cls->kset.kobj, - (const struct attribute **)cls->attrs); - return retval; -} - -void sysdev_class_unregister(struct sysdev_class *cls) -{ - pr_debug("Unregistering sysdev class '%s'\n", - kobject_name(&cls->kset.kobj)); - if (cls->attrs) - sysfs_remove_files(&cls->kset.kobj, - (const struct attribute **)cls->attrs); - kset_unregister(&cls->kset); -} - -EXPORT_SYMBOL_GPL(sysdev_class_register); -EXPORT_SYMBOL_GPL(sysdev_class_unregister); - -static DEFINE_MUTEX(sysdev_drivers_lock); - -/* - * @dev != NULL means that we're unwinding because some drv->add() - * failed for some reason. You need to grab sysdev_drivers_lock before - * calling this. - */ -static void __sysdev_driver_remove(struct sysdev_class *cls, - struct sysdev_driver *drv, - struct sys_device *from_dev) -{ - struct sys_device *dev = from_dev; - - list_del_init(&drv->entry); - if (!cls) - return; - - if (!drv->remove) - goto kset_put; - - if (dev) - list_for_each_entry_continue_reverse(dev, &cls->kset.list, - kobj.entry) - drv->remove(dev); - else - list_for_each_entry(dev, &cls->kset.list, kobj.entry) - drv->remove(dev); - -kset_put: - kset_put(&cls->kset); -} - -/** - * sysdev_driver_register - Register auxiliary driver - * @cls: Device class driver belongs to. - * @drv: Driver. - * - * @drv is inserted into @cls->drivers to be - * called on each operation on devices of that class. The refcount - * of @cls is incremented. - */ -int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) -{ - struct sys_device *dev = NULL; - int err = 0; - - if (!cls) { - WARN(1, KERN_WARNING "sysdev: invalid class passed to %s!\n", - __func__); - return -EINVAL; - } - - /* Check whether this driver has already been added to a class. */ - if (drv->entry.next && !list_empty(&drv->entry)) - WARN(1, KERN_WARNING "sysdev: class %s: driver (%p) has already" - " been registered to a class, something is wrong, but " - "will forge on!\n", cls->name, drv); - - mutex_lock(&sysdev_drivers_lock); - if (cls && kset_get(&cls->kset)) { - list_add_tail(&drv->entry, &cls->drivers); - - /* If devices of this class already exist, tell the driver */ - if (drv->add) { - list_for_each_entry(dev, &cls->kset.list, kobj.entry) { - err = drv->add(dev); - if (err) - goto unwind; - } - } - } else { - err = -EINVAL; - WARN(1, KERN_ERR "%s: invalid device class\n", __func__); - } - - goto unlock; - -unwind: - __sysdev_driver_remove(cls, drv, dev); - -unlock: - mutex_unlock(&sysdev_drivers_lock); - return err; -} - -/** - * sysdev_driver_unregister - Remove an auxiliary driver. - * @cls: Class driver belongs to. - * @drv: Driver. - */ -void sysdev_driver_unregister(struct sysdev_class *cls, - struct sysdev_driver *drv) -{ - mutex_lock(&sysdev_drivers_lock); - __sysdev_driver_remove(cls, drv, NULL); - mutex_unlock(&sysdev_drivers_lock); -} -EXPORT_SYMBOL_GPL(sysdev_driver_register); -EXPORT_SYMBOL_GPL(sysdev_driver_unregister); - -/** - * sysdev_register - add a system device to the tree - * @sysdev: device in question - * - */ -int sysdev_register(struct sys_device *sysdev) -{ - int error; - struct sysdev_class *cls = sysdev->cls; - - if (!cls) - return -EINVAL; - - pr_debug("Registering sys device of class '%s'\n", - kobject_name(&cls->kset.kobj)); - - /* initialize the kobject to 0, in case it had previously been used */ - memset(&sysdev->kobj, 0x00, sizeof(struct kobject)); - - /* Make sure the kset is set */ - sysdev->kobj.kset = &cls->kset; - - /* Register the object */ - error = kobject_init_and_add(&sysdev->kobj, &ktype_sysdev, NULL, - "%s%d", kobject_name(&cls->kset.kobj), - sysdev->id); - - if (!error) { - struct sysdev_driver *drv; - - pr_debug("Registering sys device '%s'\n", - kobject_name(&sysdev->kobj)); - - mutex_lock(&sysdev_drivers_lock); - /* Generic notification is implicit, because it's that - * code that should have called us. - */ - - /* Notify class auxiliary drivers */ - list_for_each_entry(drv, &cls->drivers, entry) { - if (drv->add) - drv->add(sysdev); - } - mutex_unlock(&sysdev_drivers_lock); - kobject_uevent(&sysdev->kobj, KOBJ_ADD); - } - - return error; -} - -void sysdev_unregister(struct sys_device *sysdev) -{ - struct sysdev_driver *drv; - - mutex_lock(&sysdev_drivers_lock); - list_for_each_entry(drv, &sysdev->cls->drivers, entry) { - if (drv->remove) - drv->remove(sysdev); - } - mutex_unlock(&sysdev_drivers_lock); - - kobject_put(&sysdev->kobj); -} - -EXPORT_SYMBOL_GPL(sysdev_register); -EXPORT_SYMBOL_GPL(sysdev_unregister); - -#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr) - -ssize_t sysdev_store_ulong(struct sys_device *sysdev, - struct sysdev_attribute *attr, - const char *buf, size_t size) -{ - struct sysdev_ext_attribute *ea = to_ext_attr(attr); - char *end; - unsigned long new = simple_strtoul(buf, &end, 0); - if (end == buf) - return -EINVAL; - *(unsigned long *)(ea->var) = new; - /* Always return full write size even if we didn't consume all */ - return size; -} -EXPORT_SYMBOL_GPL(sysdev_store_ulong); - -ssize_t sysdev_show_ulong(struct sys_device *sysdev, - struct sysdev_attribute *attr, - char *buf) -{ - struct sysdev_ext_attribute *ea = to_ext_attr(attr); - return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); -} -EXPORT_SYMBOL_GPL(sysdev_show_ulong); - -ssize_t sysdev_store_int(struct sys_device *sysdev, - struct sysdev_attribute *attr, - const char *buf, size_t size) -{ - struct sysdev_ext_attribute *ea = to_ext_attr(attr); - char *end; - long new = simple_strtol(buf, &end, 0); - if (end == buf || new > INT_MAX || new < INT_MIN) - return -EINVAL; - *(int *)(ea->var) = new; - /* Always return full write size even if we didn't consume all */ - return size; -} -EXPORT_SYMBOL_GPL(sysdev_store_int); - -ssize_t sysdev_show_int(struct sys_device *sysdev, - struct sysdev_attribute *attr, - char *buf) -{ - struct sysdev_ext_attribute *ea = to_ext_attr(attr); - return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); -} -EXPORT_SYMBOL_GPL(sysdev_show_int); - diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h deleted file mode 100644 index 20f63d3e6144..000000000000 --- a/include/linux/sysdev.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * System devices follow a slightly different driver model. - * They don't need to do dynammic driver binding, can't be probed, - * and don't reside on any type of peripheral bus. - * So, we represent and treat them a little differently. - * - * We still have a notion of a driver for a system device, because we still - * want to perform basic operations on these devices. - * - * We also support auxiliary drivers binding to devices of a certain class. - * - * This allows configurable drivers to register themselves for devices of - * a certain type. And, it allows class definitions to reside in generic - * code while arch-specific code can register specific drivers. - * - * Auxiliary drivers registered with a NULL cls are registered as drivers - * for all system devices, and get notification calls for each device. - */ - - -#ifndef _SYSDEV_H_ -#define _SYSDEV_H_ - -#include -#include - - -struct sys_device; -struct sysdev_class_attribute; - -struct sysdev_class { - const char *name; - struct list_head drivers; - struct sysdev_class_attribute **attrs; - struct kset kset; -}; - -struct sysdev_class_attribute { - struct attribute attr; - ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *, - char *); - ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *, - const char *, size_t); -}; - -#define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \ -{ \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ -} - -#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \ - struct sysdev_class_attribute attr_##_name = \ - _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) - - -extern int sysdev_class_register(struct sysdev_class *); -extern void sysdev_class_unregister(struct sysdev_class *); - -extern int sysdev_class_create_file(struct sysdev_class *, - struct sysdev_class_attribute *); -extern void sysdev_class_remove_file(struct sysdev_class *, - struct sysdev_class_attribute *); -/** - * Auxiliary system device drivers. - */ - -struct sysdev_driver { - struct list_head entry; - int (*add)(struct sys_device *); - int (*remove)(struct sys_device *); -}; - - -extern int sysdev_driver_register(struct sysdev_class *, struct sysdev_driver *); -extern void sysdev_driver_unregister(struct sysdev_class *, struct sysdev_driver *); - - -/** - * sys_devices can be simplified a lot from regular devices, because they're - * simply not as versatile. - */ - -struct sys_device { - u32 id; - struct sysdev_class * cls; - struct kobject kobj; -}; - -extern int sysdev_register(struct sys_device *); -extern void sysdev_unregister(struct sys_device *); - - -struct sysdev_attribute { - struct attribute attr; - ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *); - ssize_t (*store)(struct sys_device *, struct sysdev_attribute *, - const char *, size_t); -}; - - -#define _SYSDEV_ATTR(_name, _mode, _show, _store) \ -{ \ - .attr = { .name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ -} - -#define SYSDEV_ATTR(_name, _mode, _show, _store) \ - struct sysdev_attribute attr_##_name = \ - _SYSDEV_ATTR(_name, _mode, _show, _store); - -extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *); -extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *); - -/* Create/remove NULL terminated attribute list */ -static inline int -sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a) -{ - return sysfs_create_files(&d->kobj, (const struct attribute **)a); -} - -static inline void -sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a) -{ - return sysfs_remove_files(&d->kobj, (const struct attribute **)a); -} - -struct sysdev_ext_attribute { - struct sysdev_attribute attr; - void *var; -}; - -/* - * Support for simple variable sysdev attributes. - * The pointer to the variable is stored in a sysdev_ext_attribute - */ - -/* Add more types as needed */ - -extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *, - char *); -extern ssize_t sysdev_store_ulong(struct sys_device *, - struct sysdev_attribute *, const char *, size_t); -extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *, - char *); -extern ssize_t sysdev_store_int(struct sys_device *, - struct sysdev_attribute *, const char *, size_t); - -#define _SYSDEV_ULONG_ATTR(_name, _mode, _var) \ - { _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \ - &(_var) } -#define SYSDEV_ULONG_ATTR(_name, _mode, _var) \ - struct sysdev_ext_attribute attr_##_name = \ - _SYSDEV_ULONG_ATTR(_name, _mode, _var); -#define _SYSDEV_INT_ATTR(_name, _mode, _var) \ - { _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \ - &(_var) } -#define SYSDEV_INT_ATTR(_name, _mode, _var) \ - struct sysdev_ext_attribute attr_##_name = \ - _SYSDEV_INT_ATTR(_name, _mode, _var); - -#endif /* _SYSDEV_H_ */ From af1be04901e27ce669b4ecde1c953d5c939498f5 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 18 Jan 2012 14:03:11 +0100 Subject: [PATCH 032/380] iommu/amd: Work around broken IVRS tables On some systems the IVRS table does not contain all PCI devices present in the system. In case a device not present in the IVRS table is translated by the IOMMU no DMA is possible from that device by default. This patch fixes this by removing the DTE entry for every PCI device present in the system and not covered by IVRS. Cc: stable@vger.kernel.org # >= 3.0 Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index cce1f03b8895..f75e0608be5b 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2863,6 +2863,9 @@ static unsigned device_dma_ops_init(void) for_each_pci_dev(pdev) { if (!check_device(&pdev->dev)) { + + iommu_ignore_device(&pdev->dev); + unhandled += 1; continue; } From d07a74a546981a09ba490936645fbf0d1340b96c Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 25 Aug 2011 16:13:55 -0700 Subject: [PATCH 033/380] dmaengine: fix missing 'cnt' in ?: in dmatest Hi, On the latest tree my compiler has started giving the warning: drivers/dma/dmatest.c:575:28: warning: the omitted middle operand in ?: will always be ?true?, suggest explicit middle operand [-Wparentheses] The following patch fixes the missing middle clause with the same fix that Nicolas Ferre used in the similar clauses. (There seems to have been a race between him fixing that and the extra clause going in a little later). I don't actually know the dmatest code/structures, nor do I own any hardware to test it on (assuming it needs a DMA engine); but this patch builds, the existing code is almost certainly wrong and the fix is the same as the corresponding lines above it. (WTH is x=y?:z legal C anyway?) Signed-off-by: Dr. David Alan Gilbert Reported-by: Dan Carpenter Reported-by: Paul Gortmaker Acked-by: Nicolas Ferre Signed-off-by: Dan Williams --- drivers/dma/dmatest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 2b8661b54eaf..24225f0fdcd8 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -599,7 +599,7 @@ static int dmatest_add_channel(struct dma_chan *chan) } if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { cnt = dmatest_add_threads(dtc, DMA_PQ); - thread_count += cnt > 0 ?: 0; + thread_count += cnt > 0 ? cnt : 0; } pr_info("dmatest: Started %u threads using %s\n", From 875ad3f8e7dff6bc1d053e5bfe73d8e8d2e6ae67 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 23 Jan 2012 12:49:36 -0500 Subject: [PATCH 034/380] SUNRPC: Fix machine creds in generic_create_cred and generic_match - generic_create_cred needs to copy the '.principal' field. - generic_match needs to ignore the groups and match on the '.principal' field. This fixes an Oops that was introduced by commit 68c9715 (SUNRPC: Clean up the RPCSEC_GSS service ticket requests) Reported-by: J. Bruce Fields Signed-off-by: Trond Myklebust Tested-by: J. Bruce Fields --- net/sunrpc/auth_generic.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 1426ec3d0a53..75762f346975 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -92,6 +92,7 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) if (gcred->acred.group_info != NULL) get_group_info(gcred->acred.group_info); gcred->acred.machine_cred = acred->machine_cred; + gcred->acred.principal = acred->principal; dprintk("RPC: allocated %s cred %p for uid %d gid %d\n", gcred->acred.machine_cred ? "machine" : "generic", @@ -123,6 +124,17 @@ generic_destroy_cred(struct rpc_cred *cred) call_rcu(&cred->cr_rcu, generic_free_cred_callback); } +static int +machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flags) +{ + if (!gcred->acred.machine_cred || + gcred->acred.principal != acred->principal || + gcred->acred.uid != acred->uid || + gcred->acred.gid != acred->gid) + return 0; + return 1; +} + /* * Match credentials against current process creds. */ @@ -132,9 +144,12 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base); int i; + if (acred->machine_cred) + return machine_cred_match(acred, gcred, flags); + if (gcred->acred.uid != acred->uid || gcred->acred.gid != acred->gid || - gcred->acred.machine_cred != acred->machine_cred) + gcred->acred.machine_cred != 0) goto out_nomatch; /* Optimisation in the case where pointers are identical... */ From 68d8a781575d7be490f97eb2c403fb13b083da6a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 29 Dec 2011 06:32:29 +0200 Subject: [PATCH 035/380] usb: dwc3: ep0: tidy up Pending Request handling The way our code was written, we should never have a DWC3_EP_PENDING_REQUEST flag set out of a Data Phase and the code in __dwc3_gadget_ep0_queue() did not reflect that situation properly. Tidy up that case to avoid any possible mistakes when starting requests for IRQs which are long gone. Cc: stable@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 2f51de57593a..74a3828cf950 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -149,20 +149,14 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, direction = !!(dep->flags & DWC3_EP0_DIR_IN); - if (dwc->ep0state == EP0_STATUS_PHASE) { - type = dwc->three_stage_setup - ? DWC3_TRBCTL_CONTROL_STATUS3 - : DWC3_TRBCTL_CONTROL_STATUS2; - } else if (dwc->ep0state == EP0_DATA_PHASE) { - type = DWC3_TRBCTL_CONTROL_DATA; - } else { - /* should never happen */ - WARN_ON(1); + if (dwc->ep0state != EP0_DATA_PHASE) { + dev_WARN(dwc->dev, "Unexpected pending request\n"); return 0; } ret = dwc3_ep0_start_trans(dwc, direction, - req->request.dma, req->request.length, type); + req->request.dma, req->request.length, + DWC3_TRBCTL_CONTROL_DATA); dep->flags &= ~(DWC3_EP_PENDING_REQUEST | DWC3_EP0_DIR_IN); } else if (dwc->delayed_status) { From c1084a56da255ef5385c0f587e16fdc225a5460f Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 21 Dec 2011 10:19:38 +0200 Subject: [PATCH 036/380] usb: otg: kill langwell_otg driver The way this driver was added by f0ae849 (usb: Add Intel Langwell USB OTG Transceiver Driver) never even compiled together with langwell_udc, and that's the only way for it to be useful. Signed-off-by: Alexander Shishkin Cc: stable@vger.kernel.org # v2.6.31+ Cc: Heikki Krogerus Cc: Greg Kroah-Hartman Cc: Alan Cox Cc: linux-usb@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/otg/Kconfig | 14 - drivers/usb/otg/Makefile | 1 - drivers/usb/otg/langwell_otg.c | 2347 ------------------------------ include/linux/usb/langwell_otg.h | 139 -- 4 files changed, 2501 deletions(-) delete mode 100644 drivers/usb/otg/langwell_otg.c delete mode 100644 include/linux/usb/langwell_otg.h diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 2a25955881fc..9105c285f594 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -86,20 +86,6 @@ config NOP_USB_XCEIV built-in with usb ip or which are autonomous and doesn't require any phy programming such as ISP1x04 etc. -config USB_LANGWELL_OTG - tristate "Intel Langwell USB OTG dual-role support" - depends on USB && PCI && INTEL_SCU_IPC - select USB_OTG - select USB_OTG_UTILS - help - Say Y here if you want to build Intel Langwell USB OTG - transciever driver in kernel. This driver implements role - switch between EHCI host driver and Langwell USB OTG - client driver. - - To compile this driver as a module, choose M here: the - module will be called langwell_otg. - config USB_MSM_OTG tristate "OTG support for Qualcomm on-chip USB controller" depends on (USB || USB_GADGET) && ARCH_MSM diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index b2c5a9598637..41aa5098b139 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o -obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o obj-$(CONFIG_USB_ULPI) += ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c deleted file mode 100644 index f08f784086f7..000000000000 --- a/drivers/usb/otg/langwell_otg.c +++ /dev/null @@ -1,2347 +0,0 @@ -/* - * Intel Langwell USB OTG transceiver driver - * Copyright (C) 2008 - 2010, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/* This driver helps to switch Langwell OTG controller function between host - * and peripheral. It works with EHCI driver and Langwell client controller - * driver together. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" -#define DRIVER_VERSION "July 10, 2010" - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Henry Yuan , Hao Wu "); -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL"); - -static const char driver_name[] = "langwell_otg"; - -static int langwell_otg_probe(struct pci_dev *pdev, - const struct pci_device_id *id); -static void langwell_otg_remove(struct pci_dev *pdev); -static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message); -static int langwell_otg_resume(struct pci_dev *pdev); - -static int langwell_otg_set_host(struct otg_transceiver *otg, - struct usb_bus *host); -static int langwell_otg_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget); -static int langwell_otg_start_srp(struct otg_transceiver *otg); - -static const struct pci_device_id pci_ids[] = {{ - .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), - .class_mask = ~0, - .vendor = 0x8086, - .device = 0x0811, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, -}, { /* end: all zeroes */ } -}; - -static struct pci_driver otg_pci_driver = { - .name = (char *) driver_name, - .id_table = pci_ids, - - .probe = langwell_otg_probe, - .remove = langwell_otg_remove, - - .suspend = langwell_otg_suspend, - .resume = langwell_otg_resume, -}; - -/* HSM timers */ -static inline struct langwell_otg_timer *otg_timer_initializer -(void (*function)(unsigned long), unsigned long expires, unsigned long data) -{ - struct langwell_otg_timer *timer; - timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL); - if (timer == NULL) - return timer; - - timer->function = function; - timer->expires = expires; - timer->data = data; - return timer; -} - -static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr, - *b_se0_srp_tmr, *b_srp_init_tmr; - -static struct list_head active_timers; - -static struct langwell_otg *the_transceiver; - -/* host/client notify transceiver when event affects HNP state */ -void langwell_update_transceiver(void) -{ - struct langwell_otg *lnw = the_transceiver; - - dev_dbg(lnw->dev, "transceiver is updated\n"); - - if (!lnw->qwork) - return ; - - queue_work(lnw->qwork, &lnw->work); -} -EXPORT_SYMBOL(langwell_update_transceiver); - -static int langwell_otg_set_host(struct otg_transceiver *otg, - struct usb_bus *host) -{ - otg->host = host; - - return 0; -} - -static int langwell_otg_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget) -{ - otg->gadget = gadget; - - return 0; -} - -static int langwell_otg_set_power(struct otg_transceiver *otg, - unsigned mA) -{ - return 0; -} - -/* A-device drives vbus, controlled through IPC commands */ -static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled) -{ - struct langwell_otg *lnw = the_transceiver; - u8 sub_id; - - dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off"); - - if (enabled) - sub_id = 0x8; /* Turn on the VBus */ - else - sub_id = 0x9; /* Turn off the VBus */ - - if (intel_scu_ipc_simple_command(0xef, sub_id)) { - dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n"); - return -EBUSY; - } - - dev_dbg(lnw->dev, "%s --->\n", __func__); - - return 0; -} - -/* charge vbus or discharge vbus through a resistor to ground */ -static void langwell_otg_chrg_vbus(int on) -{ - struct langwell_otg *lnw = the_transceiver; - u32 val; - - val = readl(lnw->iotg.base + CI_OTGSC); - - if (on) - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, - lnw->iotg.base + CI_OTGSC); - else - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, - lnw->iotg.base + CI_OTGSC); -} - -/* Start SRP */ -static int langwell_otg_start_srp(struct otg_transceiver *otg) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s --->\n", __func__); - - val = readl(iotg->base + CI_OTGSC); - - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, - iotg->base + CI_OTGSC); - - /* Check if the data plus is finished or not */ - msleep(8); - val = readl(iotg->base + CI_OTGSC); - if (val & (OTGSC_HADP | OTGSC_DP)) - dev_dbg(lnw->dev, "DataLine SRP Error\n"); - - /* Disable interrupt - b_sess_vld */ - val = readl(iotg->base + CI_OTGSC); - val &= (~(OTGSC_BSVIE | OTGSC_BSEIE)); - writel(val, iotg->base + CI_OTGSC); - - /* Start VBus SRP, drive vbus to generate VBus pulse */ - iotg->otg.set_vbus(&iotg->otg, true); - msleep(15); - iotg->otg.set_vbus(&iotg->otg, false); - - /* Enable interrupt - b_sess_vld*/ - val = readl(iotg->base + CI_OTGSC); - dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val); - - val |= (OTGSC_BSVIE | OTGSC_BSEIE); - writel(val, iotg->base + CI_OTGSC); - - /* If Vbus is valid, then update the hsm */ - if (val & OTGSC_BSV) { - dev_dbg(lnw->dev, "no b_sess_vld interrupt\n"); - - lnw->iotg.hsm.b_sess_vld = 1; - langwell_update_transceiver(); - } - - dev_dbg(lnw->dev, "%s <---\n", __func__); - return 0; -} - -/* stop SOF via bus_suspend */ -static void langwell_otg_loc_sof(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct usb_hcd *hcd; - int err; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume"); - - hcd = bus_to_hcd(lnw->iotg.otg.host); - if (on) - err = hcd->driver->bus_resume(hcd); - else - err = hcd->driver->bus_suspend(hcd); - - if (err) - dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err); - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -static int langwell_otg_check_otgsc(void) -{ - struct langwell_otg *lnw = the_transceiver; - u32 otgsc, usbcfg; - - dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n"); - - otgsc = readl(lnw->iotg.base + CI_OTGSC); - usbcfg = readl(lnw->usbcfg); - - dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n", - otgsc, usbcfg); - dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV)); - dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n", - !!(usbcfg & USBCFG_VBUSVAL)); - dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV)); - dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n", - !!(usbcfg & USBCFG_AVALID)); - dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV)); - dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n", - !!(usbcfg & USBCFG_BVALID)); - dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE)); - dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n", - !!(usbcfg & USBCFG_SESEND)); - - /* Check USBCFG VBusValid/AValid/BValid/SessEnd */ - if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) { - dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n"); - goto err; - } - if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) { - dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n"); - goto err; - } - if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) { - dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n"); - goto err; - } - if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) { - dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n"); - goto err; - } - - dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n"); - - return 0; - -err: - dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n"); - return -EPIPE; -} - - -static void langwell_otg_phy_low_power(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u8 val, phcd; - int retval; - - dev_dbg(lnw->dev, "%s ---> %s mode\n", - __func__, on ? "Low power" : "Normal"); - - phcd = 0x40; - - val = readb(iotg->base + CI_HOSTPC1 + 2); - - if (on) { - /* Due to hardware issue, after set PHCD, sync will failed - * between USBCFG and OTGSC, so before set PHCD, check if - * sync is in process now. If the answer is "yes", then do - * not touch PHCD bit */ - retval = langwell_otg_check_otgsc(); - if (retval) { - dev_dbg(lnw->dev, "Skip PHCD programming..\n"); - return ; - } - - writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2); - } else - writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2); - - dev_dbg(lnw->dev, "%s <--- done\n", __func__); -} - -/* After drv vbus, add 5 ms delay to set PHCD */ -static void langwell_otg_phy_low_power_wait(int on) -{ - struct langwell_otg *lnw = the_transceiver; - - dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n"); - - mdelay(5); - langwell_otg_phy_low_power(on); -} - -/* Enable/Disable OTG interrupt */ -static void langwell_otg_intr(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - - val = readl(iotg->base + CI_OTGSC); - - /* OTGSC_INT_MASK doesn't contains 1msInt */ - if (on) { - val = val | (OTGSC_INT_MASK); - writel(val, iotg->base + CI_OTGSC); - } else { - val = val & ~(OTGSC_INT_MASK); - writel(val, iotg->base + CI_OTGSC); - } - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -/* set HAAR: Hardware Assist Auto-Reset */ -static void langwell_otg_HAAR(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - - val = readl(iotg->base + CI_OTGSC); - if (on) - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, - iotg->base + CI_OTGSC); - else - writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, - iotg->base + CI_OTGSC); - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -/* set HABA: Hardware Assist B-Disconnect to A-Connect */ -static void langwell_otg_HABA(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - - val = readl(iotg->base + CI_OTGSC); - if (on) - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, - iotg->base + CI_OTGSC); - else - writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, - iotg->base + CI_OTGSC); - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -static int langwell_otg_check_se0_srp(int on) -{ - struct langwell_otg *lnw = the_transceiver; - int delay_time = TB_SE0_SRP * 10; - u32 val; - - dev_dbg(lnw->dev, "%s --->\n", __func__); - - do { - udelay(100); - if (!delay_time--) - break; - val = readl(lnw->iotg.base + CI_PORTSC1); - val &= PORTSC_LS; - } while (!val); - - dev_dbg(lnw->dev, "%s <---\n", __func__); - return val; -} - -/* The timeout callback function to set time out bit */ -static void set_tmout(unsigned long indicator) -{ - *(int *)indicator = 1; -} - -void langwell_otg_nsf_msg(unsigned long indicator) -{ - struct langwell_otg *lnw = the_transceiver; - - switch (indicator) { - case 2: - case 4: - case 6: - case 7: - dev_warn(lnw->dev, - "OTG:NSF-%lu - deivce not responding\n", indicator); - break; - case 3: - dev_warn(lnw->dev, - "OTG:NSF-%lu - deivce not supported\n", indicator); - break; - default: - dev_warn(lnw->dev, "Do not have this kind of NSF\n"); - break; - } -} - -/* Initialize timers */ -static int langwell_otg_init_timers(struct otg_hsm *hsm) -{ - /* HSM used timers */ - a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, - (unsigned long)&hsm->a_wait_vrise_tmout); - if (a_wait_vrise_tmr == NULL) - return -ENOMEM; - a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, - (unsigned long)&hsm->a_aidl_bdis_tmout); - if (a_aidl_bdis_tmr == NULL) - return -ENOMEM; - b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, - (unsigned long)&hsm->b_se0_srp); - if (b_se0_srp_tmr == NULL) - return -ENOMEM; - b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT, - (unsigned long)&hsm->b_srp_init_tmout); - if (b_srp_init_tmr == NULL) - return -ENOMEM; - - return 0; -} - -/* Free timers */ -static void langwell_otg_free_timers(void) -{ - kfree(a_wait_vrise_tmr); - kfree(a_aidl_bdis_tmr); - kfree(b_se0_srp_tmr); - kfree(b_srp_init_tmr); -} - -/* The timeout callback function to set time out bit */ -static void langwell_otg_timer_fn(unsigned long indicator) -{ - struct langwell_otg *lnw = the_transceiver; - - *(int *)indicator = 1; - - dev_dbg(lnw->dev, "kernel timer - timeout\n"); - - langwell_update_transceiver(); -} - -/* kernel timer used instead of HW based interrupt */ -static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - unsigned long j = jiffies; - unsigned long data, time; - - switch (timers) { - case TA_WAIT_VRISE_TMR: - iotg->hsm.a_wait_vrise_tmout = 0; - data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout; - time = TA_WAIT_VRISE; - break; - case TA_WAIT_BCON_TMR: - iotg->hsm.a_wait_bcon_tmout = 0; - data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout; - time = TA_WAIT_BCON; - break; - case TA_AIDL_BDIS_TMR: - iotg->hsm.a_aidl_bdis_tmout = 0; - data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout; - time = TA_AIDL_BDIS; - break; - case TB_ASE0_BRST_TMR: - iotg->hsm.b_ase0_brst_tmout = 0; - data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout; - time = TB_ASE0_BRST; - break; - case TB_SRP_INIT_TMR: - iotg->hsm.b_srp_init_tmout = 0; - data = (unsigned long)&iotg->hsm.b_srp_init_tmout; - time = TB_SRP_INIT; - break; - case TB_SRP_FAIL_TMR: - iotg->hsm.b_srp_fail_tmout = 0; - data = (unsigned long)&iotg->hsm.b_srp_fail_tmout; - time = TB_SRP_FAIL; - break; - case TB_BUS_SUSPEND_TMR: - iotg->hsm.b_bus_suspend_tmout = 0; - data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout; - time = TB_BUS_SUSPEND; - break; - default: - dev_dbg(lnw->dev, "unknown timer, cannot enable it\n"); - return; - } - - lnw->hsm_timer.data = data; - lnw->hsm_timer.function = langwell_otg_timer_fn; - lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */ - - add_timer(&lnw->hsm_timer); - - dev_dbg(lnw->dev, "add timer successfully\n"); -} - -/* Add timer to timer list */ -static void langwell_otg_add_timer(void *gtimer) -{ - struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; - struct langwell_otg_timer *tmp_timer; - struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg; - u32 val32; - - /* Check if the timer is already in the active list, - * if so update timer count - */ - list_for_each_entry(tmp_timer, &active_timers, list) - if (tmp_timer == timer) { - timer->count = timer->expires; - return; - } - timer->count = timer->expires; - - if (list_empty(&active_timers)) { - val32 = readl(iotg->base + CI_OTGSC); - writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC); - } - - list_add_tail(&timer->list, &active_timers); -} - -/* Remove timer from the timer list; clear timeout status */ -static void langwell_otg_del_timer(void *gtimer) -{ - struct langwell_otg *lnw = the_transceiver; - struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; - struct langwell_otg_timer *tmp_timer, *del_tmp; - u32 val32; - - list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) - if (tmp_timer == timer) - list_del(&timer->list); - - if (list_empty(&active_timers)) { - val32 = readl(lnw->iotg.base + CI_OTGSC); - writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC); - } -} - -/* Reduce timer count by 1, and find timeout conditions.*/ -static int langwell_otg_tick_timer(u32 *int_sts) -{ - struct langwell_otg *lnw = the_transceiver; - struct langwell_otg_timer *tmp_timer, *del_tmp; - int expired = 0; - - list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { - tmp_timer->count--; - /* check if timer expires */ - if (!tmp_timer->count) { - list_del(&tmp_timer->list); - tmp_timer->function(tmp_timer->data); - expired = 1; - } - } - - if (list_empty(&active_timers)) { - dev_dbg(lnw->dev, "tick timer: disable 1ms int\n"); - *int_sts = *int_sts & ~OTGSC_1MSE; - } - return expired; -} - -static void reset_otg(void) -{ - struct langwell_otg *lnw = the_transceiver; - int delay_time = 1000; - u32 val; - - dev_dbg(lnw->dev, "reseting OTG controller ...\n"); - val = readl(lnw->iotg.base + CI_USBCMD); - writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD); - do { - udelay(100); - if (!delay_time--) - dev_dbg(lnw->dev, "reset timeout\n"); - val = readl(lnw->iotg.base + CI_USBCMD); - val &= USBCMD_RST; - } while (val != 0); - dev_dbg(lnw->dev, "reset done.\n"); -} - -static void set_host_mode(void) -{ - struct langwell_otg *lnw = the_transceiver; - u32 val; - - reset_otg(); - val = readl(lnw->iotg.base + CI_USBMODE); - val = (val & (~USBMODE_CM)) | USBMODE_HOST; - writel(val, lnw->iotg.base + CI_USBMODE); -} - -static void set_client_mode(void) -{ - struct langwell_otg *lnw = the_transceiver; - u32 val; - - reset_otg(); - val = readl(lnw->iotg.base + CI_USBMODE); - val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; - writel(val, lnw->iotg.base + CI_USBMODE); -} - -static void init_hsm(void) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val32; - - /* read OTGSC after reset */ - val32 = readl(lnw->iotg.base + CI_OTGSC); - dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32); - - /* set init state */ - if (val32 & OTGSC_ID) { - iotg->hsm.id = 1; - iotg->otg.default_a = 0; - set_client_mode(); - iotg->otg.state = OTG_STATE_B_IDLE; - } else { - iotg->hsm.id = 0; - iotg->otg.default_a = 1; - set_host_mode(); - iotg->otg.state = OTG_STATE_A_IDLE; - } - - /* set session indicator */ - if (val32 & OTGSC_BSE) - iotg->hsm.b_sess_end = 1; - if (val32 & OTGSC_BSV) - iotg->hsm.b_sess_vld = 1; - if (val32 & OTGSC_ASV) - iotg->hsm.a_sess_vld = 1; - if (val32 & OTGSC_AVV) - iotg->hsm.a_vbus_vld = 1; - - /* defautly power the bus */ - iotg->hsm.a_bus_req = 1; - iotg->hsm.a_bus_drop = 0; - /* defautly don't request bus as B device */ - iotg->hsm.b_bus_req = 0; - /* no system error */ - iotg->hsm.a_clr_err = 0; - - langwell_otg_phy_low_power_wait(1); -} - -static void update_hsm(void) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val32; - - /* read OTGSC */ - val32 = readl(lnw->iotg.base + CI_OTGSC); - dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); - - iotg->hsm.id = !!(val32 & OTGSC_ID); - iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE); - iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV); - iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV); - iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV); -} - -static irqreturn_t otg_dummy_irq(int irq, void *_dev) -{ - struct langwell_otg *lnw = the_transceiver; - void __iomem *reg_base = _dev; - u32 val; - u32 int_mask = 0; - - val = readl(reg_base + CI_USBMODE); - if ((val & USBMODE_CM) != USBMODE_DEVICE) - return IRQ_NONE; - - val = readl(reg_base + CI_USBSTS); - int_mask = val & INTR_DUMMY_MASK; - - if (int_mask == 0) - return IRQ_NONE; - - /* clear hsm.b_conn here since host driver can't detect it - * otg_dummy_irq called means B-disconnect happened. - */ - if (lnw->iotg.hsm.b_conn) { - lnw->iotg.hsm.b_conn = 0; - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - } - - /* Clear interrupts */ - writel(int_mask, reg_base + CI_USBSTS); - return IRQ_HANDLED; -} - -static irqreturn_t otg_irq(int irq, void *_dev) -{ - struct langwell_otg *lnw = _dev; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 int_sts, int_en; - u32 int_mask = 0; - int flag = 0; - - int_sts = readl(lnw->iotg.base + CI_OTGSC); - int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; - int_mask = int_sts & int_en; - if (int_mask == 0) - return IRQ_NONE; - - if (int_mask & OTGSC_IDIS) { - dev_dbg(lnw->dev, "%s: id change int\n", __func__); - iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; - dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id); - flag = 1; - } - if (int_mask & OTGSC_DPIS) { - dev_dbg(lnw->dev, "%s: data pulse int\n", __func__); - iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; - dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det); - flag = 1; - } - if (int_mask & OTGSC_BSEIS) { - dev_dbg(lnw->dev, "%s: b session end int\n", __func__); - iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; - dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end); - flag = 1; - } - if (int_mask & OTGSC_BSVIS) { - dev_dbg(lnw->dev, "%s: b session valid int\n", __func__); - iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; - dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end); - flag = 1; - } - if (int_mask & OTGSC_ASVIS) { - dev_dbg(lnw->dev, "%s: a session valid int\n", __func__); - iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; - dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld); - flag = 1; - } - if (int_mask & OTGSC_AVVIS) { - dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__); - iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; - dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld); - flag = 1; - } - - if (int_mask & OTGSC_1MSS) { - /* need to schedule otg_work if any timer is expired */ - if (langwell_otg_tick_timer(&int_sts)) - flag = 1; - } - - writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, - lnw->iotg.base + CI_OTGSC); - if (flag) - langwell_update_transceiver(); - - return IRQ_HANDLED; -} - -static int langwell_otg_iotg_notify(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = data; - int flag = 0; - - if (iotg == NULL) - return NOTIFY_BAD; - - if (lnw == NULL) - return NOTIFY_BAD; - - switch (action) { - case MID_OTG_NOTIFY_CONNECT: - dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_conn = 1; - else - iotg->hsm.a_conn = 1; - flag = 1; - break; - case MID_OTG_NOTIFY_DISCONN: - dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_conn = 0; - else - iotg->hsm.a_conn = 0; - flag = 1; - break; - case MID_OTG_NOTIFY_HSUSPEND: - dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.a_suspend_req = 1; - else - iotg->hsm.b_bus_req = 0; - flag = 1; - break; - case MID_OTG_NOTIFY_HRESUME: - dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_bus_resume = 1; - flag = 1; - break; - case MID_OTG_NOTIFY_CSUSPEND: - dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n"); - if (iotg->otg.default_a == 1) { - if (iotg->hsm.b_bus_suspend_vld == 2) { - iotg->hsm.b_bus_suspend = 1; - iotg->hsm.b_bus_suspend_vld = 0; - flag = 1; - } else { - iotg->hsm.b_bus_suspend_vld++; - flag = 0; - } - } else { - if (iotg->hsm.a_bus_suspend == 0) { - iotg->hsm.a_bus_suspend = 1; - flag = 1; - } - } - break; - case MID_OTG_NOTIFY_CRESUME: - dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n"); - if (iotg->otg.default_a == 0) - iotg->hsm.a_bus_suspend = 0; - flag = 0; - break; - case MID_OTG_NOTIFY_HOSTADD: - dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n"); - flag = 1; - break; - case MID_OTG_NOTIFY_HOSTREMOVE: - dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n"); - flag = 1; - break; - case MID_OTG_NOTIFY_CLIENTADD: - dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n"); - flag = 1; - break; - case MID_OTG_NOTIFY_CLIENTREMOVE: - dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n"); - flag = 1; - break; - default: - dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n"); - return NOTIFY_DONE; - } - - if (flag) - langwell_update_transceiver(); - - return NOTIFY_OK; -} - -static void langwell_otg_work(struct work_struct *work) -{ - struct langwell_otg *lnw; - struct intel_mid_otg_xceiv *iotg; - int retval; - struct pci_dev *pdev; - - lnw = container_of(work, struct langwell_otg, work); - iotg = &lnw->iotg; - pdev = to_pci_dev(lnw->dev); - - dev_dbg(lnw->dev, "%s: old state = %s\n", __func__, - otg_state_string(iotg->otg.state)); - - switch (iotg->otg.state) { - case OTG_STATE_UNDEFINED: - case OTG_STATE_B_IDLE: - if (!iotg->hsm.id) { - langwell_otg_del_timer(b_srp_init_tmr); - del_timer_sync(&lnw->hsm_timer); - - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - set_host_mode(); - langwell_otg_phy_low_power(1); - - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.b_sess_vld) { - langwell_otg_del_timer(b_srp_init_tmr); - del_timer_sync(&lnw->hsm_timer); - iotg->hsm.b_sess_end = 0; - iotg->hsm.a_bus_suspend = 0; - langwell_otg_chrg_vbus(0); - - if (lnw->iotg.start_peripheral) { - lnw->iotg.start_peripheral(&lnw->iotg); - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } else - dev_dbg(lnw->dev, "client driver not loaded\n"); - - } else if (iotg->hsm.b_srp_init_tmout) { - iotg->hsm.b_srp_init_tmout = 0; - dev_warn(lnw->dev, "SRP init timeout\n"); - } else if (iotg->hsm.b_srp_fail_tmout) { - iotg->hsm.b_srp_fail_tmout = 0; - iotg->hsm.b_bus_req = 0; - - /* No silence failure */ - langwell_otg_nsf_msg(6); - } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) { - del_timer_sync(&lnw->hsm_timer); - /* workaround for b_se0_srp detection */ - retval = langwell_otg_check_se0_srp(0); - if (retval) { - iotg->hsm.b_bus_req = 0; - dev_dbg(lnw->dev, "LS isn't SE0, try later\n"); - } else { - /* clear the PHCD before start srp */ - langwell_otg_phy_low_power(0); - - /* Start SRP */ - langwell_otg_add_timer(b_srp_init_tmr); - iotg->otg.start_srp(&iotg->otg); - langwell_otg_del_timer(b_srp_init_tmr); - langwell_otg_add_ktimer(TB_SRP_FAIL_TMR); - - /* reset PHY low power mode here */ - langwell_otg_phy_low_power_wait(1); - } - } - break; - case OTG_STATE_B_SRP_INIT: - if (!iotg->hsm.id) { - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_chrg_vbus(0); - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.b_sess_vld) { - langwell_otg_chrg_vbus(0); - if (lnw->iotg.start_peripheral) { - lnw->iotg.start_peripheral(&lnw->iotg); - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } else - dev_dbg(lnw->dev, "client driver not loaded\n"); - } - break; - case OTG_STATE_B_PERIPHERAL: - if (!iotg->hsm.id) { - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.b_sess_vld) { - iotg->hsm.b_hnp_enable = 0; - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - iotg->otg.state = OTG_STATE_B_IDLE; - } else if (iotg->hsm.b_bus_req && iotg->otg.gadget && - iotg->otg.gadget->b_hnp_enable && - iotg->hsm.a_bus_suspend) { - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - langwell_otg_HAAR(1); - iotg->hsm.a_conn = 0; - - if (lnw->iotg.start_host) { - lnw->iotg.start_host(&lnw->iotg); - iotg->otg.state = OTG_STATE_B_WAIT_ACON; - } else - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - - iotg->hsm.a_bus_resume = 0; - langwell_otg_add_ktimer(TB_ASE0_BRST_TMR); - } - break; - - case OTG_STATE_B_WAIT_ACON: - if (!iotg->hsm.id) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - - langwell_otg_HAAR(0); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.b_sess_vld) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->hsm.b_hnp_enable = 0; - iotg->hsm.b_bus_req = 0; - - langwell_otg_chrg_vbus(0); - langwell_otg_HAAR(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - } else if (iotg->hsm.a_conn) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - langwell_otg_HAAR(0); - iotg->otg.state = OTG_STATE_B_HOST; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_resume || - iotg->hsm.b_ase0_brst_tmout) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - langwell_otg_HAAR(0); - langwell_otg_nsf_msg(7); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - iotg->hsm.a_bus_suspend = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.start_peripheral) - lnw->iotg.start_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver not loaded.\n"); - - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } - break; - - case OTG_STATE_B_HOST: - if (!iotg->hsm.id) { - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.b_sess_vld) { - iotg->hsm.b_hnp_enable = 0; - iotg->hsm.b_bus_req = 0; - - langwell_otg_chrg_vbus(0); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - } else if ((!iotg->hsm.b_bus_req) || - (!iotg->hsm.a_conn)) { - iotg->hsm.b_bus_req = 0; - langwell_otg_loc_sof(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - iotg->hsm.a_bus_suspend = 0; - - if (lnw->iotg.start_peripheral) - lnw->iotg.start_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver not loaded.\n"); - - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } - break; - - case OTG_STATE_A_IDLE: - iotg->otg.default_a = 1; - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - iotg->hsm.vbus_srp_up = 0; - - langwell_otg_chrg_vbus(0); - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_bus_drop && - (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) { - langwell_otg_phy_low_power(0); - - /* Turn on VBus */ - iotg->otg.set_vbus(&iotg->otg, true); - - iotg->hsm.vbus_srp_up = 0; - iotg->hsm.a_wait_vrise_tmout = 0; - langwell_otg_add_timer(a_wait_vrise_tmr); - iotg->otg.state = OTG_STATE_A_WAIT_VRISE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) { - iotg->hsm.vbus_srp_up = 1; - } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) { - msleep(10); - langwell_otg_phy_low_power(0); - - /* Turn on VBus */ - iotg->otg.set_vbus(&iotg->otg, true); - iotg->hsm.a_srp_det = 1; - iotg->hsm.vbus_srp_up = 0; - iotg->hsm.a_wait_vrise_tmout = 0; - langwell_otg_add_timer(a_wait_vrise_tmr); - iotg->otg.state = OTG_STATE_A_WAIT_VRISE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_sess_vld && - !iotg->hsm.vbus_srp_up) { - langwell_otg_phy_low_power(1); - } - break; - case OTG_STATE_A_WAIT_VRISE: - if (iotg->hsm.id) { - langwell_otg_del_timer(a_wait_vrise_tmr); - iotg->hsm.b_bus_req = 0; - iotg->otg.default_a = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - } else if (iotg->hsm.a_vbus_vld) { - langwell_otg_del_timer(a_wait_vrise_tmr); - iotg->hsm.b_conn = 0; - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else { - dev_dbg(lnw->dev, "host driver not loaded.\n"); - break; - } - - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } else if (iotg->hsm.a_wait_vrise_tmout) { - iotg->hsm.b_conn = 0; - if (iotg->hsm.a_vbus_vld) { - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else { - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - break; - } - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } else { - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } - } - break; - case OTG_STATE_A_WAIT_BCON: - if (iotg->hsm.id) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_vbus_vld) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (iotg->hsm.a_bus_drop || - (iotg->hsm.a_wait_bcon_tmout && - !iotg->hsm.a_bus_req)) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (iotg->hsm.b_conn) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->hsm.a_suspend_req = 0; - iotg->otg.state = OTG_STATE_A_HOST; - if (iotg->hsm.a_srp_det && iotg->otg.host && - !iotg->otg.host->b_hnp_enable) { - /* SRP capable peripheral-only device */ - iotg->hsm.a_bus_req = 1; - iotg->hsm.a_srp_det = 0; - } else if (!iotg->hsm.a_bus_req && iotg->otg.host && - iotg->otg.host->b_hnp_enable) { - /* It is not safe enough to do a fast - * transition from A_WAIT_BCON to - * A_SUSPEND */ - msleep(10000); - if (iotg->hsm.a_bus_req) - break; - - if (request_irq(pdev->irq, - otg_dummy_irq, IRQF_SHARED, - driver_name, iotg->base) != 0) { - dev_dbg(lnw->dev, - "request interrupt %d fail\n", - pdev->irq); - } - - langwell_otg_HABA(1); - iotg->hsm.b_bus_resume = 0; - iotg->hsm.a_aidl_bdis_tmout = 0; - - langwell_otg_loc_sof(0); - /* clear PHCD to enable HW timer */ - langwell_otg_phy_low_power(0); - langwell_otg_add_timer(a_aidl_bdis_tmr); - iotg->otg.state = OTG_STATE_A_SUSPEND; - } else if (!iotg->hsm.a_bus_req && iotg->otg.host && - !iotg->otg.host->b_hnp_enable) { - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } - } - break; - case OTG_STATE_A_HOST: - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_drop || - (iotg->otg.host && - !iotg->otg.host->b_hnp_enable && - !iotg->hsm.a_bus_req)) { - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (!iotg->hsm.a_vbus_vld) { - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (iotg->otg.host && - iotg->otg.host->b_hnp_enable && - !iotg->hsm.a_bus_req) { - /* Set HABA to enable hardware assistance to signal - * A-connect after receiver B-disconnect. Hardware - * will then set client mode and enable URE, SLE and - * PCE after the assistance. otg_dummy_irq is used to - * clean these ints when client driver is not resumed. - */ - if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED, - driver_name, iotg->base) != 0) { - dev_dbg(lnw->dev, - "request interrupt %d failed\n", - pdev->irq); - } - - /* set HABA */ - langwell_otg_HABA(1); - iotg->hsm.b_bus_resume = 0; - iotg->hsm.a_aidl_bdis_tmout = 0; - langwell_otg_loc_sof(0); - /* clear PHCD to enable HW timer */ - langwell_otg_phy_low_power(0); - langwell_otg_add_timer(a_aidl_bdis_tmr); - iotg->otg.state = OTG_STATE_A_SUSPEND; - } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) { - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } - break; - case OTG_STATE_A_SUSPEND: - if (iotg->hsm.id) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_req || - iotg->hsm.b_bus_resume) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - iotg->hsm.a_suspend_req = 0; - langwell_otg_loc_sof(1); - iotg->otg.state = OTG_STATE_A_HOST; - } else if (iotg->hsm.a_aidl_bdis_tmout || - iotg->hsm.a_bus_drop) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (!iotg->hsm.b_conn && iotg->otg.host && - iotg->otg.host->b_hnp_enable) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - iotg->hsm.b_bus_suspend = 0; - iotg->hsm.b_bus_suspend_vld = 0; - - /* msleep(200); */ - if (lnw->iotg.start_peripheral) - lnw->iotg.start_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver not loaded.\n"); - - langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR); - iotg->otg.state = OTG_STATE_A_PERIPHERAL; - break; - } else if (!iotg->hsm.a_vbus_vld) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } - break; - case OTG_STATE_A_PERIPHERAL: - if (iotg->hsm.id) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_vbus_vld) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (iotg->hsm.a_bus_drop) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (iotg->hsm.b_bus_suspend) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } else if (iotg->hsm.b_bus_suspend_tmout) { - u32 val; - val = readl(lnw->iotg.base + CI_PORTSC1); - if (!(val & PORTSC_SUSP)) - break; - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } - break; - case OTG_STATE_A_VBUS_ERR: - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - iotg->hsm.a_clr_err = 0; - iotg->hsm.a_srp_det = 0; - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_clr_err) { - iotg->hsm.a_clr_err = 0; - iotg->hsm.a_srp_det = 0; - reset_otg(); - init_hsm(); - if (iotg->otg.state == OTG_STATE_A_IDLE) - langwell_update_transceiver(); - } else { - /* FW will clear PHCD bit when any VBus - * event detected. Reset PHCD to 1 again */ - langwell_otg_phy_low_power(1); - } - break; - case OTG_STATE_A_WAIT_VFALL: - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_req) { - - /* Turn on VBus */ - iotg->otg.set_vbus(&iotg->otg, true); - iotg->hsm.a_wait_vrise_tmout = 0; - langwell_otg_add_timer(a_wait_vrise_tmr); - iotg->otg.state = OTG_STATE_A_WAIT_VRISE; - } else if (!iotg->hsm.a_sess_vld) { - iotg->hsm.a_srp_det = 0; - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - } - break; - default: - ; - } - - dev_dbg(lnw->dev, "%s: new state = %s\n", __func__, - otg_state_string(iotg->otg.state)); -} - -static ssize_t -show_registers(struct device *_dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, - "\n" - "USBCMD = 0x%08x\n" - "USBSTS = 0x%08x\n" - "USBINTR = 0x%08x\n" - "ASYNCLISTADDR = 0x%08x\n" - "PORTSC1 = 0x%08x\n" - "HOSTPC1 = 0x%08x\n" - "OTGSC = 0x%08x\n" - "USBMODE = 0x%08x\n", - readl(lnw->iotg.base + 0x30), - readl(lnw->iotg.base + 0x34), - readl(lnw->iotg.base + 0x38), - readl(lnw->iotg.base + 0x48), - readl(lnw->iotg.base + 0x74), - readl(lnw->iotg.base + 0xb4), - readl(lnw->iotg.base + 0xf4), - readl(lnw->iotg.base + 0xf8) - ); - size -= t; - next += t; - - return PAGE_SIZE - size; -} -static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); - -static ssize_t -show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - if (iotg->otg.host) - iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable; - - if (iotg->otg.gadget) - iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable; - - t = scnprintf(next, size, - "\n" - "current state = %s\n" - "a_bus_resume = \t%d\n" - "a_bus_suspend = \t%d\n" - "a_conn = \t%d\n" - "a_sess_vld = \t%d\n" - "a_srp_det = \t%d\n" - "a_vbus_vld = \t%d\n" - "b_bus_resume = \t%d\n" - "b_bus_suspend = \t%d\n" - "b_conn = \t%d\n" - "b_se0_srp = \t%d\n" - "b_sess_end = \t%d\n" - "b_sess_vld = \t%d\n" - "id = \t%d\n" - "a_set_b_hnp_en = \t%d\n" - "b_srp_done = \t%d\n" - "b_hnp_enable = \t%d\n" - "a_wait_vrise_tmout = \t%d\n" - "a_wait_bcon_tmout = \t%d\n" - "a_aidl_bdis_tmout = \t%d\n" - "b_ase0_brst_tmout = \t%d\n" - "a_bus_drop = \t%d\n" - "a_bus_req = \t%d\n" - "a_clr_err = \t%d\n" - "a_suspend_req = \t%d\n" - "b_bus_req = \t%d\n" - "b_bus_suspend_tmout = \t%d\n" - "b_bus_suspend_vld = \t%d\n", - otg_state_string(iotg->otg.state), - iotg->hsm.a_bus_resume, - iotg->hsm.a_bus_suspend, - iotg->hsm.a_conn, - iotg->hsm.a_sess_vld, - iotg->hsm.a_srp_det, - iotg->hsm.a_vbus_vld, - iotg->hsm.b_bus_resume, - iotg->hsm.b_bus_suspend, - iotg->hsm.b_conn, - iotg->hsm.b_se0_srp, - iotg->hsm.b_sess_end, - iotg->hsm.b_sess_vld, - iotg->hsm.id, - iotg->hsm.a_set_b_hnp_en, - iotg->hsm.b_srp_done, - iotg->hsm.b_hnp_enable, - iotg->hsm.a_wait_vrise_tmout, - iotg->hsm.a_wait_bcon_tmout, - iotg->hsm.a_aidl_bdis_tmout, - iotg->hsm.b_ase0_brst_tmout, - iotg->hsm.a_bus_drop, - iotg->hsm.a_bus_req, - iotg->hsm.a_clr_err, - iotg->hsm.a_suspend_req, - iotg->hsm.b_bus_req, - iotg->hsm.b_bus_suspend_tmout, - iotg->hsm.b_bus_suspend_vld - ); - size -= t; - next += t; - - return PAGE_SIZE - size; -} -static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL); - -static ssize_t -get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req); - size -= t; - next += t; - - return PAGE_SIZE - size; -} - -static ssize_t -set_a_bus_req(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (!iotg->otg.default_a) - return -1; - if (count > 2) - return -1; - - if (buf[0] == '0') { - iotg->hsm.a_bus_req = 0; - dev_dbg(lnw->dev, "User request: a_bus_req = 0\n"); - } else if (buf[0] == '1') { - /* If a_bus_drop is TRUE, a_bus_req can't be set */ - if (iotg->hsm.a_bus_drop) - return -1; - iotg->hsm.a_bus_req = 1; - dev_dbg(lnw->dev, "User request: a_bus_req = 1\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req); - -static ssize_t -get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop); - size -= t; - next += t; - - return PAGE_SIZE - size; -} - -static ssize_t -set_a_bus_drop(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (!iotg->otg.default_a) - return -1; - if (count > 2) - return -1; - - if (buf[0] == '0') { - iotg->hsm.a_bus_drop = 0; - dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n"); - } else if (buf[0] == '1') { - iotg->hsm.a_bus_drop = 1; - iotg->hsm.a_bus_req = 0; - dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n"); - dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop); - -static ssize_t -get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req); - size -= t; - next += t; - - return PAGE_SIZE - size; -} - -static ssize_t -set_b_bus_req(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (iotg->otg.default_a) - return -1; - - if (count > 2) - return -1; - - if (buf[0] == '0') { - iotg->hsm.b_bus_req = 0; - dev_dbg(lnw->dev, "User request: b_bus_req = 0\n"); - } else if (buf[0] == '1') { - iotg->hsm.b_bus_req = 1; - dev_dbg(lnw->dev, "User request: b_bus_req = 1\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req); - -static ssize_t -set_a_clr_err(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (!iotg->otg.default_a) - return -1; - if (count > 2) - return -1; - - if (buf[0] == '1') { - iotg->hsm.a_clr_err = 1; - dev_dbg(lnw->dev, "User request: a_clr_err = 1\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err); - -static struct attribute *inputs_attrs[] = { - &dev_attr_a_bus_req.attr, - &dev_attr_a_bus_drop.attr, - &dev_attr_b_bus_req.attr, - &dev_attr_a_clr_err.attr, - NULL, -}; - -static struct attribute_group debug_dev_attr_group = { - .name = "inputs", - .attrs = inputs_attrs, -}; - -static int langwell_otg_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned long resource, len; - void __iomem *base = NULL; - int retval; - u32 val32; - struct langwell_otg *lnw; - char qname[] = "langwell_otg_queue"; - - retval = 0; - dev_dbg(&pdev->dev, "\notg controller is detected.\n"); - if (pci_enable_device(pdev) < 0) { - retval = -ENODEV; - goto done; - } - - lnw = kzalloc(sizeof *lnw, GFP_KERNEL); - if (lnw == NULL) { - retval = -ENOMEM; - goto done; - } - the_transceiver = lnw; - - /* control register: BAR 0 */ - resource = pci_resource_start(pdev, 0); - len = pci_resource_len(pdev, 0); - if (!request_mem_region(resource, len, driver_name)) { - retval = -EBUSY; - goto err; - } - lnw->region = 1; - - base = ioremap_nocache(resource, len); - if (base == NULL) { - retval = -EFAULT; - goto err; - } - lnw->iotg.base = base; - - if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) { - retval = -EBUSY; - goto err; - } - lnw->cfg_region = 1; - - /* For the SCCB.USBCFG register */ - base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN); - if (base == NULL) { - retval = -EFAULT; - goto err; - } - lnw->usbcfg = base; - - if (!pdev->irq) { - dev_dbg(&pdev->dev, "No IRQ.\n"); - retval = -ENODEV; - goto err; - } - - lnw->qwork = create_singlethread_workqueue(qname); - if (!lnw->qwork) { - dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname); - retval = -ENOMEM; - goto err; - } - INIT_WORK(&lnw->work, langwell_otg_work); - - /* OTG common part */ - lnw->dev = &pdev->dev; - lnw->iotg.otg.dev = lnw->dev; - lnw->iotg.otg.label = driver_name; - lnw->iotg.otg.set_host = langwell_otg_set_host; - lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral; - lnw->iotg.otg.set_power = langwell_otg_set_power; - lnw->iotg.otg.set_vbus = langwell_otg_set_vbus; - lnw->iotg.otg.start_srp = langwell_otg_start_srp; - lnw->iotg.otg.state = OTG_STATE_UNDEFINED; - - if (otg_set_transceiver(&lnw->iotg.otg)) { - dev_dbg(lnw->dev, "can't set transceiver\n"); - retval = -EBUSY; - goto err; - } - - reset_otg(); - init_hsm(); - - spin_lock_init(&lnw->lock); - spin_lock_init(&lnw->wq_lock); - INIT_LIST_HEAD(&active_timers); - retval = langwell_otg_init_timers(&lnw->iotg.hsm); - if (retval) { - dev_dbg(&pdev->dev, "Failed to init timers\n"); - goto err; - } - - init_timer(&lnw->hsm_timer); - ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier); - - lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify; - - retval = intel_mid_otg_register_notifier(&lnw->iotg, - &lnw->iotg_notifier); - if (retval) { - dev_dbg(lnw->dev, "Failed to register notifier\n"); - goto err; - } - - if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, - driver_name, lnw) != 0) { - dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq); - retval = -EBUSY; - goto err; - } - - /* enable OTGSC int */ - val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | - OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; - writel(val32, lnw->iotg.base + CI_OTGSC); - - retval = device_create_file(&pdev->dev, &dev_attr_registers); - if (retval < 0) { - dev_dbg(lnw->dev, - "Can't register sysfs attribute: %d\n", retval); - goto err; - } - - retval = device_create_file(&pdev->dev, &dev_attr_hsm); - if (retval < 0) { - dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval); - goto err; - } - - retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); - if (retval < 0) { - dev_dbg(lnw->dev, - "Can't register sysfs attr group: %d\n", retval); - goto err; - } - - if (lnw->iotg.otg.state == OTG_STATE_A_IDLE) - langwell_update_transceiver(); - - return 0; - -err: - if (the_transceiver) - langwell_otg_remove(pdev); -done: - return retval; -} - -static void langwell_otg_remove(struct pci_dev *pdev) -{ - struct langwell_otg *lnw = the_transceiver; - - if (lnw->qwork) { - flush_workqueue(lnw->qwork); - destroy_workqueue(lnw->qwork); - } - intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier); - langwell_otg_free_timers(); - - /* disable OTGSC interrupt as OTGSC doesn't change in reset */ - writel(0, lnw->iotg.base + CI_OTGSC); - - if (pdev->irq) - free_irq(pdev->irq, lnw); - if (lnw->usbcfg) - iounmap(lnw->usbcfg); - if (lnw->cfg_region) - release_mem_region(USBCFG_ADDR, USBCFG_LEN); - if (lnw->iotg.base) - iounmap(lnw->iotg.base); - if (lnw->region) - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - - otg_set_transceiver(NULL); - pci_disable_device(pdev); - sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); - device_remove_file(&pdev->dev, &dev_attr_hsm); - device_remove_file(&pdev->dev, &dev_attr_registers); - kfree(lnw); - lnw = NULL; -} - -static void transceiver_suspend(struct pci_dev *pdev) -{ - pci_save_state(pdev); - pci_set_power_state(pdev, PCI_D3hot); - langwell_otg_phy_low_power(1); -} - -static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - int ret = 0; - - /* Disbale OTG interrupts */ - langwell_otg_intr(0); - - if (pdev->irq) - free_irq(pdev->irq, lnw); - - /* Prevent more otg_work */ - flush_workqueue(lnw->qwork); - destroy_workqueue(lnw->qwork); - lnw->qwork = NULL; - - /* start actions */ - switch (iotg->otg.state) { - case OTG_STATE_A_WAIT_VFALL: - iotg->otg.state = OTG_STATE_A_IDLE; - case OTG_STATE_A_IDLE: - case OTG_STATE_B_IDLE: - case OTG_STATE_A_VBUS_ERR: - transceiver_suspend(pdev); - break; - case OTG_STATE_A_WAIT_VRISE: - langwell_otg_del_timer(a_wait_vrise_tmr); - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_WAIT_BCON: - del_timer_sync(&lnw->hsm_timer); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_HOST: - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_SUSPEND: - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, "host driver has been removed.\n"); - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_PERIPHERAL: - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(&pdev->dev, - "client driver has been removed.\n"); - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_B_HOST: - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - iotg->hsm.b_bus_req = 0; - iotg->otg.state = OTG_STATE_B_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_B_PERIPHERAL: - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(&pdev->dev, - "client driver has been removed.\n"); - iotg->otg.state = OTG_STATE_B_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_B_WAIT_ACON: - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - langwell_otg_HAAR(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - iotg->hsm.b_bus_req = 0; - iotg->otg.state = OTG_STATE_B_IDLE; - transceiver_suspend(pdev); - break; - default: - dev_dbg(lnw->dev, "error state before suspend\n"); - break; - } - - return ret; -} - -static void transceiver_resume(struct pci_dev *pdev) -{ - pci_restore_state(pdev); - pci_set_power_state(pdev, PCI_D0); -} - -static int langwell_otg_resume(struct pci_dev *pdev) -{ - struct langwell_otg *lnw = the_transceiver; - int ret = 0; - - transceiver_resume(pdev); - - lnw->qwork = create_singlethread_workqueue("langwell_otg_queue"); - if (!lnw->qwork) { - dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen"); - ret = -ENOMEM; - goto error; - } - - if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, - driver_name, lnw) != 0) { - dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq); - ret = -EBUSY; - goto error; - } - - /* enable OTG interrupts */ - langwell_otg_intr(1); - - update_hsm(); - - langwell_update_transceiver(); - - return ret; -error: - langwell_otg_intr(0); - transceiver_suspend(pdev); - return ret; -} - -static int __init langwell_otg_init(void) -{ - return pci_register_driver(&otg_pci_driver); -} -module_init(langwell_otg_init); - -static void __exit langwell_otg_cleanup(void) -{ - pci_unregister_driver(&otg_pci_driver); -} -module_exit(langwell_otg_cleanup); diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h deleted file mode 100644 index 51f17b16d312..000000000000 --- a/include/linux/usb/langwell_otg.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Intel Langwell USB OTG transceiver driver - * Copyright (C) 2008 - 2010, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __LANGWELL_OTG_H -#define __LANGWELL_OTG_H - -#include - -#define CI_USBCMD 0x30 -# define USBCMD_RST BIT(1) -# define USBCMD_RS BIT(0) -#define CI_USBSTS 0x34 -# define USBSTS_SLI BIT(8) -# define USBSTS_URI BIT(6) -# define USBSTS_PCI BIT(2) -#define CI_PORTSC1 0x74 -# define PORTSC_PP BIT(12) -# define PORTSC_LS (BIT(11) | BIT(10)) -# define PORTSC_SUSP BIT(7) -# define PORTSC_CCS BIT(0) -#define CI_HOSTPC1 0xb4 -# define HOSTPC1_PHCD BIT(22) -#define CI_OTGSC 0xf4 -# define OTGSC_DPIE BIT(30) -# define OTGSC_1MSE BIT(29) -# define OTGSC_BSEIE BIT(28) -# define OTGSC_BSVIE BIT(27) -# define OTGSC_ASVIE BIT(26) -# define OTGSC_AVVIE BIT(25) -# define OTGSC_IDIE BIT(24) -# define OTGSC_DPIS BIT(22) -# define OTGSC_1MSS BIT(21) -# define OTGSC_BSEIS BIT(20) -# define OTGSC_BSVIS BIT(19) -# define OTGSC_ASVIS BIT(18) -# define OTGSC_AVVIS BIT(17) -# define OTGSC_IDIS BIT(16) -# define OTGSC_DPS BIT(14) -# define OTGSC_1MST BIT(13) -# define OTGSC_BSE BIT(12) -# define OTGSC_BSV BIT(11) -# define OTGSC_ASV BIT(10) -# define OTGSC_AVV BIT(9) -# define OTGSC_ID BIT(8) -# define OTGSC_HABA BIT(7) -# define OTGSC_HADP BIT(6) -# define OTGSC_IDPU BIT(5) -# define OTGSC_DP BIT(4) -# define OTGSC_OT BIT(3) -# define OTGSC_HAAR BIT(2) -# define OTGSC_VC BIT(1) -# define OTGSC_VD BIT(0) -# define OTGSC_INTEN_MASK (0x7f << 24) -# define OTGSC_INT_MASK (0x5f << 24) -# define OTGSC_INTSTS_MASK (0x7f << 16) -#define CI_USBMODE 0xf8 -# define USBMODE_CM (BIT(1) | BIT(0)) -# define USBMODE_IDLE 0 -# define USBMODE_DEVICE 0x2 -# define USBMODE_HOST 0x3 -#define USBCFG_ADDR 0xff10801c -#define USBCFG_LEN 4 -# define USBCFG_VBUSVAL BIT(14) -# define USBCFG_AVALID BIT(13) -# define USBCFG_BVALID BIT(12) -# define USBCFG_SESEND BIT(11) - -#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI) - -enum langwell_otg_timer_type { - TA_WAIT_VRISE_TMR, - TA_WAIT_BCON_TMR, - TA_AIDL_BDIS_TMR, - TB_ASE0_BRST_TMR, - TB_SE0_SRP_TMR, - TB_SRP_INIT_TMR, - TB_SRP_FAIL_TMR, - TB_BUS_SUSPEND_TMR -}; - -#define TA_WAIT_VRISE 100 -#define TA_WAIT_BCON 30000 -#define TA_AIDL_BDIS 15000 -#define TB_ASE0_BRST 5000 -#define TB_SE0_SRP 2 -#define TB_SRP_INIT 100 -#define TB_SRP_FAIL 5500 -#define TB_BUS_SUSPEND 500 - -struct langwell_otg_timer { - unsigned long expires; /* Number of count increase to timeout */ - unsigned long count; /* Tick counter */ - void (*function)(unsigned long); /* Timeout function */ - unsigned long data; /* Data passed to function */ - struct list_head list; -}; - -struct langwell_otg { - struct intel_mid_otg_xceiv iotg; - struct device *dev; - - void __iomem *usbcfg; /* SCCBUSB config Reg */ - - unsigned region; - unsigned cfg_region; - - struct work_struct work; - struct workqueue_struct *qwork; - struct timer_list hsm_timer; - - spinlock_t lock; - spinlock_t wq_lock; - - struct notifier_block iotg_notifier; -}; - -static inline -struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg) -{ - return container_of(iotg, struct langwell_otg, iotg); -} - -#endif /* __LANGWELL_OTG_H__ */ From 28bd6222544d7559edf9ff487172e45ce46e2578 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 21 Dec 2011 10:19:39 +0200 Subject: [PATCH 037/380] usb: gadget: langwell: drop langwell_otg support Since there is no working (or even compilable) OTG_TRANSCEIVER support for this driver, remove the dead code which depends on it at compile time. Signed-off-by: Alexander Shishkin Cc: stable@vger.kernel.org # v2.6.31+ Cc: Heikki Krogerus Cc: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/gadget/langwell_udc.c | 89 +------------------------------ drivers/usb/gadget/langwell_udc.h | 1 - 2 files changed, 2 insertions(+), 88 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index fa0fcc11263f..34e3bf877341 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -11,11 +11,6 @@ /* #undef DEBUG */ /* #undef VERBOSE_DEBUG */ -#if defined(CONFIG_USB_LANGWELL_OTG) -#define OTG_TRANSCEIVER -#endif - - #include #include #include @@ -2315,13 +2310,9 @@ static void handle_setup_packet(struct langwell_udc *dev, if (!gadget_is_otg(&dev->gadget)) break; - else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) { + else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) dev->gadget.b_hnp_enable = 1; -#ifdef OTG_TRANSCEIVER - if (!dev->lotg->otg.default_a) - dev->lotg->hsm.b_hnp_enable = 1; -#endif - } else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT) + else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT) dev->gadget.a_hnp_support = 1; else if (setup->bRequest == USB_DEVICE_A_ALT_HNP_SUPPORT) @@ -2752,12 +2743,6 @@ static void handle_usb_reset(struct langwell_udc *dev) dev->usb_state = USB_STATE_ATTACHED; } -#ifdef OTG_TRANSCEIVER - /* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */ - if (!dev->lotg->otg.default_a) - dev->lotg->hsm.b_hnp_enable = 0; -#endif - dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2770,29 +2755,6 @@ static void handle_bus_suspend(struct langwell_udc *dev) dev->resume_state = dev->usb_state; dev->usb_state = USB_STATE_SUSPENDED; -#ifdef OTG_TRANSCEIVER - if (dev->lotg->otg.default_a) { - if (dev->lotg->hsm.b_bus_suspend_vld == 1) { - dev->lotg->hsm.b_bus_suspend = 1; - /* notify transceiver the state changes */ - if (spin_trylock(&dev->lotg->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&dev->lotg->wq_lock); - } - } - dev->lotg->hsm.b_bus_suspend_vld++; - } else { - if (!dev->lotg->hsm.a_bus_suspend) { - dev->lotg->hsm.a_bus_suspend = 1; - /* notify transceiver the state changes */ - if (spin_trylock(&dev->lotg->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&dev->lotg->wq_lock); - } - } - } -#endif - /* report suspend to the driver */ if (dev->driver) { if (dev->driver->suspend) { @@ -2823,11 +2785,6 @@ static void handle_bus_resume(struct langwell_udc *dev) if (dev->pdev->device != 0x0829) langwell_phy_low_power(dev, 0); -#ifdef OTG_TRANSCEIVER - if (dev->lotg->otg.default_a == 0) - dev->lotg->hsm.a_bus_suspend = 0; -#endif - /* report resume to the driver */ if (dev->driver) { if (dev->driver->resume) { @@ -3020,7 +2977,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) dev->done = &done; -#ifndef OTG_TRANSCEIVER /* free dTD dma_pool and dQH */ if (dev->dtd_pool) dma_pool_destroy(dev->dtd_pool); @@ -3032,7 +2988,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) /* release SRAM caching */ if (dev->has_sram && dev->got_sram) sram_deinit(dev); -#endif if (dev->status_req) { kfree(dev->status_req->req.buf); @@ -3045,7 +3000,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) if (dev->got_irq) free_irq(pdev->irq, dev); -#ifndef OTG_TRANSCEIVER if (dev->cap_regs) iounmap(dev->cap_regs); @@ -3055,13 +3009,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) if (dev->enabled) pci_disable_device(pdev); -#else - if (dev->transceiver) { - otg_put_transceiver(dev->transceiver); - dev->transceiver = NULL; - dev->lotg = NULL; - } -#endif dev->cap_regs = NULL; @@ -3072,9 +3019,7 @@ static void langwell_udc_remove(struct pci_dev *pdev) device_remove_file(&pdev->dev, &dev_attr_langwell_udc); device_remove_file(&pdev->dev, &dev_attr_remote_wakeup); -#ifndef OTG_TRANSCEIVER pci_set_drvdata(pdev, NULL); -#endif /* free dev, wait for the release() finished */ wait_for_completion(&done); @@ -3089,9 +3034,7 @@ static int langwell_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct langwell_udc *dev; -#ifndef OTG_TRANSCEIVER unsigned long resource, len; -#endif void __iomem *base = NULL; size_t size; int retval; @@ -3109,16 +3052,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->pdev = pdev; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); -#ifdef OTG_TRANSCEIVER - /* PCI device is already enabled by otg_transceiver driver */ - dev->enabled = 1; - - /* mem region and register base */ - dev->region = 1; - dev->transceiver = otg_get_transceiver(); - dev->lotg = otg_to_langwell(dev->transceiver); - base = dev->lotg->regs; -#else pci_set_drvdata(pdev, dev); /* now all the pci goodies ... */ @@ -3139,7 +3072,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->region = 1; base = ioremap_nocache(resource, len); -#endif if (base == NULL) { dev_err(&dev->pdev->dev, "can't map memory\n"); retval = -EFAULT; @@ -3163,7 +3095,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->got_sram = 0; dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram); -#ifndef OTG_TRANSCEIVER /* enable SRAM caching if detected */ if (dev->has_sram && !dev->got_sram) sram_init(dev); @@ -3182,7 +3113,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, goto error; } dev->got_irq = 1; -#endif /* set stopped bit */ dev->stopped = 1; @@ -3257,10 +3187,8 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->remote_wakeup = 0; dev->dev_status = 1 << USB_DEVICE_SELF_POWERED; -#ifndef OTG_TRANSCEIVER /* reset device controller */ langwell_udc_reset(dev); -#endif /* initialize gadget structure */ dev->gadget.ops = &langwell_ops; /* usb_gadget_ops */ @@ -3268,9 +3196,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */ dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */ dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */ -#ifdef OTG_TRANSCEIVER - dev->gadget.is_otg = 1; /* support otg mode */ -#endif /* the "gadget" abstracts/virtualizes the controller */ dev_set_name(&dev->gadget.dev, "gadget"); @@ -3282,10 +3207,8 @@ static int langwell_udc_probe(struct pci_dev *pdev, /* controller endpoints reinit */ eps_reinit(dev); -#ifndef OTG_TRANSCEIVER /* reset ep0 dQH and endptctrl */ ep0_reset(dev); -#endif /* create dTD dma_pool resource */ dev->dtd_pool = dma_pool_create("langwell_dtd", @@ -3525,22 +3448,14 @@ static struct pci_driver langwell_pci_driver = { static int __init init(void) { -#ifdef OTG_TRANSCEIVER - return langwell_register_peripheral(&langwell_pci_driver); -#else return pci_register_driver(&langwell_pci_driver); -#endif } module_init(init); static void __exit cleanup(void) { -#ifdef OTG_TRANSCEIVER - return langwell_unregister_peripheral(&langwell_pci_driver); -#else pci_unregister_driver(&langwell_pci_driver); -#endif } module_exit(cleanup); diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h index ef79e242b7b0..d6e78accaffe 100644 --- a/drivers/usb/gadget/langwell_udc.h +++ b/drivers/usb/gadget/langwell_udc.h @@ -8,7 +8,6 @@ */ #include -#include /*-------------------------------------------------------------------------*/ From 37fd37108449d574da11aa9055c5c8afb39ff226 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 21 Dec 2011 10:19:40 +0200 Subject: [PATCH 038/380] usb: gadget: langwell: don't call gadget's disconnect() UDC core will call disconnect() and unbind() for us upon the gadget removal, so we should not do it ourselves. Otherwise, a composite gadget will explode, for example. Others might too. This was introduced during conversion to new style gadget in 2c7f0989 (usb: gadget: langwell: convert to new style). Signed-off-by: Alexander Shishkin Cc: stable@vger.kernel.org # v3.2 Cc: Heikki Krogerus Cc: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/gadget/langwell_udc.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 34e3bf877341..e2293c1588ee 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -1517,8 +1517,7 @@ static void langwell_udc_stop(struct langwell_udc *dev) /* stop all USB activities */ -static void stop_activity(struct langwell_udc *dev, - struct usb_gadget_driver *driver) +static void stop_activity(struct langwell_udc *dev) { struct langwell_ep *ep; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); @@ -1530,9 +1529,9 @@ static void stop_activity(struct langwell_udc *dev, } /* report disconnect; the driver is already quiesced */ - if (driver) { + if (dev->driver) { spin_unlock(&dev->lock); - driver->disconnect(&dev->gadget); + dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); } @@ -1920,11 +1919,10 @@ static int langwell_stop(struct usb_gadget *g, /* stop all usb activities */ dev->gadget.speed = USB_SPEED_UNKNOWN; - stop_activity(dev, driver); - spin_unlock_irqrestore(&dev->lock, flags); - dev->gadget.dev.driver = NULL; dev->driver = NULL; + stop_activity(dev); + spin_unlock_irqrestore(&dev->lock, flags); device_remove_file(&dev->pdev->dev, &dev_attr_function); @@ -2724,7 +2722,7 @@ static void handle_usb_reset(struct langwell_udc *dev) dev->bus_reset = 1; /* reset all the queues, stop all USB activities */ - stop_activity(dev, dev->driver); + stop_activity(dev); dev->usb_state = USB_STATE_DEFAULT; } else { dev_vdbg(&dev->pdev->dev, "device controller reset\n"); @@ -2732,7 +2730,7 @@ static void handle_usb_reset(struct langwell_udc *dev) langwell_udc_reset(dev); /* reset all the queues, stop all USB activities */ - stop_activity(dev, dev->driver); + stop_activity(dev); /* reset ep0 dQH and endptctrl */ ep0_reset(dev); @@ -3290,7 +3288,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) spin_lock_irq(&dev->lock); /* stop all usb activities */ - stop_activity(dev, dev->driver); + stop_activity(dev); spin_unlock_irq(&dev->lock); /* free dTD dma_pool and dQH */ From 006896fc612f11bf0624db7814a75d0d5410855f Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Wed, 28 Dec 2011 12:02:57 +0530 Subject: [PATCH 039/380] usb: musb: davinci: fix build breakage Commit 0020afb369859472a461ef4af6410732e929d402 (ARM: mach-davinci: remove mach/memory.h) removed mach/memory.h for DaVinci which broke DaVinci MUSB build. mach/memory.h is not actually needed in davinci.c, so remove it. While at it, also remove some more machine specific inclulde files which are not needed for build. Tested on DM644x EVM using USB card reader. Cc: stable@vger.kernel.org # v3.2 Signed-off-by: Sekhar Nori Signed-off-by: Felipe Balbi --- drivers/usb/musb/davinci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index f9a3f62a83b5..7c569f51212a 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -33,9 +33,6 @@ #include #include -#include -#include -#include #include #include From 1a0955fed11363bea66742fffc6f8ad1e6800a6d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 10 Jan 2012 17:29:29 +0200 Subject: [PATCH 040/380] usb: dwc3: ep0: fix compile warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 34c60a7 (usb: dwc3: ep0: tidy up Pending Request handling) introduced a compile warning by leaving an unused variable. This patch fixes that warning: drivers/usb/dwc3/ep0.c: In function ‘__dwc3_gadget_ep0_queue’: drivers/usb/dwc3/ep0.c:129:8: warning: unused variable ‘type’ [-Wunused-variable] Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 74a3828cf950..c8df1dd967ef 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -126,7 +126,6 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, struct dwc3_request *req) { struct dwc3 *dwc = dep->dwc; - u32 type; int ret = 0; req->request.actual = 0; From a85016390135d577c457876d0e905095600751de Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Wed, 4 Jan 2012 15:18:27 +0800 Subject: [PATCH 041/380] usb: gadget: storage: endian fix Fix some endian issues for storage gadgets. Cc: stable@vger.kernel.org Signed-off-by: Andiry Xu Signed-off-by: Felipe Balbi --- drivers/usb/gadget/storage_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index c7f291a331df..85ea14e2545e 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -598,16 +598,16 @@ static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = { | USB_5GBPS_OPERATION), .bFunctionalitySupport = USB_LOW_SPEED_OPERATION, .bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT, - .bU2DevExitLat = USB_DEFAULT_U2_DEV_EXIT_LAT, + .bU2DevExitLat = cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT), }; static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = { .bLength = USB_DT_BOS_SIZE, .bDescriptorType = USB_DT_BOS, - .wTotalLength = USB_DT_BOS_SIZE + .wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE + USB_DT_USB_EXT_CAP_SIZE - + USB_DT_USB_SS_CAP_SIZE, + + USB_DT_USB_SS_CAP_SIZE), .bNumDeviceCaps = 2, }; From 9e878a6bfa9e1cf70cf77caeca60a0465d77954b Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Mon, 16 Jan 2012 13:24:38 -0800 Subject: [PATCH 042/380] usb: gadget: SS Isoc endpoints use comp_desc->bMaxBurst too SuperSpeed Isoc endpoints also use the bMaxBurst value from the companion descriptor. See section 9.6.7 in the USB 3.0 spec. Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index a95de6a4a134..baaebf2830fc 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -175,13 +175,12 @@ ep_found: _ep->comp_desc = comp_desc; if (g->speed == USB_SPEED_SUPER) { switch (usb_endpoint_type(_ep->desc)) { - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_INT: - _ep->maxburst = comp_desc->bMaxBurst; - break; case USB_ENDPOINT_XFER_ISOC: /* mult: bits 1:0 of bmAttributes */ _ep->mult = comp_desc->bmAttributes & 0x3; + case USB_ENDPOINT_XFER_BULK: + case USB_ENDPOINT_XFER_INT: + _ep->maxburst = comp_desc->bMaxBurst; break; default: /* Do nothing for control endpoints */ From 7983bc74fc0bc91f026c7ba0654b08073d843657 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 16 Jan 2012 22:42:10 +0100 Subject: [PATCH 043/380] usb: renesas: silence uninitialized variable report in usbhsg_recip_run_handle() In drivers/usb/renesas_usbhs/mod_gadget.c::usbhsg_recip_run_handle() the Coverity Prevent checker currently flags a warning about possibly uninitialized use of 'ret' i usbhsg_recip_run_handle(). It does this since it assumes we take one of the non-default branches in the switch and then subsequently take the false branch in the 'if (func)' case below. This exact scenario will never happen, but Coverity can't see that for some reason. This patch initializes 'ret' to '0' when it is declared which should shut up this report and won't really hurt - so why not? At least then it's clear that 'ret' is always initialized.. Signed-off-by: Jesper Juhl Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 528691d5f3e2..7542aa94a462 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -425,7 +425,7 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv, struct usbhs_pipe *pipe; int recip = ctrl->bRequestType & USB_RECIP_MASK; int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; - int ret; + int ret = 0; int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep, struct usb_ctrlrequest *ctrl); char *msg; From a37670b1c0f5dee021e451130653936742233457 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 13 Jan 2012 15:19:06 -0200 Subject: [PATCH 044/380] drivers: usb: otg: Fix dependencies for some OTG drivers Fix the following build warning: warning: (USB_LANGWELL_OTG && FSL_USB2_OTG && USB_MV_OTG) selects USB_OTG which has unmet direct dependencies (USB_SUPPORT && USB && EXPERIMENTAL && USB_SUSPEND) Signed-off-by: Fabio Estevam Signed-off-by: Felipe Balbi --- drivers/usb/otg/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 9105c285f594..76d629345418 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -110,7 +110,7 @@ config AB8500_USB config FSL_USB2_OTG bool "Freescale USB OTG Transceiver Driver" - depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 + depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND select USB_OTG select USB_OTG_UTILS help @@ -118,7 +118,7 @@ config FSL_USB2_OTG config USB_MV_OTG tristate "Marvell USB OTG support" - depends on USB_MV_UDC + depends on USB_MV_UDC && USB_SUSPEND select USB_OTG select USB_OTG_UTILS help From 118d63f7f84cd400ba537f5d318c035c95c6776d Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 11 Jan 2012 13:39:07 +0800 Subject: [PATCH 045/380] usb: gadget: fsl_udc: fix the usage of udc->max_ep The max_ep is the number of endpoint * 2. But in dtd_complete_irq, it does again * 2, it will deference wrong memory after scanning max_ep - 1. The another similar problem is at USB_REQ_SET_FEATURE (the pipe number should be 0 and max_ep - 1). Signed-off-by: Peter Chen Signed-off-by: Matthieu castet Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_udc_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index d7ea6c076ce9..b04712f19f1e 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1430,7 +1430,7 @@ static void setup_received_irq(struct fsl_udc *udc, int pipe = get_pipe_by_windex(wIndex); struct fsl_ep *ep; - if (wValue != 0 || wLength != 0 || pipe > udc->max_ep) + if (wValue != 0 || wLength != 0 || pipe >= udc->max_ep) break; ep = get_ep_by_pipe(udc, pipe); @@ -1673,7 +1673,7 @@ static void dtd_complete_irq(struct fsl_udc *udc) if (!bit_pos) return; - for (i = 0; i < udc->max_ep * 2; i++) { + for (i = 0; i < udc->max_ep; i++) { ep_num = i >> 1; direction = i % 2; From c74c930082fd407e3b9e503d855d78777a8e5a84 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 11 Jan 2012 21:42:44 +0100 Subject: [PATCH 046/380] usb: gadget: check for streams only for SS udcs Currently the UASP gadget fails to bind on an UDC which does not provide stream support. This is true for all udc in tree except for dummy and dwc3 since they don't support SuperSpeed. There is no need to test for the availability of stream support on those UDCs because we will never even try to use them. I think it is sane to assume that StreamSupport is always available on SuperSpeed since it is one of the key features. The host side will only allocate on SS so this part is also fine. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 753aa0683ac1..e0e6375ef5dd 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -126,7 +126,7 @@ ep_matches ( * descriptor and see if the EP matches it */ if (usb_endpoint_xfer_bulk(desc)) { - if (ep_comp) { + if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) { num_req_streams = ep_comp->bmAttributes & 0x1f; if (num_req_streams > ep->max_streams) return 0; From 4b5203f1883e2dd49273e9f91235c36a0708aad1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 12 Jan 2012 16:09:15 -0200 Subject: [PATCH 047/380] usb: gadget: f_mass_storage: Use "bool" instead of "int" in fsg_module_parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following build warnings: CC [M] drivers/usb/gadget/acm_ms.o drivers/usb/gadget/acm_ms.c: In function ‘__check_ro’: drivers/usb/gadget/acm_ms.c:119: warning: return from incompatible pointer type drivers/usb/gadget/acm_ms.c: In function ‘__check_removable’: drivers/usb/gadget/acm_ms.c:119: warning: return from incompatible pointer type drivers/usb/gadget/acm_ms.c: In function ‘__check_cdrom’: drivers/usb/gadget/acm_ms.c:119: warning: return from incompatible pointer type drivers/usb/gadget/acm_ms.c: In function ‘__check_nofua’: drivers/usb/gadget/acm_ms.c:119: warning: return from incompatible pointer type drivers/usb/gadget/acm_ms.c: In function ‘__check_stall’: drivers/usb/gadget/acm_ms.c:119: warning: return from incompatible pointer type CC [M] drivers/usb/gadget/mass_storage.o drivers/usb/gadget/mass_storage.c: In function ‘__check_ro’: drivers/usb/gadget/mass_storage.c:94: warning: return from incompatible pointer type drivers/usb/gadget/mass_storage.c: In function ‘__check_removable’: drivers/usb/gadget/mass_storage.c:94: warning: return from incompatible pointer type drivers/usb/gadget/mass_storage.c: In function ‘__check_cdrom’: drivers/usb/gadget/mass_storage.c:94: warning: return from incompatible pointer type drivers/usb/gadget/mass_storage.c: In function ‘__check_nofua’: drivers/usb/gadget/mass_storage.c:94: warning: return from incompatible pointer type drivers/usb/gadget/mass_storage.c: In function ‘__check_stall’: drivers/usb/gadget/mass_storage.c:94: warning: return from incompatible pointer type Declare the fsg_module_parameters fields as "bool" so that they can match the types passed in FSG_MODULE_PARAM_ARRAY macro. Since commit 493c90ef (module_param: check that bool parameters really are bool.), moduleparam.h was changed in a way that the "bool" parameter type now really requires "bool" type and no longer allows "unsigned int". Signed-off-by: Fabio Estevam Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_mass_storage.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 6353eca1e852..ee8ceec01560 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -3123,15 +3123,15 @@ fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c, struct fsg_module_parameters { char *file[FSG_MAX_LUNS]; - int ro[FSG_MAX_LUNS]; - int removable[FSG_MAX_LUNS]; - int cdrom[FSG_MAX_LUNS]; - int nofua[FSG_MAX_LUNS]; + bool ro[FSG_MAX_LUNS]; + bool removable[FSG_MAX_LUNS]; + bool cdrom[FSG_MAX_LUNS]; + bool nofua[FSG_MAX_LUNS]; unsigned int file_count, ro_count, removable_count, cdrom_count; unsigned int nofua_count; unsigned int luns; /* nluns */ - int stall; /* can_stall */ + bool stall; /* can_stall */ }; #define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ From 24307caef4950e42e7875a901856ed8816c4679c Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Thu, 12 Jan 2012 15:22:45 +0200 Subject: [PATCH 048/380] usb: musb: fix shutdown while usb gadget is in use If we shutdown without stopping the gadget first or removing the cable, gadget manages to configure itself again: root@pandora /root# poweroff The system is going down NOW! Requesting system poweroff [ 47.714385] musb-hm halted. [ 48.120697] gadget: suspend [ 48.123748] gadget: reset config [ 48.127227] gadget: ecm deactivated [ 48.130981] usb0: gether_disconnect [ 48.281799] gadget: high-speed config #1: CDC Ethernet (ECM) [ 48.287872] gadget: init ecm [ 48.290985] gadget: notify connect false [ 48.295288] gadget: notify speed 425984000 This is not only unwanted, it's also happening on half-unitialized state, after musb_shutdown() has returned, which sometimes causes hardware to fail to work after reboot. Let's better properly stop gadget on shutdown too. This patch moves musb_gadget_cleanup out of musb_free(), which has 2 callsites: probe error path and musb_remove. On probe error path it was superflous since musb_gadget_cleanup is called explicitly there, and musb_remove() calls musb_shutdown(), so cleanup will get called as before. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 56cf0243979e..3d11cf64ebd1 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -981,6 +981,9 @@ static void musb_shutdown(struct platform_device *pdev) unsigned long flags; pm_runtime_get_sync(musb->controller); + + musb_gadget_cleanup(musb); + spin_lock_irqsave(&musb->lock, flags); musb_platform_disable(musb); musb_generic_disable(musb); @@ -1827,8 +1830,6 @@ static void musb_free(struct musb *musb) sysfs_remove_group(&musb->controller->kobj, &musb_attr_group); #endif - musb_gadget_cleanup(musb); - if (musb->nIrq >= 0) { if (musb->irq_wake) disable_irq_wake(musb->nIrq); From c09d6b51d78f5ad33417dbac9b479bd6709f9f25 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 24 Jan 2012 12:44:34 +0100 Subject: [PATCH 049/380] usb: dwc3: unmap the proper number of sg entries num_sgs contains the number of sgs assigned by the gadget. num_mapped_sgs contains the number of mapped sgs which may differ from the gadget's values. For dma_unmap_sg() we have to provide the value which was returned by dma_map_sg(). Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a696bde53222..064b6e2cd411 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -101,7 +101,7 @@ void dwc3_unmap_buffer_from_dma(struct dwc3_request *req) if (req->request.num_mapped_sgs) { req->request.dma = DMA_ADDR_INVALID; dma_unmap_sg(dwc->dev, req->request.sg, - req->request.num_sgs, + req->request.num_mapped_sgs, req->direction ? DMA_TO_DEVICE : DMA_FROM_DEVICE); From 803ab977618eae2b292cda0a97eed75f42250ddf Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 24 Jan 2012 11:39:22 +0300 Subject: [PATCH 050/380] cifs: NULL dereference on allocation failure We should just return directly here, the goto causes a NULL dereference. Signed-off-by: Dan Carpenter Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 986709a8d903..026d6464335b 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3857,10 +3857,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) struct smb_vol *vol_info; vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); - if (vol_info == NULL) { - tcon = ERR_PTR(-ENOMEM); - goto out; - } + if (vol_info == NULL) + return ERR_PTR(-ENOMEM); vol_info->local_nls = cifs_sb->local_nls; vol_info->linux_uid = fsuid; From 7a7546b377bdaa25ac77f33d9433c59f259b9688 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 23 Jan 2012 19:32:25 +0000 Subject: [PATCH 051/380] x86: xen: size struct xen_spinlock to always fit in arch_spinlock_t If NR_CPUS < 256 then arch_spinlock_t is only 16 bits wide but struct xen_spinlock is 32 bits. When a spin lock is contended and xl->spinners is modified the two bytes immediately after the spin lock would be corrupted. This is a regression caused by 84eb950db13ca40a0572ce9957e14723500943d6 (x86, ticketlock: Clean up types and accessors) which reduced the size of arch_spinlock_t. Fix this by making xl->spinners a u8 if NR_CPUS < 256. A BUILD_BUG_ON() is also added to check the sizes of the two structures are compatible. In many cases this was not noticable as there would often be padding bytes after the lock (e.g., if any of CONFIG_GENERIC_LOCKBREAK, CONFIG_DEBUG_SPINLOCK, or CONFIG_DEBUG_LOCK_ALLOC were enabled). The bnx2 driver is affected. In struct bnx2, phy_lock and indirect_lock may have no padding after them. Contention on phy_lock would corrupt indirect_lock making it appear locked and the driver would deadlock. Signed-off-by: David Vrabel Signed-off-by: Jeremy Fitzhardinge Acked-by: Ian Campbell CC: stable@kernel.org #only 3.2 Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/spinlock.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index cc9b1e182fcf..d69cc6c3f808 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -116,9 +116,26 @@ static inline void spin_time_accum_blocked(u64 start) } #endif /* CONFIG_XEN_DEBUG_FS */ +/* + * Size struct xen_spinlock so it's the same as arch_spinlock_t. + */ +#if NR_CPUS < 256 +typedef u8 xen_spinners_t; +# define inc_spinners(xl) \ + asm(LOCK_PREFIX " incb %0" : "+m" ((xl)->spinners) : : "memory"); +# define dec_spinners(xl) \ + asm(LOCK_PREFIX " decb %0" : "+m" ((xl)->spinners) : : "memory"); +#else +typedef u16 xen_spinners_t; +# define inc_spinners(xl) \ + asm(LOCK_PREFIX " incw %0" : "+m" ((xl)->spinners) : : "memory"); +# define dec_spinners(xl) \ + asm(LOCK_PREFIX " decw %0" : "+m" ((xl)->spinners) : : "memory"); +#endif + struct xen_spinlock { unsigned char lock; /* 0 -> free; 1 -> locked */ - unsigned short spinners; /* count of waiting cpus */ + xen_spinners_t spinners; /* count of waiting cpus */ }; static int xen_spin_is_locked(struct arch_spinlock *lock) @@ -164,8 +181,7 @@ static inline struct xen_spinlock *spinning_lock(struct xen_spinlock *xl) wmb(); /* set lock of interest before count */ - asm(LOCK_PREFIX " incw %0" - : "+m" (xl->spinners) : : "memory"); + inc_spinners(xl); return prev; } @@ -176,8 +192,7 @@ static inline struct xen_spinlock *spinning_lock(struct xen_spinlock *xl) */ static inline void unspinning_lock(struct xen_spinlock *xl, struct xen_spinlock *prev) { - asm(LOCK_PREFIX " decw %0" - : "+m" (xl->spinners) : : "memory"); + dec_spinners(xl); wmb(); /* decrement count before restoring lock */ __this_cpu_write(lock_spinners, prev); } @@ -373,6 +388,8 @@ void xen_uninit_lock_cpu(int cpu) void __init xen_init_spinlocks(void) { + BUILD_BUG_ON(sizeof(struct xen_spinlock) > sizeof(arch_spinlock_t)); + pv_lock_ops.spin_is_locked = xen_spin_is_locked; pv_lock_ops.spin_is_contended = xen_spin_is_contended; pv_lock_ops.spin_lock = xen_spin_lock; From 1a5e29fc2b90daf71a60329c29a1886fd126169a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 21 Jan 2012 11:02:51 -0800 Subject: [PATCH 052/380] kernel-doc: fix new warnings in device.h Fix new kernel-doc warnings: Warning(include/linux/device.h:299): No description found for parameter 'name' Warning(include/linux/device.h:299): No description found for parameter 'subsys' Warning(include/linux/device.h:299): No description found for parameter 'node' Warning(include/linux/device.h:299): No description found for parameter 'add_dev' Warning(include/linux/device.h:299): No description found for parameter 'remove_dev' Warning(include/linux/device.h:685): No description found for parameter 'id' Warning(include/linux/device.h:1009): No description found for parameter '__driver' Warning(include/linux/device.h:1009): No description found for parameter '__register' Warning(include/linux/device.h:1009): No description found for parameter '__unregister' Signed-off-by: Randy Dunlap Cc: Lars-Peter Clausen Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/linux/device.h b/include/linux/device.h index 5b3adb8f9588..b63fb393aa58 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -279,11 +279,11 @@ struct device *driver_find_device(struct device_driver *drv, /** * struct subsys_interface - interfaces to device functions - * @name name of the device function - * @subsystem subsytem of the devices to attach to - * @node the list of functions registered at the subsystem - * @add device hookup to device function handler - * @remove device hookup to device function handler + * @name: name of the device function + * @subsys: subsytem of the devices to attach to + * @node: the list of functions registered at the subsystem + * @add_dev: device hookup to device function handler + * @remove_dev: device hookup to device function handler * * Simple interfaces attached to a subsystem. Multiple interfaces can * attach to a subsystem and its devices. Unlike drivers, they do not @@ -612,6 +612,7 @@ struct device_dma_parameters { * @archdata: For arch-specific additions. * @of_node: Associated device tree node. * @devt: For creating the sysfs "dev". + * @id: device instance * @devres_lock: Spinlock to protect the resource of the device. * @devres_head: The resources list of the device. * @knode_class: The node used to add the device to the class list. @@ -1003,6 +1004,10 @@ extern long sysfs_deprecated; * Each module may only use this macro once, and calling it replaces * module_init() and module_exit(). * + * @__driver: driver name + * @__register: register function for this driver type + * @__unregister: unregister function for this driver type + * * Use this macro to construct bus specific macros for registering * drivers, and do not use it on its own. */ From 0863b04d1578879173aacbc5c7be749fccb70809 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 21 Jan 2012 11:02:42 -0800 Subject: [PATCH 053/380] kernel-doc: fix new warnings in debugfs Fix new kernel-doc warnings: Warning(fs/debugfs/file.c:556): No description found for parameter 'nregs' Warning(fs/debugfs/file.c:556): Excess function parameter 'mregs' description in 'debugfs_print_regs32' Signed-off-by: Randy Dunlap Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index f65d4455c5e5..ef023eef0464 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -540,7 +540,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_blob); * debugfs_print_regs32 - use seq_print to describe a set of registers * @s: the seq_file structure being used to generate output * @regs: an array if struct debugfs_reg32 structures - * @mregs: the length of the above array + * @nregs: the length of the above array * @base: the base address to be used in reading the registers * @prefix: a string to be prefixed to every output line * From 4f4ffe52e1e5ddb9708fe075aaef4424f1fb744a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 21 Jan 2012 11:02:28 -0800 Subject: [PATCH 054/380] kernel-doc: fix new warnings in driver-core Fix new kernel-doc warnings: Warning(drivers/base/bus.c:925): No description found for parameter 'key' Warning(drivers/base/bus.c:1241): No description found for parameter 'subsys' Warning(drivers/base/bus.c:1241): No description found for parameter 'groups' Signed-off-by: Randy Dunlap Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 99dc5921e1dd..40fb12288ce2 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -915,9 +915,10 @@ static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); /** * __bus_register - register a driver-core subsystem - * @bus: bus. + * @bus: bus to register + * @key: lockdep class key * - * Once we have that, we registered the bus with the kobject + * Once we have that, we register the bus with the kobject * infrastructure, then register the children subsystems it has: * the devices and drivers that belong to the subsystem. */ @@ -1220,8 +1221,8 @@ static void system_root_device_release(struct device *dev) } /** * subsys_system_register - register a subsystem at /sys/devices/system/ - * @subsys - system subsystem - * @groups - default attributes for the root device + * @subsys: system subsystem + * @groups: default attributes for the root device * * All 'system' subsystems have a /sys/devices/system/ root device * with the name of the subsystem. The root device can carry subsystem- From b10d5efdf7892d18b3b7d899edce2c8d9b80aea9 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 17 Jan 2012 11:39:00 -0500 Subject: [PATCH 055/380] Documentation update for the driver model core This patch (as1509) documents two important points regarding the use of device structures in the driver model: Structures must be initialized to all 0's before they are passed to device_initialize(). Structures must not be passed to device_add() or device_register() more than once. Although these restrictions have applied ever since the driver model was first created, they have not been mentioned anywhere. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 4a67cc0c8b37..ad29e928baaa 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -632,6 +632,11 @@ static void klist_children_put(struct klist_node *n) * may be used for reference counting of @dev after calling this * function. * + * All fields in @dev must be initialized by the caller to 0, except + * for those explicitly set to some other value. The simplest + * approach is to use kzalloc() to allocate the structure containing + * @dev. + * * NOTE: Use put_device() to give up your reference instead of freeing * @dev directly once you have called this function. */ @@ -930,6 +935,13 @@ int device_private_init(struct device *dev) * to the global and sibling lists for the device, then * adds it to the other relevant subsystems of the driver model. * + * Do not call this routine or device_register() more than once for + * any device structure. The driver model core is not designed to work + * with devices that get unregistered and then spring back to life. + * (Among other things, it's very hard to guarantee that all references + * to the previous incarnation of @dev have been dropped.) Allocate + * and register a fresh new struct device instead. + * * NOTE: _Never_ directly free @dev after calling this function, even * if it returned an error! Always use put_device() to give up your * reference instead. @@ -1090,6 +1102,9 @@ name_error: * have a clearly defined need to use and refcount the device * before it is added to the hierarchy. * + * For more information, see the kerneldoc for device_initialize() + * and device_add(). + * * NOTE: _Never_ directly free @dev after calling this function, even * if it returned an error! Always use put_device() to give up the * reference initialized in this function instead. From 543f43ce87c45220a8ffbff5ff4b60122499ce5f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 15 Jan 2012 13:31:46 +0100 Subject: [PATCH 056/380] Documentation: devres: add allocation functions to list of supported calls Signed-off-by: Wolfram Sang Acked-by: Grant Likely Acked-by: Tejun Heo Cc: Randy Dunlap Cc: Greg KH Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-model/devres.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 10c64c8a13d4..41c0c5d1ba14 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -233,6 +233,10 @@ certainly invest a bit more effort into libata core layer). 6. List of managed interfaces ----------------------------- +MEM + devm_kzalloc() + devm_kfree() + IO region devm_request_region() devm_request_mem_region() From 268863f43629ef88763400d0cae4a66c754a0d23 Mon Sep 17 00:00:00 2001 From: majianpeng Date: Wed, 11 Jan 2012 15:12:06 +0000 Subject: [PATCH 057/380] base/core.c:fix typo in comment in function device_add Signed-off-by: majianpeng Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index ad29e928baaa..74dda4f697f9 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1034,7 +1034,7 @@ int device_add(struct device *dev) device_pm_add(dev); /* Notify clients of device addition. This call must come - * after dpm_sysf_add() and before kobject_uevent(). + * after dpm_sysfs_add() and before kobject_uevent(). */ if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, From 8381b5e88a19b780f19fc52b7dd67f2b05d07dca Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 23 Jan 2012 07:36:04 -0800 Subject: [PATCH 058/380] stable: update documentation to ask for kernel version It would save me an email round-trip asking which stable tree(s) that a patch should be applied to, so document that the tree number should be specified in the email request. Reported-by: Tomoya MORINAGA Signed-off-by: Greg Kroah-Hartman --- Documentation/stable_kernel_rules.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index 21fd05c28e73..f0ab5cf28fca 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -25,7 +25,8 @@ Procedure for submitting patches to the -stable tree: - Send the patch, after verifying that it follows the above rules, to stable@vger.kernel.org. You must note the upstream commit ID in the - changelog of your submission. + changelog of your submission, as well as the kernel version you wish + it to be applied to. - To have the patch automatically included in the stable tree, add the tag Cc: stable@vger.kernel.org in the sign-off area. Once the patch is merged it will be applied to From 55305afc30529143bdb5928b2154dccdf073acd5 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 10 Jan 2012 15:43:08 -0800 Subject: [PATCH 059/380] drivers/usb/misc/emi26.c & emi62.c: fix warnings drivers/usb/misc/emi26.c:40: warning: 'emi26_init' declared 'static' but never defined drivers/usb/misc/emi26.c:41: warning: 'emi26_exit' declared 'static' but never defined drivers/usb/misc/emi62.c:49: warning: 'emi62_init' declared 'static' but never defined drivers/usb/misc/emi62.c:50: warning: 'emi62_exit' declared 'static' but never defined Signed-off-by: Andrew Morton Signed-off-by: Paul Gortmaker Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/emi26.c | 3 --- drivers/usb/misc/emi62.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index d9b6a0355443..da97dcec1f32 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -37,9 +37,6 @@ static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit); static int emi26_load_firmware (struct usb_device *dev); static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id); static void emi26_disconnect(struct usb_interface *intf); -static int __init emi26_init (void); -static void __exit emi26_exit (void); - /* thanks to drivers/usb/serial/keyspan_pda.c code */ static int emi26_writememory (struct usb_device *dev, int address, diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 9f39062ebb08..4e0f167a6c4e 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -46,9 +46,6 @@ static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit); static int emi62_load_firmware (struct usb_device *dev); static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id); static void emi62_disconnect(struct usb_interface *intf); -static int __init emi62_init (void); -static void __exit emi62_exit (void); - /* thanks to drivers/usb/serial/keyspan_pda.c code */ static int emi62_writememory(struct usb_device *dev, int address, From eb833a9e0972f60beb4ab8104ad7ef6bf30f02fc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 10 Jan 2012 23:33:37 +0100 Subject: [PATCH 060/380] USB: ftdi_sio: fix TIOCSSERIAL baud_base handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return EINVAL if new baud_base does not match the current one. The baud_base is device specific and can not be changed. This restores the old (pre-2005) behaviour which was changed due to a misunderstanding regarding this fact (see https://lkml.org/lkml/2005/1/20/84). Reported-by: Torbjörn Lofterud Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 01b6404df395..ff5a8e172a34 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1333,8 +1333,7 @@ static int set_serial_info(struct tty_struct *tty, goto check_and_exit; } - if ((new_serial.baud_base != priv->baud_base) && - (new_serial.baud_base < 9600)) { + if (new_serial.baud_base != priv->baud_base) { mutex_unlock(&priv->cfg_lock); return -EINVAL; } From 108e02b12921078a59dcacd048079ece48a4a983 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 18 Jan 2012 01:46:00 +0100 Subject: [PATCH 061/380] USB: ftdi_sio: fix initial baud rate Fix regression introduced by commit b1ffb4c851f1 ("USB: Fix Corruption issue in USB ftdi driver ftdi_sio.c") which caused the termios settings to no longer be initialised at open. Consequently it was no longer possible to set the port to the default speed of 9600 baud without first changing to another baud rate and back again. Reported-by: Roland Ramthun Cc: stable Signed-off-by: Johan Hovold Tested-by: Roland Ramthun Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ff5a8e172a34..7dbdf1e7684d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1823,6 +1823,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) { + struct ktermios dummy; struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); int result; @@ -1841,8 +1842,10 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ - if (tty) - ftdi_set_termios(tty, port, tty->termios); + if (tty) { + memset(&dummy, 0, sizeof(dummy)); + ftdi_set_termios(tty, port, &dummy); + } /* Start reading from the device */ result = usb_serial_generic_open(tty, port); From 55f13aeae0346f0c89bfface91ad9a97653dc433 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Wed, 18 Jan 2012 23:43:45 +0100 Subject: [PATCH 062/380] USB: ftdi_sio: add PID for TI XDS100v2 / BeagleBone A3 Port A for JTAG, port B for serial. Signed-off-by: Peter Korsgaard Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 7dbdf1e7684d..5f42757930df 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -805,6 +805,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index df1d7da933ec..f35ddef72e04 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -39,6 +39,13 @@ /* www.candapter.com Ewert Energy Systems CANdapter device */ #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ +/* + * Texas Instruments XDS100v2 JTAG / BeagleBone A3 + * http://processors.wiki.ti.com/index.php/XDS100 + * http://beagleboard.org/bone + */ +#define TI_XDS100V2_PID 0xa6d0 + #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ /* US Interface Navigator (http://www.usinterface.com/) */ From fc216ec363f4d174932df90bbf35c77d0540e561 Mon Sep 17 00:00:00 2001 From: Peter Naulls Date: Tue, 17 Jan 2012 18:27:09 -0800 Subject: [PATCH 063/380] USB: serial: ftdi additional IDs I tested this against 2.6.39 in the Ubuntu kernel, however I see the IDs are not in latest 3.2 git. This adds IDs for the FTDI controller in the Rainforest Automation Zigbee dongle. Signed-off-by: Peter Naulls Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 5f42757930df..104aff536b1e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -843,6 +843,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ST_VID, ST_STMCLT1030_PID), .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index f35ddef72e04..09237ffe2f33 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1175,3 +1175,9 @@ */ /* TagTracer MIFARE*/ #define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0 + +/* + * Rainforest Automation + */ +/* ZigBee controller */ +#define FTDI_RF_R106 0x8A28 From 9bef3d4197379a995fa80f81950bbbf8d32e9e8b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 5 Jan 2012 18:21:43 -0500 Subject: [PATCH 064/380] serial: group all the 8250 related code together The drivers/tty/serial dir is already getting rather busy. Relocate the 8250 related drivers to their own subdir to reduce the clutter. Note that sunsu.c is not included in this move -- it is 8250-like hardware, but it does not use any of the existing infrastructure -- and does not depend on SERIAL_8250. Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/{ => 8250}/8250.c | 0 drivers/tty/serial/{ => 8250}/8250.h | 0 drivers/tty/serial/{ => 8250}/8250_accent.c | 0 drivers/tty/serial/{ => 8250}/8250_acorn.c | 0 drivers/tty/serial/{ => 8250}/8250_boca.c | 0 drivers/tty/serial/{ => 8250}/8250_dw.c | 0 drivers/tty/serial/{ => 8250}/8250_early.c | 0 .../serial/{ => 8250}/8250_exar_st16c554.c | 0 drivers/tty/serial/{ => 8250}/8250_fourport.c | 0 drivers/tty/serial/{ => 8250}/8250_fsl.c | 0 drivers/tty/serial/{ => 8250}/8250_gsc.c | 0 drivers/tty/serial/{ => 8250}/8250_hp300.c | 0 drivers/tty/serial/{ => 8250}/8250_hub6.c | 0 drivers/tty/serial/{ => 8250}/8250_mca.c | 0 drivers/tty/serial/{ => 8250}/8250_pci.c | 0 drivers/tty/serial/{ => 8250}/8250_pnp.c | 0 drivers/tty/serial/8250/Kconfig | 280 ++++++++++++++++++ drivers/tty/serial/8250/Makefile | 20 ++ drivers/tty/serial/{ => 8250}/m32r_sio.c | 0 drivers/tty/serial/{ => 8250}/m32r_sio.h | 0 drivers/tty/serial/{ => 8250}/m32r_sio_reg.h | 0 drivers/tty/serial/{ => 8250}/serial_cs.c | 0 drivers/tty/serial/Kconfig | 274 +---------------- drivers/tty/serial/Makefile | 19 +- 24 files changed, 304 insertions(+), 289 deletions(-) rename drivers/tty/serial/{ => 8250}/8250.c (100%) rename drivers/tty/serial/{ => 8250}/8250.h (100%) rename drivers/tty/serial/{ => 8250}/8250_accent.c (100%) rename drivers/tty/serial/{ => 8250}/8250_acorn.c (100%) rename drivers/tty/serial/{ => 8250}/8250_boca.c (100%) rename drivers/tty/serial/{ => 8250}/8250_dw.c (100%) rename drivers/tty/serial/{ => 8250}/8250_early.c (100%) rename drivers/tty/serial/{ => 8250}/8250_exar_st16c554.c (100%) rename drivers/tty/serial/{ => 8250}/8250_fourport.c (100%) rename drivers/tty/serial/{ => 8250}/8250_fsl.c (100%) rename drivers/tty/serial/{ => 8250}/8250_gsc.c (100%) rename drivers/tty/serial/{ => 8250}/8250_hp300.c (100%) rename drivers/tty/serial/{ => 8250}/8250_hub6.c (100%) rename drivers/tty/serial/{ => 8250}/8250_mca.c (100%) rename drivers/tty/serial/{ => 8250}/8250_pci.c (100%) rename drivers/tty/serial/{ => 8250}/8250_pnp.c (100%) create mode 100644 drivers/tty/serial/8250/Kconfig create mode 100644 drivers/tty/serial/8250/Makefile rename drivers/tty/serial/{ => 8250}/m32r_sio.c (100%) rename drivers/tty/serial/{ => 8250}/m32r_sio.h (100%) rename drivers/tty/serial/{ => 8250}/m32r_sio_reg.h (100%) rename drivers/tty/serial/{ => 8250}/serial_cs.c (100%) diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250/8250.c similarity index 100% rename from drivers/tty/serial/8250.c rename to drivers/tty/serial/8250/8250.c diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250/8250.h similarity index 100% rename from drivers/tty/serial/8250.h rename to drivers/tty/serial/8250/8250.h diff --git a/drivers/tty/serial/8250_accent.c b/drivers/tty/serial/8250/8250_accent.c similarity index 100% rename from drivers/tty/serial/8250_accent.c rename to drivers/tty/serial/8250/8250_accent.c diff --git a/drivers/tty/serial/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c similarity index 100% rename from drivers/tty/serial/8250_acorn.c rename to drivers/tty/serial/8250/8250_acorn.c diff --git a/drivers/tty/serial/8250_boca.c b/drivers/tty/serial/8250/8250_boca.c similarity index 100% rename from drivers/tty/serial/8250_boca.c rename to drivers/tty/serial/8250/8250_boca.c diff --git a/drivers/tty/serial/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c similarity index 100% rename from drivers/tty/serial/8250_dw.c rename to drivers/tty/serial/8250/8250_dw.c diff --git a/drivers/tty/serial/8250_early.c b/drivers/tty/serial/8250/8250_early.c similarity index 100% rename from drivers/tty/serial/8250_early.c rename to drivers/tty/serial/8250/8250_early.c diff --git a/drivers/tty/serial/8250_exar_st16c554.c b/drivers/tty/serial/8250/8250_exar_st16c554.c similarity index 100% rename from drivers/tty/serial/8250_exar_st16c554.c rename to drivers/tty/serial/8250/8250_exar_st16c554.c diff --git a/drivers/tty/serial/8250_fourport.c b/drivers/tty/serial/8250/8250_fourport.c similarity index 100% rename from drivers/tty/serial/8250_fourport.c rename to drivers/tty/serial/8250/8250_fourport.c diff --git a/drivers/tty/serial/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c similarity index 100% rename from drivers/tty/serial/8250_fsl.c rename to drivers/tty/serial/8250/8250_fsl.c diff --git a/drivers/tty/serial/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c similarity index 100% rename from drivers/tty/serial/8250_gsc.c rename to drivers/tty/serial/8250/8250_gsc.c diff --git a/drivers/tty/serial/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c similarity index 100% rename from drivers/tty/serial/8250_hp300.c rename to drivers/tty/serial/8250/8250_hp300.c diff --git a/drivers/tty/serial/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c similarity index 100% rename from drivers/tty/serial/8250_hub6.c rename to drivers/tty/serial/8250/8250_hub6.c diff --git a/drivers/tty/serial/8250_mca.c b/drivers/tty/serial/8250/8250_mca.c similarity index 100% rename from drivers/tty/serial/8250_mca.c rename to drivers/tty/serial/8250/8250_mca.c diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c similarity index 100% rename from drivers/tty/serial/8250_pci.c rename to drivers/tty/serial/8250/8250_pci.c diff --git a/drivers/tty/serial/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c similarity index 100% rename from drivers/tty/serial/8250_pnp.c rename to drivers/tty/serial/8250/8250_pnp.c diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig new file mode 100644 index 000000000000..591f8018e7dd --- /dev/null +++ b/drivers/tty/serial/8250/Kconfig @@ -0,0 +1,280 @@ +# +# The 8250/16550 serial drivers. You shouldn't be in this list unless +# you somehow have an implicit or explicit dependency on SERIAL_8250. +# + +config SERIAL_8250 + tristate "8250/16550 and compatible serial support" + select SERIAL_CORE + ---help--- + This selects whether you want to include the driver for the standard + serial ports. The standard answer is Y. People who might say N + here are those that are setting up dedicated Ethernet WWW/FTP + servers, or users that have one of the various bus mice instead of a + serial mouse and don't intend to use their machine's standard serial + port for anything. (Note that the Cyclades and Stallion multi + serial port drivers do not need this driver built in for them to + work.) + + To compile this driver as a module, choose M here: the + module will be called 8250. + [WARNING: Do not compile this driver as a module if you are using + non-standard serial ports, since the configuration information will + be lost when the driver is unloaded. This limitation may be lifted + in the future.] + + BTW1: If you have a mouseman serial mouse which is not recognized by + the X window system, try running gpm first. + + BTW2: If you intend to use a software modem (also called Winmodem) + under Linux, forget it. These modems are crippled and require + proprietary drivers which are only available under Windows. + + Most people will say Y or M here, so that they can use serial mice, + modems and similar devices connecting to the standard serial ports. + +config SERIAL_8250_CONSOLE + bool "Console on 8250/16550 and compatible serial port" + depends on SERIAL_8250=y + select SERIAL_CORE_CONSOLE + ---help--- + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). This could be useful if some terminal or printer is connected + to that serial port. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyS1". (Try "man bootparam" or see the documentation of + your boot loader (grub or lilo or loadlin) about how to pass options + to the kernel at boot time.) + + If you don't have a VGA card installed and you say Y here, the + kernel will automatically use the first serial line, /dev/ttyS0, as + system console. + + You can set that using a kernel command line option such as + "console=uart8250,io,0x3f8,9600n8" + "console=uart8250,mmio,0xff5e0000,115200n8". + and it will switch to normal serial console when the corresponding + port is ready. + "earlycon=uart8250,io,0x3f8,9600n8" + "earlycon=uart8250,mmio,0xff5e0000,115200n8". + it will not only setup early console. + + If unsure, say N. + +config FIX_EARLYCON_MEM + bool + depends on X86 + default y + +config SERIAL_8250_GSC + tristate + depends on SERIAL_8250 && GSC + default SERIAL_8250 + +config SERIAL_8250_PCI + tristate "8250/16550 PCI device support" if EXPERT + depends on SERIAL_8250 && PCI + default SERIAL_8250 + help + This builds standard PCI serial support. You may be able to + disable this feature if you only need legacy serial support. + Saves about 9K. + +config SERIAL_8250_PNP + tristate "8250/16550 PNP device support" if EXPERT + depends on SERIAL_8250 && PNP + default SERIAL_8250 + help + This builds standard PNP serial support. You may be able to + disable this feature if you only need legacy serial support. + +config SERIAL_8250_HP300 + tristate + depends on SERIAL_8250 && HP300 + default SERIAL_8250 + +config SERIAL_8250_CS + tristate "8250/16550 PCMCIA device support" + depends on PCMCIA && SERIAL_8250 + ---help--- + Say Y here to enable support for 16-bit PCMCIA serial devices, + including serial port cards, modems, and the modem functions of + multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are + credit-card size devices often used with laptops.) + + To compile this driver as a module, choose M here: the + module will be called serial_cs. + + If unsure, say N. + +config SERIAL_8250_NR_UARTS + int "Maximum number of 8250/16550 serial ports" + depends on SERIAL_8250 + default "4" + help + Set this to the number of serial ports you want the driver + to support. This includes any ports discovered via ACPI or + PCI enumeration and any ports that may be added at run-time + via hot-plug, or any ISA multi-port serial cards. + +config SERIAL_8250_RUNTIME_UARTS + int "Number of 8250/16550 serial ports to register at runtime" + depends on SERIAL_8250 + range 0 SERIAL_8250_NR_UARTS + default "4" + help + Set this to the maximum number of serial ports you want + the kernel to register at boot time. This can be overridden + with the module parameter "nr_uarts", or boot-time parameter + 8250.nr_uarts + +config SERIAL_8250_EXTENDED + bool "Extended 8250/16550 serial driver options" + depends on SERIAL_8250 + help + If you wish to use any non-standard features of the standard "dumb" + driver, say Y here. This includes HUB6 support, shared serial + interrupts, special multiport support, support for more than the + four COM 1/2/3/4 boards, etc. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about serial driver options. If unsure, say N. + +config SERIAL_8250_MANY_PORTS + bool "Support more than 4 legacy serial ports" + depends on SERIAL_8250_EXTENDED && !IA64 + help + Say Y here if you have dumb serial boards other than the four + standard COM 1/2/3/4 ports. This may happen if you have an AST + FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available + from ), or other custom + serial port hardware which acts similar to standard serial port + hardware. If you only use the standard COM 1/2/3/4 ports, you can + say N here to save some memory. You can also say Y if you have an + "intelligent" multiport card such as Cyclades, Digiboards, etc. + +# +# Multi-port serial cards +# + +config SERIAL_8250_FOURPORT + tristate "Support Fourport cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have an AST FourPort serial board. + + To compile this driver as a module, choose M here: the module + will be called 8250_fourport. + +config SERIAL_8250_ACCENT + tristate "Support Accent cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have an Accent Async serial board. + + To compile this driver as a module, choose M here: the module + will be called 8250_accent. + +config SERIAL_8250_BOCA + tristate "Support Boca cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have a Boca serial board. Please read the Boca + mini-HOWTO, available from + + To compile this driver as a module, choose M here: the module + will be called 8250_boca. + +config SERIAL_8250_EXAR_ST16C554 + tristate "Support Exar ST16C554/554D Quad UART" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + The Uplogix Envoy TU301 uses this Exar Quad UART. If you are + tinkering with your Envoy TU301, or have a machine with this UART, + say Y here. + + To compile this driver as a module, choose M here: the module + will be called 8250_exar_st16c554. + +config SERIAL_8250_HUB6 + tristate "Support Hub6 cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have a HUB6 serial board. + + To compile this driver as a module, choose M here: the module + will be called 8250_hub6. + +# +# Misc. options/drivers. +# + +config SERIAL_8250_SHARE_IRQ + bool "Support for sharing serial interrupts" + depends on SERIAL_8250_EXTENDED + help + Some serial boards have hardware support which allows multiple dumb + serial ports on the same board to share a single IRQ. To enable + support for this in the serial driver, say Y here. + +config SERIAL_8250_DETECT_IRQ + bool "Autodetect IRQ on standard ports (unsafe)" + depends on SERIAL_8250_EXTENDED + help + Say Y here if you want the kernel to try to guess which IRQ + to use for your serial port. + + This is considered unsafe; it is far better to configure the IRQ in + a boot script using the setserial command. + + If unsure, say N. + +config SERIAL_8250_RSA + bool "Support RSA serial ports" + depends on SERIAL_8250_EXTENDED + help + ::: To be written ::: + +config SERIAL_8250_MCA + tristate "Support 8250-type ports on MCA buses" + depends on SERIAL_8250 != n && MCA + help + Say Y here if you have a MCA serial ports. + + To compile this driver as a module, choose M here: the module + will be called 8250_mca. + +config SERIAL_8250_ACORN + tristate "Acorn expansion card serial port support" + depends on ARCH_ACORN && SERIAL_8250 + help + If you have an Atomwide Serial card or Serial Port card for an Acorn + system, say Y to this option. The driver can handle 1, 2, or 3 port + cards. If unsure, say N. + +config SERIAL_8250_RM9K + bool "Support for MIPS RM9xxx integrated serial port" + depends on SERIAL_8250 != n && SERIAL_RM9000 + select SERIAL_8250_SHARE_IRQ + help + Selecting this option will add support for the integrated serial + port hardware found on MIPS RM9122 and similar processors. + If unsure, say N. + +config SERIAL_8250_FSL + bool + depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550 + default PPC + +config SERIAL_8250_DW + tristate "Support for Synopsys DesignWare 8250 quirks" + depends on SERIAL_8250 && OF + help + Selecting this option will enable handling of the extra features + present in the Synopsys DesignWare APB UART. diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile new file mode 100644 index 000000000000..867bba738908 --- /dev/null +++ b/drivers/tty/serial/8250/Makefile @@ -0,0 +1,20 @@ +# +# Makefile for the 8250 serial device drivers. +# + +obj-$(CONFIG_SERIAL_8250) += 8250.o +obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o +obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o +obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o +obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o +obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o +obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o +obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o +obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o +obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o +obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o +obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o +obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o +obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o +obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/8250/m32r_sio.c similarity index 100% rename from drivers/tty/serial/m32r_sio.c rename to drivers/tty/serial/8250/m32r_sio.c diff --git a/drivers/tty/serial/m32r_sio.h b/drivers/tty/serial/8250/m32r_sio.h similarity index 100% rename from drivers/tty/serial/m32r_sio.h rename to drivers/tty/serial/8250/m32r_sio.h diff --git a/drivers/tty/serial/m32r_sio_reg.h b/drivers/tty/serial/8250/m32r_sio_reg.h similarity index 100% rename from drivers/tty/serial/m32r_sio_reg.h rename to drivers/tty/serial/8250/m32r_sio_reg.h diff --git a/drivers/tty/serial/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c similarity index 100% rename from drivers/tty/serial/serial_cs.c rename to drivers/tty/serial/8250/serial_cs.c diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index aca2386c5ef1..0bff23897509 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -5,279 +5,7 @@ menu "Serial drivers" depends on HAS_IOMEM -# -# The new 8250/16550 serial drivers -config SERIAL_8250 - tristate "8250/16550 and compatible serial support" - select SERIAL_CORE - ---help--- - This selects whether you want to include the driver for the standard - serial ports. The standard answer is Y. People who might say N - here are those that are setting up dedicated Ethernet WWW/FTP - servers, or users that have one of the various bus mice instead of a - serial mouse and don't intend to use their machine's standard serial - port for anything. (Note that the Cyclades and Stallion multi - serial port drivers do not need this driver built in for them to - work.) - - To compile this driver as a module, choose M here: the - module will be called 8250. - [WARNING: Do not compile this driver as a module if you are using - non-standard serial ports, since the configuration information will - be lost when the driver is unloaded. This limitation may be lifted - in the future.] - - BTW1: If you have a mouseman serial mouse which is not recognized by - the X window system, try running gpm first. - - BTW2: If you intend to use a software modem (also called Winmodem) - under Linux, forget it. These modems are crippled and require - proprietary drivers which are only available under Windows. - - Most people will say Y or M here, so that they can use serial mice, - modems and similar devices connecting to the standard serial ports. - -config SERIAL_8250_CONSOLE - bool "Console on 8250/16550 and compatible serial port" - depends on SERIAL_8250=y - select SERIAL_CORE_CONSOLE - ---help--- - If you say Y here, it will be possible to use a serial port as the - system console (the system console is the device which receives all - kernel messages and warnings and which allows logins in single user - mode). This could be useful if some terminal or printer is connected - to that serial port. - - Even if you say Y here, the currently visible virtual console - (/dev/tty0) will still be used as the system console by default, but - you can alter that using a kernel command line option such as - "console=ttyS1". (Try "man bootparam" or see the documentation of - your boot loader (grub or lilo or loadlin) about how to pass options - to the kernel at boot time.) - - If you don't have a VGA card installed and you say Y here, the - kernel will automatically use the first serial line, /dev/ttyS0, as - system console. - - You can set that using a kernel command line option such as - "console=uart8250,io,0x3f8,9600n8" - "console=uart8250,mmio,0xff5e0000,115200n8". - and it will switch to normal serial console when the corresponding - port is ready. - "earlycon=uart8250,io,0x3f8,9600n8" - "earlycon=uart8250,mmio,0xff5e0000,115200n8". - it will not only setup early console. - - If unsure, say N. - -config FIX_EARLYCON_MEM - bool - depends on X86 - default y - -config SERIAL_8250_GSC - tristate - depends on SERIAL_8250 && GSC - default SERIAL_8250 - -config SERIAL_8250_PCI - tristate "8250/16550 PCI device support" if EXPERT - depends on SERIAL_8250 && PCI - default SERIAL_8250 - help - This builds standard PCI serial support. You may be able to - disable this feature if you only need legacy serial support. - Saves about 9K. - -config SERIAL_8250_PNP - tristate "8250/16550 PNP device support" if EXPERT - depends on SERIAL_8250 && PNP - default SERIAL_8250 - help - This builds standard PNP serial support. You may be able to - disable this feature if you only need legacy serial support. - -config SERIAL_8250_FSL - bool - depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550 - default PPC - -config SERIAL_8250_HP300 - tristate - depends on SERIAL_8250 && HP300 - default SERIAL_8250 - -config SERIAL_8250_CS - tristate "8250/16550 PCMCIA device support" - depends on PCMCIA && SERIAL_8250 - ---help--- - Say Y here to enable support for 16-bit PCMCIA serial devices, - including serial port cards, modems, and the modem functions of - multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are - credit-card size devices often used with laptops.) - - To compile this driver as a module, choose M here: the - module will be called serial_cs. - - If unsure, say N. - -config SERIAL_8250_NR_UARTS - int "Maximum number of 8250/16550 serial ports" - depends on SERIAL_8250 - default "4" - help - Set this to the number of serial ports you want the driver - to support. This includes any ports discovered via ACPI or - PCI enumeration and any ports that may be added at run-time - via hot-plug, or any ISA multi-port serial cards. - -config SERIAL_8250_RUNTIME_UARTS - int "Number of 8250/16550 serial ports to register at runtime" - depends on SERIAL_8250 - range 0 SERIAL_8250_NR_UARTS - default "4" - help - Set this to the maximum number of serial ports you want - the kernel to register at boot time. This can be overridden - with the module parameter "nr_uarts", or boot-time parameter - 8250.nr_uarts - -config SERIAL_8250_EXTENDED - bool "Extended 8250/16550 serial driver options" - depends on SERIAL_8250 - help - If you wish to use any non-standard features of the standard "dumb" - driver, say Y here. This includes HUB6 support, shared serial - interrupts, special multiport support, support for more than the - four COM 1/2/3/4 boards, etc. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about serial driver options. If unsure, say N. - -config SERIAL_8250_MANY_PORTS - bool "Support more than 4 legacy serial ports" - depends on SERIAL_8250_EXTENDED && !IA64 - help - Say Y here if you have dumb serial boards other than the four - standard COM 1/2/3/4 ports. This may happen if you have an AST - FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available - from ), or other custom - serial port hardware which acts similar to standard serial port - hardware. If you only use the standard COM 1/2/3/4 ports, you can - say N here to save some memory. You can also say Y if you have an - "intelligent" multiport card such as Cyclades, Digiboards, etc. - -# -# Multi-port serial cards -# - -config SERIAL_8250_FOURPORT - tristate "Support Fourport cards" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - Say Y here if you have an AST FourPort serial board. - - To compile this driver as a module, choose M here: the module - will be called 8250_fourport. - -config SERIAL_8250_ACCENT - tristate "Support Accent cards" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - Say Y here if you have an Accent Async serial board. - - To compile this driver as a module, choose M here: the module - will be called 8250_accent. - -config SERIAL_8250_BOCA - tristate "Support Boca cards" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - Say Y here if you have a Boca serial board. Please read the Boca - mini-HOWTO, available from - - To compile this driver as a module, choose M here: the module - will be called 8250_boca. - -config SERIAL_8250_EXAR_ST16C554 - tristate "Support Exar ST16C554/554D Quad UART" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - The Uplogix Envoy TU301 uses this Exar Quad UART. If you are - tinkering with your Envoy TU301, or have a machine with this UART, - say Y here. - - To compile this driver as a module, choose M here: the module - will be called 8250_exar_st16c554. - -config SERIAL_8250_HUB6 - tristate "Support Hub6 cards" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - Say Y here if you have a HUB6 serial board. - - To compile this driver as a module, choose M here: the module - will be called 8250_hub6. - -config SERIAL_8250_SHARE_IRQ - bool "Support for sharing serial interrupts" - depends on SERIAL_8250_EXTENDED - help - Some serial boards have hardware support which allows multiple dumb - serial ports on the same board to share a single IRQ. To enable - support for this in the serial driver, say Y here. - -config SERIAL_8250_DETECT_IRQ - bool "Autodetect IRQ on standard ports (unsafe)" - depends on SERIAL_8250_EXTENDED - help - Say Y here if you want the kernel to try to guess which IRQ - to use for your serial port. - - This is considered unsafe; it is far better to configure the IRQ in - a boot script using the setserial command. - - If unsure, say N. - -config SERIAL_8250_RSA - bool "Support RSA serial ports" - depends on SERIAL_8250_EXTENDED - help - ::: To be written ::: - -config SERIAL_8250_MCA - tristate "Support 8250-type ports on MCA buses" - depends on SERIAL_8250 != n && MCA - help - Say Y here if you have a MCA serial ports. - - To compile this driver as a module, choose M here: the module - will be called 8250_mca. - -config SERIAL_8250_ACORN - tristate "Acorn expansion card serial port support" - depends on ARCH_ACORN && SERIAL_8250 - help - If you have an Atomwide Serial card or Serial Port card for an Acorn - system, say Y to this option. The driver can handle 1, 2, or 3 port - cards. If unsure, say N. - -config SERIAL_8250_RM9K - bool "Support for MIPS RM9xxx integrated serial port" - depends on SERIAL_8250 != n && SERIAL_RM9000 - select SERIAL_8250_SHARE_IRQ - help - Selecting this option will add support for the integrated serial - port hardware found on MIPS RM9122 and similar processors. - If unsure, say N. - -config SERIAL_8250_DW - tristate "Support for Synopsys DesignWare 8250 quirks" - depends on SERIAL_8250 && OF - help - Selecting this option will enable handling of the extra features - present in the Synopsys DesignWare APB UART. +source "drivers/tty/serial/8250/Kconfig" comment "Non-8250 serial port support" diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index f5b01f2ce525..a6d1ac049965 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -14,22 +14,9 @@ obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o -obj-$(CONFIG_SERIAL_8250) += 8250.o -obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o -obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o -obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o -obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o -obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o -obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o -obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o -obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o -obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o -obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o -obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o -obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o -obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o -obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o -obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o +# Now bring in any enabled 8250/16450/16550 type drivers. +obj-$(CONFIG_SERIAL_8250) += 8250/ + obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o From 791b7d7cf69de11275e4dccec2f538eec02cbff6 Mon Sep 17 00:00:00 2001 From: Renato Caldas Date: Fri, 6 Jan 2012 15:20:51 +0000 Subject: [PATCH 065/380] USB: serial: CP210x: Added USB-ID for the Link Instruments MSO-19 This device is a Oscilloscope/Logic Analizer/Pattern Generator/TDR, using a Silabs CP2103 USB to UART Bridge. Signed-off-by: Renato Caldas Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index fba1147ed916..c2b5d4a09b16 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -138,6 +138,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ + { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { } /* Terminating Entry */ }; From 55b2afbb92ad92e9f6b0aa4354eb1c94589280c3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 16 Jan 2012 00:36:48 +0100 Subject: [PATCH 066/380] USB: cp210x: call generic open last in open Make sure port is fully initialised before calling generic open. Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index c2b5d4a09b16..bb4290bfe59d 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -410,13 +410,10 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) return result; } - result = usb_serial_generic_open(tty, port); - if (result) - return result; - /* Configure the termios structure */ cp210x_get_termios(tty, port); - return 0; + + return usb_serial_generic_open(tty, port); } static void cp210x_close(struct usb_serial_port *port) From 7f482fc88ac47662228d6b1f05759797c8936a30 Mon Sep 17 00:00:00 2001 From: Preston Fick Date: Mon, 16 Jan 2012 18:14:09 -0600 Subject: [PATCH 067/380] USB: cp210x: fix CP2104 baudrate usage This fix changes the way baudrates are set on the CP210x devices from Silicon Labs. The CP2101/2/3 will respond to both a GET/SET_BAUDDIV command, and GET/SET_BAUDRATE command, while CP2104 and higher devices only respond to GET/SET_BAUDRATE. The current cp210x.ko driver in kernel version 3.2.0 only implements the GET/SET_BAUDDIV command. This patch implements the two new codes for the GET/SET_BAUDRATE commands. Then there is a change in the way that the baudrate is assigned or retrieved. This is done according to the CP210x USB specification in AN571. This document can be found here: http://www.silabs.com/pages/DownloadDoc.aspx?FILEURL=Support%20Documents/TechnicalDocs/AN571.pdf&src=DocumentationWebPart Sections 5.3/5.4 describe the USB packets for the old baudrate method. Sections 5.5/5.6 describe the USB packets for the new method. This patch also implements the new request scheme, and eliminates the unnecessary baudrate calculations since it uses the "actual baudrate" method. This patch solves the problem reported for the CP2104 in bug 42586, and also keeps support for all other devices (CP2101/2/3). This patchfile is also attached to the bug report on bugzilla.kernel.org. This patch has been developed and test on the 3.2.0 mainline kernel version under Ubuntu 10.11. Signed-off-by: Preston Fick [duplicate patch also sent by Johan - gregkh] Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index bb4290bfe59d..f4267886e255 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -202,6 +202,8 @@ static struct usb_serial_driver cp210x_device = { #define CP210X_EMBED_EVENTS 0x15 #define CP210X_GET_EVENTSTATE 0x16 #define CP210X_SET_CHARS 0x19 +#define CP210X_GET_BAUDRATE 0x1D +#define CP210X_SET_BAUDRATE 0x1E /* CP210X_IFC_ENABLE */ #define UART_ENABLE 0x0001 @@ -465,10 +467,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, dbg("%s - port %d", __func__, port->number); - cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2); - /* Convert to baudrate */ - if (baud) - baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); + cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4); dbg("%s - baud rate = %d", __func__, baud); *baudp = baud; @@ -597,8 +596,7 @@ static void cp210x_set_termios(struct tty_struct *tty, if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { dbg("%s - Setting baud rate to %d baud", __func__, baud); - if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, - ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { + if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, 4)) { dbg("Baud rate requested not supported by device"); baud = tty_termios_baud_rate(old_termios); } From ba1960257c5980f9b58057995ce3394bd8e48ca3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 10 Jan 2012 15:19:54 +0200 Subject: [PATCH 068/380] mac80211: update oper_channel on ibss join Commit 13c40c5 ("mac80211: Add HT operation modes for IBSS") broke ibss operation by mistakenly removing the local->oper_channel update (causing ibss to start on the wrong channel). fix it. Signed-off-by: Eliad Peller Acked-by: Simon Wunderlich Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index b3d76b756cd5..a4643969a13b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -106,6 +106,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; + local->oper_channel = chan; channel_type = ifibss->channel_type; if (channel_type > NL80211_CHAN_HT20 && !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) From 405385f8ce7a2ed8f82e216d88b5282142e1288b Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 11 Jan 2012 13:11:50 +0200 Subject: [PATCH 069/380] mac80211: set bss_conf.idle when vif is connected __ieee80211_recalc_idle() iterates through the vifs, sets bss_conf.idle = true if they are disconnected, and increases "count" if they are not (which later gets evaluated in order to determine whether the device is idle). However, the loop doesn't set bss_conf.idle = false (along with increasing "count"), causing the device idle state and the vif idle state to get out of sync in some cases. Signed-off-by: Eliad Peller Signed-off-by: John W. Linville --- net/mac80211/iface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index e47768cb8cb3..01a21c2f6ab3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1314,6 +1314,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) continue; } /* count everything else */ + sdata->vif.bss_conf.idle = false; count++; } From b49ba04a3a0382e7314d990707c21094c410425a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 19 Jan 2012 08:20:57 -0800 Subject: [PATCH 070/380] iwlwifi: fix PCI-E transport "inta" race When an interrupt comes in, we read the reason bits and collect them into "trans_pcie->inta". This happens with the spinlock held. However, there's a bug resetting this variable -- that happens after the spinlock has been released. This means that it is possible for interrupts to be missed if the reset happens after some other interrupt reasons were already added to the variable. I found this by code inspection, looking for a reason that we sometimes see random commands time out. It seems possible that this causes such behaviour, but I can't say for sure right now since it happens extremely infrequently on my test systems. Cc: stable@vger.kernel.org [3.2] Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 752493f00406..65d1f05007be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -972,11 +972,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) } #endif - spin_unlock_irqrestore(&trans->shrd->lock, flags); - /* saved interrupt in inta variable now we can reset trans_pcie->inta */ trans_pcie->inta = 0; + spin_unlock_irqrestore(&trans->shrd->lock, flags); + /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { IWL_ERR(trans, "Hardware error detected. Restarting.\n"); From 34b76fcaee574017862ea3fa0efdcd77a9d0e57d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 16 Jan 2012 00:36:49 +0100 Subject: [PATCH 071/380] USB: cp210x: fix up set_termios variables [Based on a patch from Johan, mangled by gregkh to keep things in line] Fix up the variable usage in the set_termios call. Signed-off-by: Johan Hovold Cc: Preston Fick Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f4267886e255..1270e024bb3e 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -580,7 +580,8 @@ static void cp210x_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag, old_cflag; - unsigned int baud = 0, bits; + u32 baud; + unsigned int bits; unsigned int modem_ctl[4]; dbg("%s - port %d", __func__, port->number); @@ -596,7 +597,7 @@ static void cp210x_set_termios(struct tty_struct *tty, if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { dbg("%s - Setting baud rate to %d baud", __func__, baud); - if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, 4)) { + if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, sizeof(baud))) { dbg("Baud rate requested not supported by device"); baud = tty_termios_baud_rate(old_termios); } From be125d9c8d59560e7cc2d6e2b65c8fd233498ab7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 16 Jan 2012 00:36:50 +0100 Subject: [PATCH 072/380] USB: cp210x: do not map baud rates to B0 We do not implement B0 hangup yet so map low baudrates to 300bps. Signed-off-by: Johan Hovold Cc: Preston Fick Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 1270e024bb3e..ad7599ed5df9 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -363,8 +363,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port, * Quantises the baud rate as per AN205 Table 1 */ static unsigned int cp210x_quantise_baudrate(unsigned int baud) { - if (baud <= 56) baud = 0; - else if (baud <= 300) baud = 300; + if (baud <= 300) + baud = 300; else if (baud <= 600) baud = 600; else if (baud <= 1200) baud = 1200; else if (baud <= 1800) baud = 1800; From e5990874e511d5bbca23b3396419480cb2ca0ee7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 16 Jan 2012 00:36:51 +0100 Subject: [PATCH 073/380] USB: cp210x: clean up, refactor and document speed handling Clean up and refactor speed handling. Document baud rate handling for CP210{1,2,4,5,10}. Signed-off-by: Johan Hovold Cc: Preston Fick Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 69 ++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index ad7599ed5df9..2d2d23933ba6 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -39,6 +39,8 @@ static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *port); static void cp210x_get_termios_port(struct usb_serial_port *port, unsigned int *cflagp, unsigned int *baudp); +static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *, + struct ktermios *); static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, struct ktermios*); static int cp210x_tiocmget(struct tty_struct *); @@ -576,11 +578,62 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, *cflagp = cflag; } +/* + * CP2101 supports the following baud rates: + * + * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800, + * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600 + * + * CP2102 and CP2103 support the following additional rates: + * + * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000, + * 576000 + * + * The device will map a requested rate to a supported one, but the result + * of requests for rates greater than 1053257 is undefined (see AN205). + * + * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud, + * respectively, with an error less than 1%. The actual rates are determined + * by + * + * div = round(freq / (2 x prescale x request)) + * actual = freq / (2 x prescale x div) + * + * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps + * or 1 otherwise. + * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1 + * otherwise. + */ +static void cp210x_change_speed(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + u32 baud; + + baud = tty->termios->c_ospeed; + + /* This maps the requested rate to a rate valid on cp2102 or cp2103. + * + * NOTE: B0 is not implemented. + */ + baud = cp210x_quantise_baudrate(baud); + + dbg("%s - setting baud rate to %u", __func__, baud); + if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, + sizeof(baud))) { + dev_warn(&port->dev, "failed to set baud rate to %u\n", baud); + if (old_termios) + baud = old_termios->c_ospeed; + else + baud = 9600; + } + + tty_encode_baud_rate(tty, baud, baud); +} + static void cp210x_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag, old_cflag; - u32 baud; unsigned int bits; unsigned int modem_ctl[4]; @@ -591,19 +644,9 @@ static void cp210x_set_termios(struct tty_struct *tty, cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; - baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty)); - /* If the baud rate is to be updated*/ - if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { - dbg("%s - Setting baud rate to %d baud", __func__, - baud); - if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, sizeof(baud))) { - dbg("Baud rate requested not supported by device"); - baud = tty_termios_baud_rate(old_termios); - } - } - /* Report back the resulting baud rate */ - tty_encode_baud_rate(tty, baud, baud); + if (tty->termios->c_ospeed != old_termios->c_ospeed) + cp210x_change_speed(tty, port, old_termios); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { From cdc32fd6f7b2b2580d7f1b74563f888e4dd9eb8a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 16 Jan 2012 00:36:52 +0100 Subject: [PATCH 074/380] USB: cp210x: initialise baud rate at open The newer cp2104 devices require the baud rate to be initialised after power on. Make sure it is set when port is opened. Signed-off-by: Johan Hovold Cc: Preston Fick Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2d2d23933ba6..5c3e8592fd22 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -417,6 +417,10 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) /* Configure the termios structure */ cp210x_get_termios(tty, port); + /* The baud rate must be initialised on cp2104 */ + if (tty) + cp210x_change_speed(tty, port, NULL); + return usb_serial_generic_open(tty, port); } From d1620ca9e7bb0030068c3b45b653defde8839dac Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 16 Jan 2012 00:36:53 +0100 Subject: [PATCH 075/380] USB: cp210x: allow more baud rates above 1Mbaud Allow more baud rates to be set in [1M,2M] baud. Signed-off-by: Johan Hovold Cc: Preston Fick Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 5c3e8592fd22..8dbf51a43c45 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -394,10 +394,10 @@ static unsigned int cp210x_quantise_baudrate(unsigned int baud) { else if (baud <= 491520) baud = 460800; else if (baud <= 567138) baud = 500000; else if (baud <= 670254) baud = 576000; - else if (baud <= 1053257) baud = 921600; - else if (baud <= 1474560) baud = 1228800; - else if (baud <= 2457600) baud = 1843200; - else baud = 3686400; + else if (baud < 1000000) + baud = 921600; + else if (baud > 2000000) + baud = 2000000; return baud; } @@ -615,7 +615,8 @@ static void cp210x_change_speed(struct tty_struct *tty, baud = tty->termios->c_ospeed; - /* This maps the requested rate to a rate valid on cp2102 or cp2103. + /* This maps the requested rate to a rate valid on cp2102 or cp2103, + * or to an arbitrary rate in [1M,2M]. * * NOTE: B0 is not implemented. */ From 52a749992ca6a0fd304609af40ed3bfd6cef4660 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Jan 2012 12:02:38 -0800 Subject: [PATCH 076/380] Revert "USB: usb-skeleton.c: fix open/disconnect race" This reverts commit 26c71a79cade5ccad80e0752cd82f3518df48fb3. It's not needed, to quote Ming Lei: Looks you have queued the patch into your tree, but just now I find the patch is not needed at all, since we have had minor_rwsem(drivers/usb/core/file.c) for this purpose, please drop the patch, sorry for it. Cc: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usb-skeleton.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 8efeae24764f..b4a71679c933 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -27,8 +27,6 @@ #define USB_SKEL_VENDOR_ID 0xfff0 #define USB_SKEL_PRODUCT_ID 0xfff0 -static DEFINE_MUTEX(skel_mutex); - /* table of devices that work with this driver */ static const struct usb_device_id skel_table[] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, @@ -101,25 +99,18 @@ static int skel_open(struct inode *inode, struct file *file) goto exit; } - mutex_lock(&skel_mutex); dev = usb_get_intfdata(interface); if (!dev) { - mutex_unlock(&skel_mutex); retval = -ENODEV; goto exit; } /* increment our usage count for the device */ kref_get(&dev->kref); - mutex_unlock(&skel_mutex); /* lock the device to allow correctly handling errors * in resumption */ mutex_lock(&dev->io_mutex); - if (!dev->interface) { - retval = -ENODEV; - goto out_err; - } retval = usb_autopm_get_interface(interface); if (retval) @@ -127,11 +118,7 @@ static int skel_open(struct inode *inode, struct file *file) /* save our object in the file's private structure */ file->private_data = dev; - -out_err: mutex_unlock(&dev->io_mutex); - if (retval) - kref_put(&dev->kref, skel_delete); exit: return retval; @@ -611,6 +598,7 @@ static void skel_disconnect(struct usb_interface *interface) int minor = interface->minor; dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); /* give back our minor */ usb_deregister_dev(interface, &skel_class); @@ -622,12 +610,8 @@ static void skel_disconnect(struct usb_interface *interface) usb_kill_anchored_urbs(&dev->submitted); - mutex_lock(&skel_mutex); - usb_set_intfdata(interface, NULL); - /* decrement our usage count */ kref_put(&dev->kref, skel_delete); - mutex_unlock(&skel_mutex); dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor); } From 6d443d8499e4e59ffb949759cdded32730f8d2f6 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 13 Jan 2012 21:32:06 -0800 Subject: [PATCH 077/380] usb: io_ti: Make edge_remove_sysfs_attrs the port_remove method. Calling edge_remove_sysfs_attrs from edge_disconnect is too late as the device has already been removed from sysfs. Do the simple and obvious thing and make edge_remove_sysfs_attrs the port_remove method. Signed-off-by: Eric W. Biederman Reported-by: Wolfgang Frisch Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 65bf06aa591a..5818bfc3261e 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2657,15 +2657,7 @@ cleanup: static void edge_disconnect(struct usb_serial *serial) { - int i; - struct edgeport_port *edge_port; - dbg("%s", __func__); - - for (i = 0; i < serial->num_ports; ++i) { - edge_port = usb_get_serial_port_data(serial->port[i]); - edge_remove_sysfs_attrs(edge_port->port); - } } static void edge_release(struct usb_serial *serial) @@ -2744,6 +2736,7 @@ static struct usb_serial_driver edgeport_1port_device = { .disconnect = edge_disconnect, .release = edge_release, .port_probe = edge_create_sysfs_attrs, + .port_remove = edge_remove_sysfs_attrs, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -2775,6 +2768,7 @@ static struct usb_serial_driver edgeport_2port_device = { .disconnect = edge_disconnect, .release = edge_release, .port_probe = edge_create_sysfs_attrs, + .port_remove = edge_remove_sysfs_attrs, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, From e423d7401fd0717cb56a6cf51dd8341cc3e800d2 Mon Sep 17 00:00:00 2001 From: Kentaro Matsuyama Date: Thu, 12 Jan 2012 23:07:51 +0900 Subject: [PATCH 078/380] USB: option: Add LG docomo L-02C Add vendor and product ID for USB 3G/LTE modem of docomo L-02C Signed-off-by: Kentaro Matsuyama Cc: stable 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 420d9857394a..ea126a4490cd 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -480,6 +480,10 @@ static void option_instat_callback(struct urb *urb); #define ZD_VENDOR_ID 0x0685 #define ZD_PRODUCT_7000 0x7000 +/* LG products */ +#define LG_VENDOR_ID 0x1004 +#define LG_PRODUCT_L02C 0x618f + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1183,6 +1187,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, + { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); From 1097ccebe630170080c41df0edcf88e0626e9c75 Mon Sep 17 00:00:00 2001 From: Harrison Metzger Date: Sun, 15 Jan 2012 08:43:24 -0600 Subject: [PATCH 079/380] USB: usbsevseg: fix max length This changes the max length for the usb seven segment delcom device to 8 from 6. Delcom has both 6 and 8 variants and having 8 works fine with devices which are only 6. Signed-off-by: Harrison Metzger Signed-off-by: Stuart Pook Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbsevseg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c index 107bf13b1cf1..b2d82b937392 100644 --- a/drivers/usb/misc/usbsevseg.c +++ b/drivers/usb/misc/usbsevseg.c @@ -24,7 +24,7 @@ #define VENDOR_ID 0x0fc5 #define PRODUCT_ID 0x1227 -#define MAXLEN 6 +#define MAXLEN 8 /* table of devices that work with this driver */ static const struct usb_device_id id_table[] = { From ce597919361dcec97341151690e780eade2a9cf4 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 13 Jan 2012 21:32:59 -0800 Subject: [PATCH 080/380] sysfs: Complain bitterly about attempts to remove files from nonexistent directories. Recently an OOPS was observed from the usb serial io_ti driver when it tried to remove sysfs directories. Upon investigation it turns out this driver was always buggy and that a recent sysfs change had stopped guarding itself against removing attributes from sysfs directories that had already been removed. :( Historically we have been silent about attempting to files from nonexistent sysfs directories and have politely returned error codes. That has resulted in people writing broken code that ignores the error codes. Issue a kernel WARNING and a stack backtrace to make it clear in no uncertain terms that abusing sysfs is not ok, and the callers need to fix their code. This change transforms the io_ti OOPS into a more comprehensible error message and stack backtrace. Signed-off-by: Eric W. Biederman Reported-by: Wolfgang Frisch Cc: stable Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 6 ++++++ fs/sysfs/inode.c | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 62f4fb37789e..00012e31829d 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -493,6 +493,12 @@ int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr, const void *ns = NULL; int err; + if (!dir_sd) { + WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n", + kobject_name(kobj)); + return -ENOENT; + } + err = 0; if (!sysfs_ns_type(dir_sd)) goto out; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 4a802b4a9056..85eb81683a29 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -318,8 +318,11 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const cha struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; - if (!dir_sd) + if (!dir_sd) { + WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n", + name); return -ENOENT; + } sysfs_addrm_start(&acxt, dir_sd); From c428b70c1e115c5649707a602742e34130d19428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 16 Jan 2012 12:41:47 +0100 Subject: [PATCH 081/380] USB: cdc-wdm: updating desc->length must be protected by spin_lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wdm_in_callback() will also touch this field, so we cannot change it without locking Cc: stable@vger.kernel.org Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 1c50baff7725..1f6b5c8394b4 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -467,7 +467,9 @@ retry: for (i = 0; i < desc->length - cntr; i++) desc->ubuf[i] = desc->ubuf[i + cntr]; + spin_lock_irq(&desc->iuspin); desc->length -= cntr; + spin_unlock_irq(&desc->iuspin); /* in case we had outstanding data */ if (!desc->length) clear_bit(WDM_READ, &desc->flags); From e8537bd2c4f325a4796da33564ddcef9489b7feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 16 Jan 2012 12:41:48 +0100 Subject: [PATCH 082/380] USB: cdc-wdm: use two mutexes to allow simultaneous read and write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit using a separate read and write mutex for locking is sufficient to make the driver accept simultaneous read and write. This improves useability a lot. Signed-off-by: Bjørn Mork Cc: stable Cc: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 49 +++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 1f6b5c8394b4..023d271c2614 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -88,7 +88,8 @@ struct wdm_device { int count; dma_addr_t shandle; dma_addr_t ihandle; - struct mutex lock; + struct mutex wlock; + struct mutex rlock; wait_queue_head_t wait; struct work_struct rxwork; int werr; @@ -323,7 +324,7 @@ static ssize_t wdm_write } /* concurrent writes and disconnect */ - r = mutex_lock_interruptible(&desc->lock); + r = mutex_lock_interruptible(&desc->wlock); rv = -ERESTARTSYS; if (r) { kfree(buf); @@ -386,7 +387,7 @@ static ssize_t wdm_write out: usb_autopm_put_interface(desc->intf); outnp: - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); outnl: return rv < 0 ? rv : count; } @@ -399,7 +400,7 @@ static ssize_t wdm_read struct wdm_device *desc = file->private_data; - rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */ + rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ if (rv < 0) return -ERESTARTSYS; @@ -476,7 +477,7 @@ retry: rv = cntr; err: - mutex_unlock(&desc->lock); + mutex_unlock(&desc->rlock); return rv; } @@ -542,7 +543,8 @@ static int wdm_open(struct inode *inode, struct file *file) } intf->needs_remote_wakeup = 1; - mutex_lock(&desc->lock); + /* using write lock to protect desc->count */ + mutex_lock(&desc->wlock); if (!desc->count++) { desc->werr = 0; desc->rerr = 0; @@ -555,7 +557,7 @@ static int wdm_open(struct inode *inode, struct file *file) } else { rv = 0; } - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); usb_autopm_put_interface(desc->intf); out: mutex_unlock(&wdm_mutex); @@ -567,9 +569,11 @@ static int wdm_release(struct inode *inode, struct file *file) struct wdm_device *desc = file->private_data; mutex_lock(&wdm_mutex); - mutex_lock(&desc->lock); + + /* using write lock to protect desc->count */ + mutex_lock(&desc->wlock); desc->count--; - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); if (!desc->count) { dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); @@ -667,7 +671,8 @@ next_desc: desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); if (!desc) goto out; - mutex_init(&desc->lock); + mutex_init(&desc->rlock); + mutex_init(&desc->wlock); spin_lock_init(&desc->iuspin); init_waitqueue_head(&desc->wait); desc->wMaxCommand = maxcom; @@ -781,10 +786,12 @@ static void wdm_disconnect(struct usb_interface *intf) /* to terminate pending flushes */ clear_bit(WDM_IN_USE, &desc->flags); spin_unlock_irqrestore(&desc->iuspin, flags); - mutex_lock(&desc->lock); + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); kill_urbs(desc); cancel_work_sync(&desc->rxwork); - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); + mutex_unlock(&desc->rlock); wake_up_all(&desc->wait); if (!desc->count) cleanup(desc); @@ -800,8 +807,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); /* if this is an autosuspend the caller does the locking */ - if (!PMSG_IS_AUTO(message)) - mutex_lock(&desc->lock); + if (!PMSG_IS_AUTO(message)) { + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); + } spin_lock_irq(&desc->iuspin); if (PMSG_IS_AUTO(message) && @@ -817,8 +826,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) kill_urbs(desc); cancel_work_sync(&desc->rxwork); } - if (!PMSG_IS_AUTO(message)) - mutex_unlock(&desc->lock); + if (!PMSG_IS_AUTO(message)) { + mutex_unlock(&desc->wlock); + mutex_unlock(&desc->rlock); + } return rv; } @@ -856,7 +867,8 @@ static int wdm_pre_reset(struct usb_interface *intf) { struct wdm_device *desc = usb_get_intfdata(intf); - mutex_lock(&desc->lock); + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); kill_urbs(desc); /* @@ -878,7 +890,8 @@ static int wdm_post_reset(struct usb_interface *intf) int rv; rv = recover_from_urb_loss(desc); - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); + mutex_unlock(&desc->rlock); return 0; } From 62aaf24dc125d7c55c93e313d15611f152b030c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 16 Jan 2012 15:11:57 +0100 Subject: [PATCH 083/380] USB: cdc-wdm: call wake_up_all to allow driver to shutdown on device removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wdm_disconnect() waits for the mutex held by wdm_read() before calling wake_up_all(). This causes a deadlock, preventing device removal to complete. Do the wake_up_all() before we start waiting for the locks. Signed-off-by: Bjørn Mork Cc: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 023d271c2614..07aa67611b65 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -786,13 +786,13 @@ static void wdm_disconnect(struct usb_interface *intf) /* to terminate pending flushes */ clear_bit(WDM_IN_USE, &desc->flags); spin_unlock_irqrestore(&desc->iuspin, flags); + wake_up_all(&desc->wait); mutex_lock(&desc->rlock); mutex_lock(&desc->wlock); kill_urbs(desc); cancel_work_sync(&desc->rxwork); mutex_unlock(&desc->wlock); mutex_unlock(&desc->rlock); - wake_up_all(&desc->wait); if (!desc->count) cleanup(desc); mutex_unlock(&wdm_mutex); From 655e247daf52b202a6c2d0f8a06dd2051e756ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 16 Jan 2012 15:11:59 +0100 Subject: [PATCH 084/380] USB: cdc-wdm: better allocate a buffer that is at least as big as we tell the USB core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As it turns out, there was a mismatch between the allocated inbuf size (desc->bMaxPacketSize0, typically something like 64) and the length we specified in the URB (desc->wMaxCommand, typically something like 2048) Signed-off-by: Bjørn Mork Cc: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 07aa67611b65..a940ad9d0d8f 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -723,7 +723,7 @@ next_desc: goto err; desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf), - desc->bMaxPacketSize0, + desc->wMaxCommand, GFP_KERNEL, &desc->response->transfer_dma); if (!desc->inbuf) From 2492c6e6454ff3edb11e273b071a6ea80a199c71 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 12 Jan 2012 10:55:13 +0100 Subject: [PATCH 085/380] drivers/usb/host/ehci-fsl.c: add missing iounmap Add missing iounmap in error handling code, in a case where the function already preforms iounmap on some other execution path. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e; statement S,S1; int ret; @@ e = \(ioremap\|ioremap_nocache\)(...) ... when != iounmap(e) if (<+...e...+>) S ... when any when != iounmap(e) *if (...) { ... when != iounmap(e) return ...; } ... when any iounmap(e); // Signed-off-by: Julia Lawall Acked-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index e90344a17631..b556a72264d1 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -125,7 +125,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, */ if (pdata->init && pdata->init(pdev)) { retval = -ENODEV; - goto err3; + goto err4; } /* Enable USB controller, 83xx or 8536 */ From 3297f86a3d4158e052538c7b9a3dea9c855a1b42 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 24 Jan 2012 10:18:10 +0200 Subject: [PATCH 086/380] usb: serial: kobil_sct: fix compile warning: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following compile warning: drivers/usb/serial/kobil_sct.c: In function ‘__check_debug’: drivers/usb/serial/kobil_sct.c:719:1: warning: return from incompatible pointer type [enabled by default] Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 5d3beeeb5fd9..a92a3efb507b 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -38,7 +38,7 @@ #include #include "kobil_sct.h" -static int debug; +static bool debug; /* Version Information */ #define DRIVER_VERSION "21/05/2004" From 194b3af4eb4b7ba84e2e4274daf9f58aa958bd04 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 24 Jan 2012 11:58:15 -0500 Subject: [PATCH 087/380] USB: OHCI: fix new compiler warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch (as1515) fixes some unavoidably dumb compiler warnings: CC [M] drivers/usb/renesas_usbhs/mod.o In file included from drivers/usb/host/ohci-hcd.c:101:0: drivers/usb/host/ohci-dbg.c: In function ‘fill_registers_buffer’: drivers/usb/host/ohci-dbg.c:656:2: warning: the comparison will always evaluate as ‘true’ for the address of ‘next’ will never be NULL [-Waddress] drivers/usb/host/ohci-dbg.c:675:3: warning: the comparison will always evaluate as ‘true’ for the address of ‘next’ will never be NULL [-Waddress] Instead of trying to fix the macro to work under all cirumstances, just add a second macro for use in cases where the "next" argument is the address of a local variable. Unfortunately the macro cannot be replaced by a real subroutine, because there's no va_list version of ohci_dbg() or dev_dbg(). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-dbg.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 5179fcd73d8a..e4bcb62b930a 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -82,6 +82,14 @@ urb_print(struct urb * urb, char * str, int small, int status) ohci_dbg(ohci,format, ## arg ); \ } while (0); +/* Version for use where "next" is the address of a local variable */ +#define ohci_dbg_nosw(ohci, next, size, format, arg...) \ + do { \ + unsigned s_len; \ + s_len = scnprintf(*next, *size, format, ## arg); \ + *size -= s_len; *next += s_len; \ + } while (0); + static void ohci_dump_intr_mask ( struct ohci_hcd *ohci, @@ -653,7 +661,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* dump driver info, then registers in spec order */ - ohci_dbg_sw (ohci, &next, &size, + ohci_dbg_nosw(ohci, &next, &size, "bus %s, device %s\n" "%s\n" "%s\n", @@ -672,7 +680,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* hcca */ if (ohci->hcca) - ohci_dbg_sw (ohci, &next, &size, + ohci_dbg_nosw(ohci, &next, &size, "hcca frame 0x%04x\n", ohci_frame_no(ohci)); /* other registers mostly affect frame timings */ From 0fcd97789028e8ec286a4248c20a71eae239ba61 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 21 Jan 2012 11:02:56 -0800 Subject: [PATCH 088/380] kernel-doc: fix new warning in usb.h Fix new kernel-doc warning: Warning(include/linux/usb.h:1251): No description found for parameter 'num_mapped_sgs' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- include/linux/usb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/usb.h b/include/linux/usb.h index 27a4e16d2bf1..69d845739bc2 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1073,6 +1073,7 @@ typedef void (*usb_complete_t)(struct urb *); * which the host controller driver should use in preference to the * transfer_buffer. * @sg: scatter gather buffer list + * @num_mapped_sgs: (internal) number of mapped sg entries * @num_sgs: number of entries in the sg list * @transfer_buffer_length: How big is transfer_buffer. The transfer may * be broken up into chunks according to the current maximum packet From 8dd5d2f15134c17302e67d9aedb0c51e00c354b0 Mon Sep 17 00:00:00 2001 From: Lucas Kannebley Tavares Date: Mon, 9 Jan 2012 17:39:24 -0200 Subject: [PATCH 089/380] Updated TTY MAINTAINERS info Greg Kroah-Hartman is the current TTY maintainer, however he wouldn't appear listed as such upon running get_maintainers.pl for drivers under drivers/tty/serial. Signed-off-by: Lucas Kannebley Tavares Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 89b70df91f4f..a723385f9140 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6664,7 +6664,7 @@ TTY LAYER M: Greg Kroah-Hartman S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git -F: drivers/tty/* +F: drivers/tty/ F: drivers/tty/serial/serial_core.c F: include/linux/serial_core.h F: include/linux/serial.h From 26aa38cafae0dbef3b2fe75ea487c83313c36d45 Mon Sep 17 00:00:00 2001 From: Lucas Kannebley Tavares Date: Mon, 9 Jan 2012 10:58:06 -0200 Subject: [PATCH 090/380] jsm: Fixed EEH recovery error There was an error on the jsm driver that would cause it to be unable to recover after a second error is detected. At the first error, the device recovers properly: [72521.485691] EEH: Detected PCI bus error on device 0003:02:00.0 [72521.485695] EEH: This PCI device has failed 1 times in the last hour: ... [72532.035693] ttyn3 at MMIO 0x0 (irq = 49) is a jsm [72532.105689] jsm: Port 3 added However, at the second error, it cascades until EEH disables the device: [72631.229549] Call Trace: ... [72641.725687] jsm: Port 3 added [72641.725695] EEH: Detected PCI bus error on device 0003:02:00.0 [72641.725698] EEH: This PCI device has failed 3 times in the last hour: It was caused because the PCI state was not being saved after the first restore. Therefore, at the second recovery the PCI state would not be restored. Signed-off-by: Lucas Kannebley Tavares Signed-off-by: Breno Leitao Acked-by: Thadeu Lima de Souza Cascardo Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/jsm/jsm_driver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index 7c867a046c97..7545fe1b9925 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c @@ -251,6 +251,7 @@ static void jsm_io_resume(struct pci_dev *pdev) struct jsm_board *brd = pci_get_drvdata(pdev); pci_restore_state(pdev); + pci_save_state(pdev); jsm_uart_port_init(brd); } From 0eee50af5b13e00b3fb7a5fe8480419a71b8235d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 12 Jan 2012 22:55:15 +0100 Subject: [PATCH 091/380] TTY: fix UV serial console regression Commit 74c2107759d (serial: Use block_til_ready helper) and its fixup 3f582b8c110 (serial: fix termios settings in open) introduced a regression on UV systems. The serial eventually freezes while being used. It's completely unpredictable and sometimes needs a heap of traffic to happen first. To reproduce this, yast installation was used as it turned out to be pretty reliable in reproducing. Especially during installation process where one doesn't have an SSH daemon running. And no monitor as the HW is completely headless. So this was fun to find. Given the machine doesn't boot on vanilla before 2.6.36 final. (And the commits above are older.) Unless there is some bad race in the code, the hardware seems to be pretty broken. Otherwise pure MSR read should not cause such a bug, or? So to prevent the bug, revert to the old behavior. I.e. read modem status only if we really have to -- for non-CLOCAL set serials. Non-CLOCAL works on this hardware OK, I tried. See? I don't. And document that shit. Signed-off-by: Jiri Slaby Cc: stable References: https://lkml.org/lkml/2011/12/6/573 References: https://bugzilla.novell.com/show_bug.cgi?id=718518 Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index ef9dd628ba0b..bf6e238146ae 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -227,7 +227,6 @@ int tty_port_block_til_ready(struct tty_port *port, int do_clocal = 0, retval; unsigned long flags; DEFINE_WAIT(wait); - int cd; /* block if port is in the process of being closed */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { @@ -284,11 +283,14 @@ int tty_port_block_til_ready(struct tty_port *port, retval = -ERESTARTSYS; break; } - /* Probe the carrier. For devices with no carrier detect this - will always return true */ - cd = tty_port_carrier_raised(port); + /* + * Probe the carrier. For devices with no carrier detect + * tty_port_carrier_raised will always return true. + * Never ask drivers if CLOCAL is set, this causes troubles + * on some hardware. + */ if (!(port->flags & ASYNC_CLOSING) && - (do_clocal || cd)) + (do_clocal || tty_port_carrier_raised(port))) break; if (signal_pending(current)) { retval = -ERESTARTSYS; From f54367f9de1b52000c008d3f68512f44cc392816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 19 Jan 2012 22:35:05 +0100 Subject: [PATCH 092/380] Documentation/pinctrl: fix a few syntax errors in code examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Stephen Warren Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 6727b92bc2fb..5324d3199f34 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -857,42 +857,41 @@ case), we define a mapping like this: ... { - .name "2bit" + .name = "2bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { - .name "4bit" + .name = "4bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { - .name "4bit" + .name = "4bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { - .name "8bit" + .name = "8bit" .ctrl_dev_name = "pinctrl-foo", - .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { - .name "8bit" + .name = "8bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { - .name "8bit" + .name = "8bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_3_grp", @@ -995,7 +994,7 @@ This is enabled by simply setting the .hog_on_boot field in the map to true, like this: { - .name "POWERMAP" + .name = "POWERMAP" .ctrl_dev_name = "pinctrl-foo", .function = "power_func", .hog_on_boot = true, From f9d41d7cb5a3a4fe9585d47e518d779d2aef8c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 19 Jan 2012 22:42:48 +0100 Subject: [PATCH 093/380] pinctrl: unbreak error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's better to not line break error messages to allow easier grepping for them even when the line gets >80 chars. Additionally some minor reformating is done. Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux.c | 46 +++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index a76a348321bb..0b22037965b9 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -152,8 +152,7 @@ static int pin_request(struct pinctrl_dev *pctldev, status = 0; if (status) - dev_err(pctldev->dev, "->request on device %s failed " - "for pin %d\n", + dev_err(pctldev->dev, "->request on device %s failed for pin %d\n", pctldev->desc->name, pin); out_free_pin: if (status) { @@ -355,21 +354,20 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, /* First sanity check the new mapping */ for (i = 0; i < num_maps; i++) { if (!maps[i].name) { - pr_err("failed to register map %d: " - "no map name given\n", i); + pr_err("failed to register map %d: no map name given\n", + i); return -EINVAL; } if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { - pr_err("failed to register map %s (%d): " - "no pin control device given\n", + pr_err("failed to register map %s (%d): no pin control device given\n", maps[i].name, i); return -EINVAL; } if (!maps[i].function) { - pr_err("failed to register map %s (%d): " - "no function ID given\n", maps[i].name, i); + pr_err("failed to register map %s (%d): no function ID given\n", + maps[i].name, i); return -EINVAL; } @@ -442,8 +440,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev, ret = pin_request(pctldev, pins[i], func, NULL); if (ret) { dev_err(pctldev->dev, - "could not get pin %d for function %s " - "on device %s - conflicting mux mappings?\n", + "could not get pin %d for function %s on device %s - conflicting mux mappings?\n", pins[i], func ? : "(undefined)", pinctrl_dev_get_name(pctldev)); /* On error release all taken pins */ @@ -473,8 +470,7 @@ static void release_pins(struct pinctrl_dev *pctldev, ret = pctlops->get_group_pins(pctldev, group_selector, &pins, &num_pins); if (ret) { - dev_err(pctldev->dev, "could not get pins to release for " - "group selector %d\n", + dev_err(pctldev->dev, "could not get pins to release for group selector %d\n", group_selector); return; } @@ -526,8 +522,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, ret = pinctrl_get_group_selector(pctldev, groups[0]); if (ret < 0) { dev_err(pctldev->dev, - "function %s wants group %s but the pin " - "controller does not seem to have that group\n", + "function %s wants group %s but the pin controller does not seem to have that group\n", pmxops->get_function_name(pctldev, func_selector), groups[0]); return ret; @@ -535,8 +530,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, if (num_groups > 1) dev_dbg(pctldev->dev, - "function %s support more than one group, " - "default-selecting first group %s (%d)\n", + "function %s support more than one group, default-selecting first group %s (%d)\n", pmxops->get_function_name(pctldev, func_selector), groups[0], ret); @@ -628,10 +622,8 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev, if (pmx->pctldev && pmx->pctldev != pctldev) { dev_err(pctldev->dev, - "different pin control devices given for device %s, " - "function %s\n", - devname, - map->function); + "different pin control devices given for device %s, function %s\n", + devname, map->function); return -EINVAL; } pmx->dev = dev; @@ -695,7 +687,6 @@ static void pinmux_free_groups(struct pinmux *pmx) */ struct pinmux *pinmux_get(struct device *dev, const char *name) { - struct pinmux_map const *map = NULL; struct pinctrl_dev *pctldev = NULL; const char *devname = NULL; @@ -745,8 +736,7 @@ struct pinmux *pinmux_get(struct device *dev, const char *name) else if (map->ctrl_dev_name) devname = map->ctrl_dev_name; - pr_warning("could not find a pinctrl device for pinmux " - "function %s, fishy, they shall all have one\n", + pr_warning("could not find a pinctrl device for pinmux function %s, fishy, they shall all have one\n", map->function); pr_warning("given pinctrl device name: %s", devname ? devname : "UNDEFINED"); @@ -932,8 +922,8 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev, * without any problems, so then we can hog pinmuxes for * all devices that just want a static pin mux at this point. */ - dev_err(pctldev->dev, "map %s wants to hog a non-system " - "pinmux, this is not going to work\n", map->name); + dev_err(pctldev->dev, "map %s wants to hog a non-system pinmux, this is not going to work\n", + map->name); return -EINVAL; } @@ -1122,13 +1112,15 @@ static int pinmux_show(struct seq_file *s, void *what) seq_printf(s, "device: %s function: %s (%u),", pinctrl_dev_get_name(pmx->pctldev), - pmxops->get_function_name(pctldev, pmx->func_selector), + pmxops->get_function_name(pctldev, + pmx->func_selector), pmx->func_selector); seq_printf(s, " groups: ["); list_for_each_entry(grp, &pmx->groups, node) { seq_printf(s, " %s (%u)", - pctlops->get_group_name(pctldev, grp->group_selector), + pctlops->get_group_name(pctldev, + grp->group_selector), grp->group_selector); } seq_printf(s, " ]"); From 0215716083cac67ff7ea3e3efdc9943bdb462274 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 20 Jan 2012 08:17:22 -0800 Subject: [PATCH 094/380] pinctrl: free debugfs entries when unloading a pinmux driver We were not cleaning up properly after unloading a pinmux driver compiled as module. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 14 +++++++++++++- drivers/pinctrl/core.h | 3 +++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 569bdb3ef104..d9d35fcbfc6b 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -510,10 +510,12 @@ static struct dentry *debugfs_root; static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) { - static struct dentry *device_root; + struct dentry *device_root; device_root = debugfs_create_dir(dev_name(pctldev->dev), debugfs_root); + pctldev->device_root = device_root; + if (IS_ERR(device_root) || !device_root) { pr_warn("failed to create debugfs directory for %s\n", dev_name(pctldev->dev)); @@ -529,6 +531,11 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) pinconf_init_device_debugfs(device_root, pctldev); } +static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev) +{ + debugfs_remove_recursive(pctldev->device_root); +} + static void pinctrl_init_debugfs(void) { debugfs_root = debugfs_create_dir("pinctrl", NULL); @@ -553,6 +560,10 @@ static void pinctrl_init_debugfs(void) { } +static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev) +{ +} + #endif /** @@ -641,6 +652,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) if (pctldev == NULL) return; + pinctrl_remove_device_debugfs(pctldev); pinmux_unhog_maps(pctldev); /* TODO: check that no pinmuxes are still active? */ mutex_lock(&pinctrldev_list_mutex); diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 177a3310547f..cfa86da6b4b1 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -41,6 +41,9 @@ struct pinctrl_dev { struct device *dev; struct module *owner; void *driver_data; +#ifdef CONFIG_DEBUG_FS + struct dentry *device_root; +#endif #ifdef CONFIG_PINMUX struct mutex pinmux_hogs_lock; struct list_head pinmux_hogs; From 3bc4f0d8f65b396d214a31195a91c0394c5bf628 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Mon, 16 Jan 2012 15:52:36 +0530 Subject: [PATCH 095/380] omap-serial :Make the suspend/resume functions depend on CONFIG_PM_SLEEP. The macro SET_SYSTEM_SLEEP_PM_OPS depends CONFIG_PM_SLEEP. The patch defines the suspend and resume functions for CONFIG_PM_SLEEP instead of CONFIG_SUSPEND. Signed-off-by: Shubhrajyoti D Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index d192dcbb82f5..33e3360023b3 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1160,7 +1160,7 @@ static struct uart_driver serial_omap_reg = { .cons = OMAP_CONSOLE, }; -#ifdef CONFIG_SUSPEND +#ifdef CONFIG_PM_SLEEP static int serial_omap_suspend(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); From b5148856a2f732e7e99edad22bb8e2037af28ad3 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Mon, 16 Jan 2012 15:52:37 +0530 Subject: [PATCH 096/380] omap-serial: make serial_omap_restore_context depend on CONFIG_PM_RUNTIME The function serial_omap_restore_context is called only from serial_omap_runtime_resume which depends on CONFIG_PM_RUNTIME. Make serial_omap_restore_context also compile conditionally. if CONFIG_PM_RUNTIME is not defined below warn may be seen. LD net/xfrm/built-in.o drivers/tty/serial/omap-serial.c:1524: warning: 'serial_omap_restore_context' defined but not used CC drivers/tty/vt/selection.o Acked-by: Govindraj.R Signed-off-by: Shubhrajyoti D Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 33e3360023b3..1c2426931484 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1521,6 +1521,7 @@ static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1) } } +#ifdef CONFIG_PM_RUNTIME static void serial_omap_restore_context(struct uart_omap_port *up) { if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) @@ -1550,7 +1551,6 @@ static void serial_omap_restore_context(struct uart_omap_port *up) serial_out(up, UART_OMAP_MDR1, up->mdr1); } -#ifdef CONFIG_PM_RUNTIME static int serial_omap_runtime_suspend(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); From 0a697b22252c9d7208b5fb3e9fbd124dd229f1d2 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Sat, 21 Jan 2012 00:27:40 -0700 Subject: [PATCH 097/380] tty: serial: OMAP: ensure FIFO levels are set correctly in non-DMA mode Ensure FIFO levels are set correctly in non-DMA mode (the default). This patch will cause a receive FIFO threshold interrupt to be raised when there is at least one byte in the RX FIFO. It will also cause a transmit FIFO threshold interrupt when there is only one byte remaining in the TX FIFO. These changes fix the receive interrupt problem and part of the transmit interrupt problem. A separate set of issues must be worked around for the transmit path to have a basic level of functionality; a subsequent patch will address these. DMA operation is unaffected by this patch. Signed-off-by: Paul Walmsley Cc: Tomi Valkeinen Cc: Govindraj Raja Cc: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 35 ++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 1c2426931484..ca54f038ab45 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -46,6 +46,18 @@ #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/ +/* SCR register bitmasks */ +#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) +#define OMAP_UART_SCR_TX_TRIG_GRANU1_MASK (1 << 6) + +/* FCR register bitmasks */ +#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6 +#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6) +#define OMAP_UART_FCR_TX_FIFO_TRIG_SHIFT 4 + +/* TLR register bitmasks */ +#define OMAP_UART_TLR_TX_FIFO_TRIG_DMA_SHIFT 0 + static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; /* Forward declaration of functions */ @@ -694,6 +706,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, unsigned char efr = 0; unsigned long flags = 0; unsigned int baud, quot; + u32 tlr; switch (termios->c_cflag & CSIZE) { case CS5: @@ -811,14 +824,28 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); /* FIFO ENABLE, DMA MODE */ - serial_out(up, UART_FCR, up->fcr); - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + + up->scr |= OMAP_UART_SCR_TX_TRIG_GRANU1_MASK; + up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK; if (up->use_dma) { - serial_out(up, UART_TI752_TLR, 0); - up->scr |= (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8); + tlr = 0; + } else { + up->scr &= ~OMAP_UART_SCR_TX_EMPTY; + + /* Set receive FIFO threshold to 1 */ + up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; + up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT); + + /* Set TX FIFO threshold to "63" (actually 1) */ + up->fcr |= (0x3 << OMAP_UART_FCR_TX_FIFO_TRIG_SHIFT); + tlr = (0xf << OMAP_UART_TLR_TX_FIFO_TRIG_DMA_SHIFT); } + serial_out(up, UART_TI752_TLR, tlr); + serial_out(up, UART_FCR, up->fcr); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_OMAP_SCR, up->scr); serial_out(up, UART_EFR, up->efr); From 43cf7c0bebf50d0b68aa42ae6d24cf08e3f24823 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Sat, 21 Jan 2012 00:27:41 -0700 Subject: [PATCH 098/380] tty: serial: OMAP: transmit FIFO threshold interrupts don't wake the chip It seems that when the transmit FIFO threshold is reached on OMAP UARTs, it does not result in a PRCM wakeup. This appears to be a silicon bug. This means that if the MPU powerdomain is in a low-power state, the MPU will not be awakened to refill the FIFO until the next interrupt from another device. The best solution, at least for the short term, would be for the OMAP serial driver to call a OMAP subarchitecture function to prevent the MPU powerdomain from entering a low power state while the FIFO has data to transmit. However, we no longer have a clean way to do this, since patches that add platform_data function pointers have been deprecated by the OMAP maintainer. So we attempt to work around this as well. The workarounds depend on the setting of CONFIG_CPU_IDLE. When CONFIG_CPU_IDLE=n, the driver will now only transmit one byte at a time. This causes the transmit FIFO threshold interrupt to stay active until there is no more data to be sent. Thus, the MPU powerdomain stays on during transmits. Aside from that energy consumption penalty, each transmitted byte results in a huge number of UART interrupts -- about five per byte. This wastes CPU time and is quite inefficient, but is probably the most expedient workaround in this case. When CONFIG_CPU_IDLE=y, there is a slightly more direct workaround: the PM QoS constraint can be abused to keep the MPU powerdomain on. This results in a normal number of interrupts, but, similar to the above workaround, wastes power by preventing the MPU from entering WFI. Future patches are planned for the 3.4 merge window to implement more efficient, but also more disruptive, workarounds to these problems. DMA operation is unaffected by this patch. Signed-off-by: Paul Walmsley Cc: Tomi Valkeinen Cc: Govindraj Raja Cc: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/include/plat/omap-serial.h | 1 + drivers/tty/serial/omap-serial.c | 51 ++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 9ff444469f3d..12a64eb8c624 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -131,6 +131,7 @@ struct uart_omap_port { u32 context_loss_cnt; u32 errata; u8 wakeups_enabled; + u8 max_tx_count; struct pm_qos_request pm_qos_request; u32 latency; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index ca54f038ab45..e00ac05cfdb4 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -88,6 +88,49 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up) serial_out(up, UART_FCR, 0); } +/** + * serial_omap_block_cpu_low_power_state - prevent MPU pwrdm from leaving ON + * @up: struct uart_omap_port * + * + * Prevent the MPU powerdomain from entering a power state lower than + * ON. (It should be sufficient to prevent it from entering INACTIVE, + * but there is presently no easy way to do this.) This works around + * a suspected silicon bug in the OMAP UART IP blocks. The UARTs should + * wake the PRCM when the transmit FIFO threshold interrupt is raised, but + * they do not. See also serial_omap_allow_cpu_low_power_state(). No + * return value. + */ +static void serial_omap_block_cpu_low_power_state(struct uart_omap_port *up) +{ +#ifdef CONFIG_CPU_IDLE + up->latency = 1; + schedule_work(&up->qos_work); +#else + up->max_tx_count = 1; +#endif +} + +/** + * serial_omap_allow_cpu_low_power_state - remove power state restriction on MPU + * @up: struct uart_omap_port * + * + * Cancel the effects of serial_omap_block_cpu_low_power_state(). + * This should allow the MPU powerdomain to enter a power state lower + * than ON, assuming the rest of the kernel is not restricting it. + * This works around a suspected silicon bug in the OMAP UART IP + * blocks. The UARTs should wake the PRCM when the transmit FIFO + * threshold interrupt is raised, but they do not. No return value. + */ +static void serial_omap_allow_cpu_low_power_state(struct uart_omap_port *up) +{ +#ifdef CONFIG_CPU_IDLE + up->latency = up->calc_latency; + schedule_work(&up->qos_work); +#else + up->max_tx_count = up->port.fifosize / 4; +#endif +} + /* * serial_omap_get_divisor - calculate divisor value * @port: uart port info @@ -163,6 +206,9 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_IER, up->ier); } + if (!up->use_dma) + serial_omap_allow_cpu_low_power_state(up); + pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); } @@ -264,7 +310,7 @@ static void transmit_chars(struct uart_omap_port *up) serial_omap_stop_tx(&up->port); return; } - count = up->port.fifosize / 4; + count = up->max_tx_count; do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -297,6 +343,7 @@ static void serial_omap_start_tx(struct uart_port *port) if (!up->use_dma) { pm_runtime_get_sync(&up->pdev->dev); + serial_omap_block_cpu_low_power_state(up); serial_omap_enable_ier_thri(up); pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); @@ -1421,6 +1468,8 @@ static int serial_omap_probe(struct platform_device *pdev) up->port.fifosize = 64; up->port.ops = &serial_omap_pops; + up->max_tx_count = up->port.fifosize / 4; + if (pdev->dev.of_node) up->port.line = of_alias_get_id(pdev->dev.of_node, "serial"); else From 0dd2b62ada6f911fbd13e98e98f57f4edc42c604 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 10 Jan 2012 13:13:50 -0200 Subject: [PATCH 099/380] drivers: usb: Fix dependency for USB_HWA_HCD Fix the following build warning: warning: (USB_HWA_HCD) selects UWB_HWA which has unmet direct dependencies (UWB && USB) Signed-off-by: Fabio Estevam Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 91413cac97be..cc12dc2e5024 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -559,7 +559,7 @@ config USB_WHCI_HCD config USB_HWA_HCD tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)" depends on EXPERIMENTAL - depends on USB + depends on USB && UWB select USB_WUSB select UWB_HWA help From 3a0bac0676d7f433c12389fc0bc574f048f921c3 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Fri, 6 Jan 2012 13:33:28 +0100 Subject: [PATCH 100/380] usb: add support for STA2X11 host driver Signed-off-by: Alessandro Rubini Acked-by: Giancarlo Asnaghi Cc: Alan Cox Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 6 ++++++ drivers/usb/host/ohci-pci.c | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index f4b627d343ac..01bb7241d6ef 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -276,6 +276,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* Serial Bus Release Number is at PCI 0x60 offset */ pci_read_config_byte(pdev, 0x60, &ehci->sbrn); + if (pdev->vendor == PCI_VENDOR_ID_STMICRO + && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST) + ehci->sbrn = 0x20; /* ConneXT has no sbrn register */ /* Keep this around for a while just in case some EHCI * implementation uses legacy PCI PM support. This test @@ -526,6 +529,9 @@ static const struct pci_device_id pci_ids [] = { { /* handle any USB 2.0 EHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0), .driver_data = (unsigned long) &ehci_pci_hc_driver, + }, { + PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_HOST), + .driver_data = (unsigned long) &ehci_pci_hc_driver, }, { /* end: all zeroes */ } }; diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 6109810cc2d3..1843bb68ac7c 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -397,6 +397,10 @@ static const struct pci_device_id pci_ids [] = { { /* handle any USB OHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), .driver_data = (unsigned long) &ohci_pci_hc_driver, + }, { + /* The device in the ConneXT I/O hub has no class reg */ + PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_OHCI), + .driver_data = (unsigned long) &ohci_pci_hc_driver, }, { /* end: all zeroes */ } }; MODULE_DEVICE_TABLE (pci, pci_ids); From 15699e6fafc3a90e5fdc2ef30555a04dee62286f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 20 Jan 2012 01:49:57 +0100 Subject: [PATCH 101/380] USB: cdc-wdm: Avoid hanging on interface with no USB_CDC_DMM_TYPE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe does not strictly require the USB_CDC_DMM_TYPE descriptor, which is a good thing as it makes the driver usable on non-conforming interfaces. A user could e.g. bind to it to a CDC ECM interface by using the new_id and bind sysfs files. But this would fail with a 0 buffer length due to the missing descriptor. Fix by defining a reasonable fallback size: The minimum device receive buffer size required by the CDC WMC standard, revision 1.1 Signed-off-by: Bjørn Mork Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index a940ad9d0d8f..d2b3cffca3f7 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -57,6 +57,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); #define WDM_MAX 16 +/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */ +#define WDM_DEFAULT_BUFSIZE 256 static DEFINE_MUTEX(wdm_mutex); @@ -636,7 +638,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) struct usb_cdc_dmm_desc *dmhd; u8 *buffer = intf->altsetting->extra; int buflen = intf->altsetting->extralen; - u16 maxcom = 0; + u16 maxcom = WDM_DEFAULT_BUFSIZE; if (!buffer) goto out; From 2053c2d1b116282038fde3d60965ac158b1b8ba2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 15 Jan 2012 12:36:16 +0100 Subject: [PATCH 102/380] usb: mv-otg - Fix build if CONFIG_USB is not set ERROR: "usb_remove_hcd" [drivers/usb/otg/mv_otg.ko] undefined! ERROR: "usb_add_hcd" [drivers/usb/otg/mv_otg.ko] undefined! Signed-off-by: Geert Uytterhoeven -- Inpired by drivers/usb/otg/msm_otg.c. Is this correct? drivers/usb/otg/mv_otg.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/mv_otg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index db0d4fcdc8e2..b5fbe1452ab0 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c @@ -202,6 +202,7 @@ static void mv_otg_init_irq(struct mv_otg *mvotg) static void mv_otg_start_host(struct mv_otg *mvotg, int on) { +#ifdef CONFIG_USB struct otg_transceiver *otg = &mvotg->otg; struct usb_hcd *hcd; @@ -216,6 +217,7 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on) usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); else usb_remove_hcd(hcd); +#endif /* CONFIG_USB */ } static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) From 0c8b92f7f25927808fb465474e344b759bade612 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Jan 2012 15:32:34 -0800 Subject: [PATCH 103/380] Revert "drivers: usb: Fix dependency for USB_HWA_HCD" This reverts commit 0dd2b62ada6f911fbd13e98e98f57f4edc42c604. It causes a bunch of Kconfig errors: drivers/usb/host/Kconfig:559:error: recursive dependency detected! drivers/usb/host/Kconfig:559: symbol USB_HWA_HCD depends on UWB drivers/uwb/Kconfig:5: symbol UWB is selected by USB_WUSB drivers/usb/wusbcore/Kconfig:4: symbol USB_WUSB is selected by USB_HWA_HCD showing that this really wasn't the correct fix at all. Cc: Fabio Estevam Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index cc12dc2e5024..91413cac97be 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -559,7 +559,7 @@ config USB_WHCI_HCD config USB_HWA_HCD tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)" depends on EXPERIMENTAL - depends on USB && UWB + depends on USB select USB_WUSB select UWB_HWA help From 074cc73506f529f39fef32ad1c9e1d4cdd8acf6c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 24 Jan 2012 17:16:54 -0600 Subject: [PATCH 104/380] qcaux: add more Pantech UML190 and UML290 ports More ports we now know how to talk to. Signed-off-by: Dan Williams Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcaux.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 30b73e68a904..a34819884c1a 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,6 +36,7 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 +#define PANTECH_PRODUCT_UML190_VZW 0x3716 #define PANTECH_PRODUCT_UML290_VZW 0x3718 /* CMOTECH devices */ @@ -67,7 +68,11 @@ static struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */ + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */ + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); From d8d8ffa477831b713ddfa2ad4d0ca545f3b567e5 Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Wed, 18 Jan 2012 15:53:59 +0530 Subject: [PATCH 105/380] amba-pl011: do not disable RTS during shutdown In present driver, shutdown clears RTS and DTR in CR register. But the documentation "Documentation/serial/driver" suggests not to disable RTS and DTR in shutdown(). Also RTS and DTR is preserved between shutdown and startup calls, i.e. these are restored in startup if they were enabled while doing shutdown. So that if RTS and DTR are set using pl011_set_mctrl then it should continue even after shutdown->startup sequence. For throttling/unthrottling user should call pl011_set_mctrl. Signed-off-by: Shreshtha Kumar Sahu Acked-by: Linus Walleij Acked-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 9ae024025ff3..ce843d058e02 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -159,6 +159,7 @@ struct uart_amba_port { unsigned int fifosize; /* vendor-specific */ unsigned int lcrh_tx; /* vendor-specific */ unsigned int lcrh_rx; /* vendor-specific */ + unsigned int old_cr; /* state during shutdown */ bool autorts; char type[12]; bool interrupt_may_hang; /* vendor-specific */ @@ -1411,7 +1412,9 @@ static int pl011_startup(struct uart_port *port) while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) barrier(); - cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; + /* restore RTS and DTR */ + cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); + cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; writew(cr, uap->port.membase + UART011_CR); /* Clear pending error interrupts */ @@ -1469,6 +1472,7 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap, static void pl011_shutdown(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int cr; /* * disable all interrupts @@ -1488,9 +1492,16 @@ static void pl011_shutdown(struct uart_port *port) /* * disable the port + * disable the port. It should not disable RTS and DTR. + * Also RTS and DTR state should be preserved to restore + * it during startup(). */ uap->autorts = false; - writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR); + cr = readw(uap->port.membase + UART011_CR); + uap->old_cr = cr; + cr &= UART011_CR_RTS | UART011_CR_DTR; + cr |= UART01x_CR_UARTEN | UART011_CR_TXE; + writew(cr, uap->port.membase + UART011_CR); /* * disable break condition and fifos @@ -1905,6 +1916,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->vendor = vendor; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; + uap->old_cr = 0; uap->fifosize = vendor->fifosize; uap->interrupt_may_hang = vendor->interrupt_may_hang; uap->port.dev = &dev->dev; From ef605fdb33883d687cff5ba75095a91b313b4966 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 17 Jan 2012 11:52:28 +0100 Subject: [PATCH 106/380] serial: amba-pl011: lock console writes against interrupts Protect against pl011_console_write() and the interrupt for the console UART running concurrently on different CPUs. Otherwise the console_write could spin for a long time waiting for the UART to become not busy, while the other CPU continuously services UART interrupts and keeps the UART busy. The checks for sysrq and oops_in_progress are taken from 8250.c. Cc: stable Signed-off-by: Rabin Vincent Reviewed-by: Srinidhi Kasagar Reviewed-by: Bibek Basu Reviewed-by: Shreshtha Kumar Sahu Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index ce843d058e02..6800f5f26241 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1751,9 +1751,19 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) { struct uart_amba_port *uap = amba_ports[co->index]; unsigned int status, old_cr, new_cr; + unsigned long flags; + int locked = 1; clk_enable(uap->clk); + local_irq_save(flags); + if (uap->port.sysrq) + locked = 0; + else if (oops_in_progress) + locked = spin_trylock(&uap->port.lock); + else + spin_lock(&uap->port.lock); + /* * First save the CR then disable the interrupts */ @@ -1773,6 +1783,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) } while (status & UART01x_FR_BUSY); writew(old_cr, uap->port.membase + UART011_CR); + if (locked) + spin_unlock(&uap->port.lock); + local_irq_restore(flags); + clk_disable(uap->clk); } From a5492e6591b8fdf171236046f9d6194f9bb4062b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 21 Jan 2012 11:03:16 -0800 Subject: [PATCH 107/380] docbook: don't use serial_core.h in device-drivers book Fix new kernel-doc warning. This file no longer contains kernel-doc comments. Warning(include/linux/serial_core.h): no structured comments found Signed-off-by: Randy Dunlap Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- Documentation/DocBook/device-drivers.tmpl | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index b638e50cf8f6..b330b327032a 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -216,7 +216,6 @@ X!Isound/sound_firmware.c 16x50 UART Driver -!Iinclude/linux/serial_core.h !Edrivers/tty/serial/serial_core.c !Edrivers/tty/serial/8250.c From 773598357c0baf03081cf87f2b444f97744faf1e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 19 Jan 2012 11:28:56 -0800 Subject: [PATCH 108/380] serial: Fix wakeup init logic to speed up startup The synchronize_rcu() call resulting from making every serial driver wake-up capable (commit b3b708fa) slows boot down on my Tegra2x system (with CONFIG_PREEMPT disabled). But this is avoidable since it is the device_set_wakeup_enable() and then subsequence disable which causes the delay. We might as well just make the device wakeup capable but not actually enable it for wakeup until needed. Effectively the current code does this: device_set_wakeup_capable(dev, 1); device_set_wakeup_enable(dev, 1); device_set_wakeup_enable(dev, 0); We can just drop the last two lines. Before this change my boot log says: [ 0.227062] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled [ 0.702928] serial8250.0: ttyS0 at MMIO 0x70006040 (irq = 69) is a Tegra after: [ 0.227264] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled [ 0.227983] serial8250.0: ttyS0 at MMIO 0x70006040 (irq = 69) is a Tegra for saving of 450ms. Suggested-by: Rafael J. Wysocki Acked-by: Rafael J. Wysocki Signed-off-by: Simon Glass Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index c7bf31a6a7e7..13056180adf5 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2348,11 +2348,11 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) */ tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev); if (likely(!IS_ERR(tty_dev))) { - device_init_wakeup(tty_dev, 1); - device_set_wakeup_enable(tty_dev, 0); - } else + device_set_wakeup_capable(tty_dev, 1); + } else { printk(KERN_ERR "Cannot register tty device on line %d\n", uport->line); + } /* * Ensure UPF_DEAD is not set. From b30b3c60a25a4afbc49167ecb6210c291178ee5f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 25 Jan 2012 10:02:46 +0200 Subject: [PATCH 109/380] usb: musb: omap2430: minor cleanups. 1/ remove incorrect comment (it is a non-blocking notifier) 2/ Use correct symbolic return value for notifier 3/ Make sure otg_notifier_work is cancelled before module exit. Signed-off-by: NeilBrown Signed-off-by: Felipe Balbi --- drivers/usb/musb/omap2430.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index c27bbbf32b52..df719eae3b03 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -222,7 +222,6 @@ static inline void omap2430_low_level_init(struct musb *musb) musb_writel(musb->mregs, OTG_FORCESTDBY, l); } -/* blocking notifier support */ static int musb_otg_notifications(struct notifier_block *nb, unsigned long event, void *unused) { @@ -231,7 +230,7 @@ static int musb_otg_notifications(struct notifier_block *nb, musb->xceiv_event = event; schedule_work(&musb->otg_notifier_work); - return 0; + return NOTIFY_OK; } static void musb_otg_notifier_work(struct work_struct *data_notifier_work) @@ -386,6 +385,7 @@ static void omap2430_musb_disable(struct musb *musb) static int omap2430_musb_exit(struct musb *musb) { del_timer_sync(&musb_idle_timer); + cancel_work_sync(&musb->otg_notifier_work); omap2430_low_level_exit(musb); otg_put_transceiver(musb->xceiv); From 9fb83526a898f14adbd3f6f52fa7126f528f15ac Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jan 2012 15:19:20 +0000 Subject: [PATCH 110/380] ASoC: wm5100: Make sure we switch to button reporting mode When we have identified an accessory make sure we've flagged that we've done so in order to make sure we always report buttons and don't continue to polarity flip. Signed-off-by: Mark Brown --- sound/soc/codecs/wm5100.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 66f0611e68b6..3f8fd3ca9454 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2183,6 +2183,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec) if (wm5100->jack_detecting) { dev_dbg(codec->dev, "Microphone detected\n"); wm5100->jack_mic = true; + wm5100->jack_detecting = false; snd_soc_jack_report(wm5100->jack, SND_JACK_HEADSET, SND_JACK_HEADSET | SND_JACK_BTN_0); @@ -2221,6 +2222,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec) SND_JACK_BTN_0); } else if (wm5100->jack_detecting) { dev_dbg(codec->dev, "Headphone detected\n"); + wm5100->jack_detecting = false; snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE, SND_JACK_HEADPHONE); From a188fcba73837f83a78dc90a44998a978f50ac83 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jan 2012 17:57:16 +0000 Subject: [PATCH 111/380] ASoC: wm5100: Fix microphone configuration We need to write the configuration for each microphone to a different register. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm5100.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 3f8fd3ca9454..fb757af19363 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2612,6 +2612,13 @@ static const struct regmap_config wm5100_regmap = { .cache_type = REGCACHE_RBTREE, }; +static const unsigned int wm5100_mic_ctrl_reg[] = { + WM5100_IN1L_CONTROL, + WM5100_IN2L_CONTROL, + WM5100_IN3L_CONTROL, + WM5100_IN4L_CONTROL, +}; + static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -2744,7 +2751,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, } for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) { - regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL, + regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i], WM5100_IN1_MODE_MASK | WM5100_IN1_DMIC_SUP_MASK, (wm5100->pdata.in_mode[i] << From cf840551a884360841bd3d3ce1ad0868ff0b759a Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Wed, 18 Jan 2012 17:47:12 +0800 Subject: [PATCH 112/380] xHCI: Cleanup isoc transfer ring when TD length mismatch found When a TD length mismatch is found during isoc TRB enqueue, it directly returns -EINVAL. However, isoc transfer is partially enqueued at this time, and the ring should be cleared. This should be backported to kernels as old as 2.6.36, which contain the commit 522989a27c7badb608155b1f1dea3487ed431f74 "xhci: Fix failed enqueue in the middle of isoch TD." Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org --- drivers/usb/host/xhci-ring.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 5a818cbbab44..b62037bff688 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3324,7 +3324,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Check TD length */ if (running_total != td_len) { xhci_err(xhci, "ISOC TD length unmatch\n"); - return -EINVAL; + ret = -EINVAL; + goto cleanup; } } From 1b76d2ee4012f325ae14e0e71dad1a0835195906 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jan 2012 21:10:07 +0000 Subject: [PATCH 113/380] ASoC: wm8996: Mark register cache as dirty when regulators are disabled Otherwise we won't resync later. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 13aa2bdaa7d7..61f7daa4d0e6 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -108,7 +108,7 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \ struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \ disable_nb[n]); \ if (event & REGULATOR_EVENT_DISABLE) { \ - regcache_cache_only(wm8996->regmap, true); \ + regcache_mark_dirty(wm8996->regmap); \ } \ return 0; \ } From 5539a102882d5ddd1bb95ea9f6f43130a789cb7f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jan 2012 21:10:21 +0000 Subject: [PATCH 114/380] ASoC: wm8962: Mark register cache as dirty when regulators are disabled Otherwise we won't resync later. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 296de4e30d26..bda3da887d7e 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -96,7 +96,7 @@ static int wm8962_regulator_event_##n(struct notifier_block *nb, \ struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \ disable_nb[n]); \ if (event & REGULATOR_EVENT_DISABLE) { \ - regcache_cache_only(wm8962->regmap, true); \ + regcache_mark_dirty(wm8962->regmap); \ } \ return 0; \ } From 5c1b136b7bf702e550039cb0039ec9c790c48f99 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 25 Jan 2012 21:10:33 +0000 Subject: [PATCH 115/380] ASoC: wm5100: Mark register cache as dirty when regulators are disabled Otherwise we won't resync later. Signed-off-by: Mark Brown --- sound/soc/codecs/wm5100.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index fb757af19363..89f2af77b1c3 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1405,6 +1405,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_OFF: regcache_cache_only(wm5100->regmap, true); + regcache_mark_dirty(wm5100->regmap); if (wm5100->pdata.ldo_ena) gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), From 68315801dbf3ab2001679fd2074c9dc5dcf87dfa Mon Sep 17 00:00:00 2001 From: James Chapman Date: Wed, 25 Jan 2012 02:39:05 +0000 Subject: [PATCH 116/380] l2tp: l2tp_ip - fix possible oops on packet receive When a packet is received on an L2TP IP socket (L2TPv3 IP link encapsulation), the l2tpip socket's backlog_rcv function calls xfrm4_policy_check(). This is not necessary, since it was called before the skb was added to the backlog. With CONFIG_NET_NS enabled, xfrm4_policy_check() will oops if skb->dev is null, so this trivial patch removes the call. This bug has always been present, but only when CONFIG_NET_NS is enabled does it cause problems. Most users are probably using UDP encapsulation for L2TP, hence the problem has only recently surfaced. EIP: 0060:[] EFLAGS: 00210246 CPU: 0 EIP is at l2tp_ip_recvmsg+0xd4/0x2a7 EAX: 00000001 EBX: d77b5180 ECX: 00000000 EDX: 00200246 ESI: 00000000 EDI: d63cbd30 EBP: d63cbd18 ESP: d63cbcf4 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Call Trace: [] sock_common_recvmsg+0x31/0x46 [] __sock_recvmsg_nosec+0x45/0x4d [] __sock_recvmsg+0x31/0x3b [] sock_recvmsg+0x96/0xab [] ? might_fault+0x47/0x81 [] ? might_fault+0x47/0x81 [] ? _copy_from_user+0x31/0x115 [] ? copy_from_user+0x8/0xa [] ? verify_iovec+0x3e/0x78 [] __sys_recvmsg+0x10a/0x1aa [] ? sock_recvmsg+0x0/0xab [] ? __lock_acquire+0xbdf/0xbee [] ? do_page_fault+0x193/0x375 [] ? fcheck_files+0x9b/0xca [] ? fget_light+0x2a/0x9c [] sys_recvmsg+0x2b/0x43 [] sys_socketcall+0x16d/0x1a5 [] ? trace_hardirqs_on_thunk+0xc/0x10 [] sysenter_do_call+0x12/0x38 Code: c6 05 8c ea a8 c1 01 e8 0c d4 d9 ff 85 f6 74 07 3e ff 86 80 00 00 00 b9 17 b6 2b c1 ba 01 00 00 00 b8 78 ed 48 c1 e8 23 f6 d9 ff 76 0c 68 28 e3 30 c1 68 2d 44 41 c1 e8 89 57 01 00 83 c4 0c Signed-off-by: James Chapman Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/l2tp/l2tp_ip.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index d21e7ebd91ca..55670ec3cd0f 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -393,11 +393,6 @@ static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb) { int rc; - if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) - goto drop; - - nf_reset(skb); - /* Charge it to the socket, dropping if the queue is full. */ rc = sock_queue_rcv_skb(sk, skb); if (rc < 0) From 2b05ad33e1e624e7f08b8676d270dc7725403b7e Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Wed, 25 Jan 2012 08:34:51 +0000 Subject: [PATCH 117/380] tcp: bind() fix autoselection to share ports The current code checks for conflicts when the application requests a specific port. If there is no conflict, then the request is granted. On the other hand, the port autoselection done by the kernel fails when all ports are bound even when there is a port with no conflict available. The fix changes port autoselection to check if there is a conflict and use it if not. Signed-off-by: Flavio Leitner Signed-off-by: Marcelo Ricardo Leitner Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 2e4e24476c4c..ecd19b5a7ee2 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -128,6 +128,11 @@ again: goto have_snum; } } + if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { + spin_unlock(&head->lock); + snum = rover; + goto have_snum; + } goto next; } break; From fddb7b5761f104f034a0e708ece756d9b2eb2cac Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Wed, 25 Jan 2012 08:34:52 +0000 Subject: [PATCH 118/380] tcp: bind() optimize port allocation Port autoselection finds a port and then drop the lock, then right after that, gets the hash bucket again and lock it. Fix it to go direct. Signed-off-by: Flavio Leitner Signed-off-by: Marcelo Ricardo Leitner Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index ecd19b5a7ee2..19d66cefd7d3 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -123,15 +123,13 @@ again: smallest_size = tb->num_owners; smallest_rover = rover; if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) { - spin_unlock(&head->lock); snum = smallest_rover; - goto have_snum; + goto tb_found; } } if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { - spin_unlock(&head->lock); snum = rover; - goto have_snum; + goto tb_found; } goto next; } From 8a093049c604ab32d94bcc5baa24f7939d5e3f7b Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 25 Jan 2012 10:31:45 +0100 Subject: [PATCH 119/380] regulator: Set apply_uV only when min and max voltages are defined apply_uV is errornously set when regulator is instantiated from device tree, even when it doesn't contain any voltage constraints. This commit fixes error: machine_constraints_voltage: CHARGER: failed to apply 0uV constraint for following regulator description in DTS: CHARGER { regulator-min-microamp = <100000>; regulator-max-microamp = <200000>; } Signed-off-by: Karol Lewandowski Signed-off-by: Kyungmin Park Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index f1651eb69648..679734d26a16 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -35,7 +35,7 @@ static void of_get_regulation_constraints(struct device_node *np, if (constraints->min_uV != constraints->max_uV) constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; /* Only one voltage? Then make sure it's set. */ - if (constraints->min_uV == constraints->max_uV) + if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) constraints->apply_uV = true; uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); From 0eaf9f52e94f756147dbfe1faf1f77a02378dbf9 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 23 Jan 2012 13:23:08 +0200 Subject: [PATCH 120/380] OMAPDSS: use sync versions of pm_runtime_put omapdss doesn't work properly on system suspend. The problem seems to be the fact that omapdss uses pm_runtime_put() functions when turning off the hardware, and when system suspend is in process only sync versions are allowed. Using non-sync versions normally and sync versions when suspending would need rather ugly hacks to convey the information of suspending/not-suspending to different functions. Optimally the driver wouldn't even need to care about this, and the PM layer would handle syncing when suspend is in process. This patch changes all omapdss's pm_runtime_put calls to pm_runtime_put_sync. This fixes the suspend problem, and probably the performance penalty of always using sync versions is negligible. Signed-off-by: Tomi Valkeinen Acked-by: Kevin Hilman --- drivers/video/omap2/dss/dispc.c | 2 +- drivers/video/omap2/dss/dsi.c | 2 +- drivers/video/omap2/dss/dss.c | 2 +- drivers/video/omap2/dss/hdmi.c | 2 +- drivers/video/omap2/dss/rfbi.c | 2 +- drivers/video/omap2/dss/venc.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a5ec7f37c185..e1626a1d5c45 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -401,7 +401,7 @@ void dispc_runtime_put(void) DSSDBG("dispc_runtime_put\n"); - r = pm_runtime_put(&dispc.pdev->dev); + r = pm_runtime_put_sync(&dispc.pdev->dev); WARN_ON(r < 0); } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 511ae2a7add8..04a89a7bbaf5 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1079,7 +1079,7 @@ void dsi_runtime_put(struct platform_device *dsidev) DSSDBG("dsi_runtime_put\n"); - r = pm_runtime_put(&dsi->pdev->dev); + r = pm_runtime_put_sync(&dsi->pdev->dev); WARN_ON(r < 0); } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 17033457ee89..77c2b5a32b5d 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -720,7 +720,7 @@ void dss_runtime_put(void) DSSDBG("dss_runtime_put\n"); - r = pm_runtime_put(&dss.pdev->dev); + r = pm_runtime_put_sync(&dss.pdev->dev); WARN_ON(r < 0); } diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index b4c270edb915..c39f9c3a92cf 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -176,7 +176,7 @@ static void hdmi_runtime_put(void) DSSDBG("hdmi_runtime_put\n"); - r = pm_runtime_put(&hdmi.pdev->dev); + r = pm_runtime_put_sync(&hdmi.pdev->dev); WARN_ON(r < 0); } diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 814bb9500dca..55f398014f33 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -140,7 +140,7 @@ static void rfbi_runtime_put(void) DSSDBG("rfbi_runtime_put\n"); - r = pm_runtime_put(&rfbi.pdev->dev); + r = pm_runtime_put_sync(&rfbi.pdev->dev); WARN_ON(r < 0); } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index b3e9f9091581..5c3d0f901510 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -401,7 +401,7 @@ static void venc_runtime_put(void) DSSDBG("venc_runtime_put\n"); - r = pm_runtime_put(&venc.pdev->dev); + r = pm_runtime_put_sync(&venc.pdev->dev); WARN_ON(r < 0); } From 575753e3bea3b67eef8e454fb87f719e3f7da599 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 17 Jan 2012 11:04:53 +0200 Subject: [PATCH 121/380] OMAP: 4430SDP/Panda: use gpio_free_array to free HDMI gpios Instead of freeing the GPIOs individually, use gpio_free_array(). Signed-off-by: Tomi Valkeinen Acked-by: Tony Lindgren --- arch/arm/mach-omap2/board-4430sdp.c | 3 +-- arch/arm/mach-omap2/board-omap4panda.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index e1fe304ce361..7bbe23ee3e35 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -614,8 +614,7 @@ static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev) static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev) { - gpio_free(HDMI_GPIO_LS_OE); - gpio_free(HDMI_GPIO_HPD); + gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios)); } static struct nokia_dsi_panel_data dsi1_panel = { diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 3e1c507fb01f..aeb9e88e0a2a 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -497,8 +497,7 @@ static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev) static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev) { - gpio_free(HDMI_GPIO_LS_OE); - gpio_free(HDMI_GPIO_HPD); + gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios)); } static struct omap_dss_device omap4_panda_hdmi_device = { From 3932a32fcf5393f8be70ac99dc718ad7ad0a415b Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 17 Jan 2012 10:49:38 +0200 Subject: [PATCH 122/380] OMAP: 4430SDP/Panda: rename HPD GPIO to CT_CP_HPD The GPIO 60 on 4430sdp and Panda is not HPD GPIO, as currently marked in the board files, but CT_CP_HPD, which is used to enable/disable HPD functionality. This patch renames the GPIO. Signed-off-by: Tomi Valkeinen Acked-by: Tony Lindgren --- arch/arm/mach-omap2/board-4430sdp.c | 4 ++-- arch/arm/mach-omap2/board-omap4panda.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 7bbe23ee3e35..02a4d5f3e8c8 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -52,7 +52,7 @@ #define ETH_KS8851_QUART 138 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO 184 #define OMAP4_SFH7741_ENABLE_GPIO 188 -#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ +#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */ #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ #define DISPLAY_SEL_GPIO 59 /* LCD2/PicoDLP switch */ #define DLP_POWER_ON_GPIO 40 @@ -596,7 +596,7 @@ static void __init omap_sfh7741prox_init(void) } static struct gpio sdp4430_hdmi_gpios[] = { - { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" }, + { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" }, { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, }; diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index aeb9e88e0a2a..844e285b40a3 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -51,7 +51,7 @@ #define GPIO_HUB_NRESET 62 #define GPIO_WIFI_PMENA 43 #define GPIO_WIFI_IRQ 53 -#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ +#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */ #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ /* wl127x BT, FM, GPS connectivity chip */ @@ -479,7 +479,7 @@ int __init omap4_panda_dvi_init(void) } static struct gpio panda_hdmi_gpios[] = { - { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" }, + { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" }, { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, }; From 7bb122d155f742fe2d79849090c825be7b4a247e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 17 Jan 2012 10:59:00 +0200 Subject: [PATCH 123/380] OMAPDSS: remove wrong HDMI HPD muxing "hdmi_hpd" pin is muxed to INPUT and PULLUP, but the pin is not currently used, and in the future when it is used, the pin is used as a GPIO and is board specific, not an OMAP4 wide thing. So remove the muxing for now. Signed-off-by: Tomi Valkeinen Acked-by: Tony Lindgren --- arch/arm/mach-omap2/display.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index ffd9bd983023..d6e65e29d83d 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -102,12 +102,8 @@ static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags) u32 reg; u16 control_i2c_1; - /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */ - omap_mux_init_signal("hdmi_hpd", - OMAP_PIN_INPUT_PULLUP); omap_mux_init_signal("hdmi_cec", OMAP_PIN_INPUT_PULLUP); - /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */ omap_mux_init_signal("hdmi_ddc_scl", OMAP_PIN_INPUT_PULLUP); omap_mux_init_signal("hdmi_ddc_sda", From 78a1ad8f12db70b8b0a4548b90704de08ee216ce Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 17 Jan 2012 11:02:36 +0200 Subject: [PATCH 124/380] OMAP: 4430SDP/Panda: setup HDMI GPIO muxes The HDMI GPIO pins LS_OE and CT_CP_HPD are not currently configured. This patch configures them as output pins. Signed-off-by: Tomi Valkeinen Acked-by: Tony Lindgren --- arch/arm/mach-omap2/board-4430sdp.c | 3 +++ arch/arm/mach-omap2/board-omap4panda.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 02a4d5f3e8c8..95766cdfc57f 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -821,6 +821,9 @@ static void omap_4430sdp_display_init(void) omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP); else omap_hdmi_init(0); + + omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT); } #ifdef CONFIG_OMAP_MUX diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 844e285b40a3..982397269360 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -538,6 +538,9 @@ void omap4_panda_display_init(void) omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP); else omap_hdmi_init(0); + + omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT); } static void __init omap4_panda_init(void) From aa74274b464d4aa24703963ac89a0ee942d5d267 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 17 Jan 2012 11:05:32 +0200 Subject: [PATCH 125/380] OMAP: 4430SDP/Panda: add HDMI HPD gpio Both Panda and 4430SDP use GPIO 63 as HDMI hot-plug-detect. Configure this GPIO in the board files. Signed-off-by: Tomi Valkeinen Acked-by: Tony Lindgren --- arch/arm/mach-omap2/board-4430sdp.c | 3 +++ arch/arm/mach-omap2/board-omap4panda.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 95766cdfc57f..cd6ec517a929 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -54,6 +54,7 @@ #define OMAP4_SFH7741_ENABLE_GPIO 188 #define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */ #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ +#define HDMI_GPIO_HPD 63 /* Hotplug detect */ #define DISPLAY_SEL_GPIO 59 /* LCD2/PicoDLP switch */ #define DLP_POWER_ON_GPIO 40 @@ -598,6 +599,7 @@ static void __init omap_sfh7741prox_init(void) static struct gpio sdp4430_hdmi_gpios[] = { { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" }, { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, + { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" }, }; static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev) @@ -824,6 +826,7 @@ static void omap_4430sdp_display_init(void) omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT); omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN); } #ifdef CONFIG_OMAP_MUX diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 982397269360..e1b196361f95 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -53,6 +53,7 @@ #define GPIO_WIFI_IRQ 53 #define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */ #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ +#define HDMI_GPIO_HPD 63 /* Hotplug detect */ /* wl127x BT, FM, GPS connectivity chip */ static int wl1271_gpios[] = {46, -1, -1}; @@ -481,6 +482,7 @@ int __init omap4_panda_dvi_init(void) static struct gpio panda_hdmi_gpios[] = { { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" }, { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, + { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" }, }; static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev) @@ -541,6 +543,7 @@ void omap4_panda_display_init(void) omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT); omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN); } static void __init omap4_panda_init(void) From c49d005b6cc8491fad5b24f82805be2d6bcbd3dd Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 17 Jan 2012 11:09:57 +0200 Subject: [PATCH 126/380] OMAPDSS: HDMI: PHY burnout fix A hardware bug in the OMAP4 HDMI PHY causes physical damage to the board if the HDMI PHY is kept powered on when the cable is not connected. This patch solves the problem by adding hot-plug-detection into the HDMI IP driver. This is not a real HPD support in the sense that nobody else than the IP driver gets to know about the HPD events, but is only meant to fix the HW bug. The strategy is simple: If the display device is turned off by the user, the PHY power is set to OFF. When the display device is turned on by the user, the PHY power is set either to LDOON or TXON, depending on whether the HDMI cable is connected. The reason to avoid PHY OFF when the display device is on, but the cable is disconnected, is that when the PHY is turned OFF, the HDMI IP is not "ticking" and thus the DISPC does not receive pixel clock from the HDMI IP. This would, for example, prevent any VSYNCs from happening, and would thus affect the users of omapdss. By using LDOON when the cable is disconnected we'll avoid the HW bug, but keep the HDMI working as usual from the user's point of view. Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/board-4430sdp.c | 5 ++ arch/arm/mach-omap2/board-omap4panda.c | 5 ++ drivers/video/omap2/dss/hdmi.c | 3 + drivers/video/omap2/dss/ti_hdmi.h | 4 ++ drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 68 +++++++++++++++++++++-- include/video/omapdss.h | 5 ++ 6 files changed, 86 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index cd6ec517a929..0ce758edaad2 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -732,6 +732,10 @@ static void sdp4430_lcd_init(void) pr_err("%s: Could not get lcd2_reset_gpio\n", __func__); } +static struct omap_dss_hdmi_data sdp4430_hdmi_data = { + .hpd_gpio = HDMI_GPIO_HPD, +}; + static struct omap_dss_device sdp4430_hdmi_device = { .name = "hdmi", .driver_name = "hdmi_panel", @@ -739,6 +743,7 @@ static struct omap_dss_device sdp4430_hdmi_device = { .platform_enable = sdp4430_panel_enable_hdmi, .platform_disable = sdp4430_panel_disable_hdmi, .channel = OMAP_DSS_CHANNEL_DIGIT, + .data = &sdp4430_hdmi_data, }; static struct picodlp_panel_data sdp4430_picodlp_pdata = { diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index e1b196361f95..370c4b428888 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -502,6 +502,10 @@ static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev) gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios)); } +static struct omap_dss_hdmi_data omap4_panda_hdmi_data = { + .hpd_gpio = HDMI_GPIO_HPD, +}; + static struct omap_dss_device omap4_panda_hdmi_device = { .name = "hdmi", .driver_name = "hdmi_panel", @@ -509,6 +513,7 @@ static struct omap_dss_device omap4_panda_hdmi_device = { .platform_enable = omap4_panda_panel_enable_hdmi, .platform_disable = omap4_panda_panel_disable_hdmi, .channel = OMAP_DSS_CHANNEL_DIGIT, + .data = &omap4_panda_hdmi_data, }; static struct omap_dss_device *omap4_panda_dss_devices[] = { diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index c39f9c3a92cf..d7aa3b056529 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -497,6 +497,7 @@ bool omapdss_hdmi_detect(void) int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) { + struct omap_dss_hdmi_data *priv = dssdev->data; int r = 0; DSSDBG("ENTER hdmi_display_enable\n"); @@ -509,6 +510,8 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) goto err0; } + hdmi.ip_data.hpd_gpio = priv->hpd_gpio; + r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h index 7503f7f619a7..50dadba5070a 100644 --- a/drivers/video/omap2/dss/ti_hdmi.h +++ b/drivers/video/omap2/dss/ti_hdmi.h @@ -126,6 +126,10 @@ struct hdmi_ip_data { const struct ti_hdmi_ip_ops *ops; struct hdmi_config cfg; struct hdmi_pll_info pll_data; + + /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */ + int hpd_gpio; + bool phy_tx_enabled; }; int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index 9af81f18f163..2d72334ca3da 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "ti_hdmi_4xxx_ip.h" #include "dss.h" @@ -223,6 +224,49 @@ void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data) hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); } +static int hdmi_check_hpd_state(struct hdmi_ip_data *ip_data) +{ + unsigned long flags; + bool hpd; + int r; + /* this should be in ti_hdmi_4xxx_ip private data */ + static DEFINE_SPINLOCK(phy_tx_lock); + + spin_lock_irqsave(&phy_tx_lock, flags); + + hpd = gpio_get_value(ip_data->hpd_gpio); + + if (hpd == ip_data->phy_tx_enabled) { + spin_unlock_irqrestore(&phy_tx_lock, flags); + return 0; + } + + if (hpd) + r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); + else + r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); + + if (r) { + DSSERR("Failed to %s PHY TX power\n", + hpd ? "enable" : "disable"); + goto err; + } + + ip_data->phy_tx_enabled = hpd; +err: + spin_unlock_irqrestore(&phy_tx_lock, flags); + return r; +} + +static irqreturn_t hpd_irq_handler(int irq, void *data) +{ + struct hdmi_ip_data *ip_data = data; + + hdmi_check_hpd_state(ip_data); + + return IRQ_HANDLED; +} + int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data) { u16 r = 0; @@ -232,10 +276,6 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data) if (r) return r; - r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); - if (r) - return r; - /* * Read address 0 in order to get the SCP reset done completed * Dummy access performed to make sure reset is done @@ -257,12 +297,32 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data) /* Write to phy address 3 to change the polarity control */ REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); + r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio), + NULL, hpd_irq_handler, + IRQF_DISABLED | IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, "hpd", ip_data); + if (r) { + DSSERR("HPD IRQ request failed\n"); + hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); + return r; + } + + r = hdmi_check_hpd_state(ip_data); + if (r) { + free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data); + hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); + return r; + } + return 0; } void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data) { + free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data); + hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); + ip_data->phy_tx_enabled = false; } static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data) diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 062b3b24ff10..483f67caa7ad 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -590,6 +590,11 @@ struct omap_dss_device { int (*get_backlight)(struct omap_dss_device *dssdev); }; +struct omap_dss_hdmi_data +{ + int hpd_gpio; +}; + struct omap_dss_driver { struct device_driver driver; From de849eecd0addaa6bf60f2f7be36b30abf9ff2ae Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 20 Jan 2012 08:17:33 -0800 Subject: [PATCH 127/380] pinctrl: fix some pinmux typos Fix some pinmux typos so implementing pinmux drivers is a bit easier. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 2 +- drivers/pinctrl/pinmux.c | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 5324d3199f34..150fd3833d0b 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -1024,7 +1024,7 @@ it, disables and releases it, and muxes it in on the pins defined by group B: foo_switch() { - struct pinmux pmx; + struct pinmux *pmx; /* Enable on position A */ pmx = pinmux_get(&device, "spi0-pos-A"); diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 0b22037965b9..f4f8c7e4b1c8 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -53,11 +53,6 @@ struct pinmux_group { * @dev: the device using this pinmux * @usecount: the number of active users of this mux setting, used to keep * track of nested use cases - * @pins: an array of discrete physical pins used in this mapping, taken - * from the global pin enumeration space (copied from pinmux map) - * @num_pins: the number of pins in this mapping array, i.e. the number of - * elements in .pins so we can iterate over that array (copied from - * pinmux map) * @pctldev: pin control device handling this pinmux * @func_selector: the function selector for the pinmux device handling * this pinmux @@ -409,7 +404,7 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, } /** - * acquire_pins() - acquire all the pins for a certain funcion on a pinmux + * acquire_pins() - acquire all the pins for a certain function on a pinmux * @pctldev: the device to take the pins on * @func_selector: the function selector to acquire the pins for * @group_selector: the group selector containing the pins to acquire @@ -455,7 +450,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev, /** * release_pins() - release pins taken by earlier acquirement - * @pctldev: the device to free the pinx on + * @pctldev: the device to free the pins on * @group_selector: the group selector containing the pins to free */ static void release_pins(struct pinctrl_dev *pctldev, From 9e2551e10b5c7ba550849bd9ed519e498cc30e68 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 20 Jan 2012 07:43:53 -0800 Subject: [PATCH 128/380] pinctrl: fix pinmux_hog_maps when ctrl_dev_name is not set The ctrl_dev_name is optional for struct pinmux_map assuming that ctrl_dev is set. Without this patch we can get: Unable to handle kernel NULL pointer dereference at virtual address 00000000 ... (pinmux_hog_maps+0xa4/0x20c) (pinctrl_register+0x2a4/0x378) ... Fix this by adding adding a test for map->ctrl_dev. Additionally move the test for map->ctrl_dev earlier to optimize out the loop a bit. Signed-off-by: Tony Lindgren Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index f4f8c7e4b1c8..3ffa9324ed82 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -978,9 +978,12 @@ int pinmux_hog_maps(struct pinctrl_dev *pctldev) for (i = 0; i < pinmux_maps_num; i++) { struct pinmux_map const *map = &pinmux_maps[i]; - if (((map->ctrl_dev == dev) || - !strcmp(map->ctrl_dev_name, devname)) && - map->hog_on_boot) { + if (!map->hog_on_boot) + continue; + + if ((map->ctrl_dev == dev) || + (map->ctrl_dev_name && + !strcmp(map->ctrl_dev_name, devname))) { /* OK time to hog! */ ret = pinmux_hog_map(pctldev, map); if (ret) From b9130b776ee481acbc27a7e56d98df75680de369 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 24 Jan 2012 16:28:08 -0800 Subject: [PATCH 129/380] pinctrl: add checks for empty function names This is needed as otherwise we can get the following when dealing with buggy data in a pinmux driver for pinmux_search_function: Unable to handle kernel NULL pointer dereference at virtual address 00000000 ... PC is at strcmp+0xc/0x34 LR is at pinmux_get+0x350/0x8f4 ... As we need pctldev initialized to call ops->list_functions, let's initialize it before check_ops calls and pass the pctldev to the check_ops functions. Do this for both pinmux and pinconf check_ops functions. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 40 +++++++++++++++++++-------------------- drivers/pinctrl/pinconf.c | 4 +++- drivers/pinctrl/pinconf.h | 4 ++-- drivers/pinctrl/pinmux.c | 17 ++++++++++++++++- drivers/pinctrl/pinmux.h | 4 ++-- 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index d9d35fcbfc6b..8fe15cf15ac8 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -583,26 +583,6 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, if (pctldesc->name == NULL) return NULL; - /* If we're implementing pinmuxing, check the ops for sanity */ - if (pctldesc->pmxops) { - ret = pinmux_check_ops(pctldesc->pmxops); - if (ret) { - pr_err("%s pinmux ops lacks necessary functions\n", - pctldesc->name); - return NULL; - } - } - - /* If we're implementing pinconfig, check the ops for sanity */ - if (pctldesc->confops) { - ret = pinconf_check_ops(pctldesc->confops); - if (ret) { - pr_err("%s pin config ops lacks necessary functions\n", - pctldesc->name); - return NULL; - } - } - pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL); if (pctldev == NULL) return NULL; @@ -617,6 +597,26 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, mutex_init(&pctldev->gpio_ranges_lock); pctldev->dev = dev; + /* If we're implementing pinmuxing, check the ops for sanity */ + if (pctldesc->pmxops) { + ret = pinmux_check_ops(pctldev); + if (ret) { + pr_err("%s pinmux ops lacks necessary functions\n", + pctldesc->name); + goto out_err; + } + } + + /* If we're implementing pinconfig, check the ops for sanity */ + if (pctldesc->confops) { + ret = pinconf_check_ops(pctldev); + if (ret) { + pr_err("%s pin config ops lacks necessary functions\n", + pctldesc->name); + goto out_err; + } + } + /* Register all the pins */ pr_debug("try to register %d pins on %s...\n", pctldesc->npins, pctldesc->name); diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 1892a3794b99..9fb75456824c 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -205,8 +205,10 @@ int pin_config_group_set(const char *dev_name, const char *pin_group, } EXPORT_SYMBOL(pin_config_group_set); -int pinconf_check_ops(const struct pinconf_ops *ops) +int pinconf_check_ops(struct pinctrl_dev *pctldev) { + const struct pinconf_ops *ops = pctldev->desc->confops; + /* We must be able to read out pin status */ if (!ops->pin_config_get && !ops->pin_config_group_get) return -EINVAL; diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h index e7dc6165032a..006b77fa737e 100644 --- a/drivers/pinctrl/pinconf.h +++ b/drivers/pinctrl/pinconf.h @@ -13,7 +13,7 @@ #ifdef CONFIG_PINCONF -int pinconf_check_ops(const struct pinconf_ops *ops); +int pinconf_check_ops(struct pinctrl_dev *pctldev); void pinconf_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev); int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, @@ -23,7 +23,7 @@ int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, #else -static inline int pinconf_check_ops(const struct pinconf_ops *ops) +static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) { return 0; } diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 3ffa9324ed82..7c3193f7a044 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -889,8 +889,11 @@ void pinmux_disable(struct pinmux *pmx) } EXPORT_SYMBOL_GPL(pinmux_disable); -int pinmux_check_ops(const struct pinmux_ops *ops) +int pinmux_check_ops(struct pinctrl_dev *pctldev) { + const struct pinmux_ops *ops = pctldev->desc->pmxops; + unsigned selector = 0; + /* Check that we implement required operations */ if (!ops->list_functions || !ops->get_function_name || @@ -899,6 +902,18 @@ int pinmux_check_ops(const struct pinmux_ops *ops) !ops->disable) return -EINVAL; + /* Check that all functions registered have names */ + while (ops->list_functions(pctldev, selector) >= 0) { + const char *fname = ops->get_function_name(pctldev, + selector); + if (!fname) { + pr_err("pinmux ops has no name for function%u\n", + selector); + return -EINVAL; + } + selector++; + } + return 0; } diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h index 844500b3331b..97f52223fbc2 100644 --- a/drivers/pinctrl/pinmux.h +++ b/drivers/pinctrl/pinmux.h @@ -12,7 +12,7 @@ */ #ifdef CONFIG_PINMUX -int pinmux_check_ops(const struct pinmux_ops *ops); +int pinmux_check_ops(struct pinctrl_dev *pctldev); void pinmux_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev); void pinmux_init_debugfs(struct dentry *subsys_root); @@ -21,7 +21,7 @@ void pinmux_unhog_maps(struct pinctrl_dev *pctldev); #else -static inline int pinmux_check_ops(const struct pinmux_ops *ops) +static inline int pinmux_check_ops(struct pinctrl_dev *pctldev) { return 0; } From 073862ba5d249c20bd5c49fc6d904ff0e1f6a672 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 26 Jan 2012 00:41:38 +0000 Subject: [PATCH 130/380] netns: fix net_alloc_generic() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a new net namespace is created, we should attach to it a "struct net_generic" with enough slots (even empty), or we can hit the following BUG_ON() : [ 200.752016] kernel BUG at include/net/netns/generic.h:40! ... [ 200.752016] [] ? get_cfcnfg+0x3a/0x180 [ 200.752016] [] ? lockdep_rtnl_is_held+0x10/0x20 [ 200.752016] [] caif_device_notify+0x2e/0x530 [ 200.752016] [] notifier_call_chain+0x67/0x110 [ 200.752016] [] raw_notifier_call_chain+0x11/0x20 [ 200.752016] [] call_netdevice_notifiers+0x32/0x60 [ 200.752016] [] register_netdevice+0x196/0x300 [ 200.752016] [] register_netdev+0x19/0x30 [ 200.752016] [] loopback_net_init+0x4a/0xa0 [ 200.752016] [] ops_init+0x42/0x180 [ 200.752016] [] setup_net+0x6b/0x100 [ 200.752016] [] copy_net_ns+0x86/0x110 [ 200.752016] [] create_new_namespaces+0xd9/0x190 net_alloc_generic() should take into account the maximum index into the ptr array, as a subsystem might use net_generic() anytime. This also reduces number of reallocations in net_assign_generic() Reported-by: Sasha Levin Tested-by: Sasha Levin Signed-off-by: Eric Dumazet Cc: Sjur Brændeland Cc: Eric W. Biederman Cc: Pavel Emelyanov Signed-off-by: David S. Miller --- net/core/net_namespace.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index aefcd7acbffa..0e950fda9a0a 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -30,6 +30,20 @@ EXPORT_SYMBOL(init_net); #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ +static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS; + +static struct net_generic *net_alloc_generic(void) +{ + struct net_generic *ng; + size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]); + + ng = kzalloc(generic_size, GFP_KERNEL); + if (ng) + ng->len = max_gen_ptrs; + + return ng; +} + static int net_assign_generic(struct net *net, int id, void *data) { struct net_generic *ng, *old_ng; @@ -43,8 +57,7 @@ static int net_assign_generic(struct net *net, int id, void *data) if (old_ng->len >= id) goto assign; - ng = kzalloc(sizeof(struct net_generic) + - id * sizeof(void *), GFP_KERNEL); + ng = net_alloc_generic(); if (ng == NULL) return -ENOMEM; @@ -59,7 +72,6 @@ static int net_assign_generic(struct net *net, int id, void *data) * the old copy for kfree after a grace period. */ - ng->len = id; memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); rcu_assign_pointer(net->gen, ng); @@ -161,18 +173,6 @@ out_undo: goto out; } -static struct net_generic *net_alloc_generic(void) -{ - struct net_generic *ng; - size_t generic_size = sizeof(struct net_generic) + - INITIAL_NET_GEN_PTRS * sizeof(void *); - - ng = kzalloc(generic_size, GFP_KERNEL); - if (ng) - ng->len = INITIAL_NET_GEN_PTRS; - - return ng; -} #ifdef CONFIG_NET_NS static struct kmem_cache *net_cachep; @@ -483,6 +483,7 @@ again: } return error; } + max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id); } error = __register_pernet_operations(list, ops); if (error) { From 4ca9b72b71f10147bd21969c1805f5b2c4ca7b7b Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 25 Jan 2012 11:50:51 +0100 Subject: [PATCH 131/380] sched: Fix rq->nr_uninterruptible update race KOSAKI Motohiro noticed the following race: > CPU0 CPU1 > -------------------------------------------------------- > deactivate_task() > task->state = TASK_UNINTERRUPTIBLE; > activate_task() > rq->nr_uninterruptible--; > > schedule() > deactivate_task() > rq->nr_uninterruptible++; > Kosaki-San's scenario is possible when CPU0 runs __sched_setscheduler() against CPU1's current @task. __sched_setscheduler() does a dequeue/enqueue in order to move the task to its new queue (position) to reflect the newly provided scheduling parameters. However it should be completely invariant to nr_uninterruptible accounting, sched_setscheduler() doesn't affect readyness to run, merely policy on when to run. So convert the inappropriate activate/deactivate_task usage to enqueue/dequeue_task, which avoids the nr_uninterruptible accounting. Also convert the two other sites: __migrate_task() and normalize_task() that still use activate/deactivate_task. These sites aren't really a problem since __migrate_task() will only be called on non-running task (and therefore are immume to the described problem) and normalize_task() isn't ever used on regular systems. Also remove the comments from activate/deactivate_task since they're misleading at best. Reported-by: KOSAKI Motohiro Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1327486224.2614.45.camel@laptop Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index df00cb09263e..e067df1fd01a 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -723,9 +723,6 @@ static void dequeue_task(struct rq *rq, struct task_struct *p, int flags) p->sched_class->dequeue_task(rq, p, flags); } -/* - * activate_task - move a task to the runqueue. - */ void activate_task(struct rq *rq, struct task_struct *p, int flags) { if (task_contributes_to_load(p)) @@ -734,9 +731,6 @@ void activate_task(struct rq *rq, struct task_struct *p, int flags) enqueue_task(rq, p, flags); } -/* - * deactivate_task - remove a task from the runqueue. - */ void deactivate_task(struct rq *rq, struct task_struct *p, int flags) { if (task_contributes_to_load(p)) @@ -4134,7 +4128,7 @@ recheck: on_rq = p->on_rq; running = task_current(rq, p); if (on_rq) - deactivate_task(rq, p, 0); + dequeue_task(rq, p, 0); if (running) p->sched_class->put_prev_task(rq, p); @@ -4147,7 +4141,7 @@ recheck: if (running) p->sched_class->set_curr_task(rq); if (on_rq) - activate_task(rq, p, 0); + enqueue_task(rq, p, 0); check_class_changed(rq, p, prev_class, oldprio); task_rq_unlock(rq, p, &flags); @@ -4998,9 +4992,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) * placed properly. */ if (p->on_rq) { - deactivate_task(rq_src, p, 0); + dequeue_task(rq_src, p, 0); set_task_cpu(p, dest_cpu); - activate_task(rq_dest, p, 0); + enqueue_task(rq_dest, p, 0); check_preempt_curr(rq_dest, p, 0); } done: @@ -7032,10 +7026,10 @@ static void normalize_task(struct rq *rq, struct task_struct *p) on_rq = p->on_rq; if (on_rq) - deactivate_task(rq, p, 0); + dequeue_task(rq, p, 0); __setscheduler(rq, p, SCHED_NORMAL, 0); if (on_rq) { - activate_task(rq, p, 0); + enqueue_task(rq, p, 0); resched_task(rq->curr); } From db7e527da41560f597ccdc4417cefa6b7657c0c0 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 11 Jan 2012 08:58:16 +0100 Subject: [PATCH 132/380] sched/s390: Fix compile error in sched/core.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 029632fbb7b7c9d85063cc9eb470de6c54873df3 ("sched: Make separate sched*.c translation units") removed the include of asm/mutex.h from sched.c. This breaks the combination of: CONFIG_MUTEX_SPIN_ON_OWNER=yes CONFIG_HAVE_ARCH_MUTEX_CPU_RELAX=yes like s390 without mutex debugging: CC kernel/sched/core.o kernel/sched/core.c: In function ‘mutex_spin_on_owner’: kernel/sched/core.c:3287: error: implicit declaration of function ‘arch_mutex_cpu_relax’ Lets re-add the include to kernel/sched/core.c Signed-off-by: Christian Borntraeger Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1326268696-30904-1-git-send-email-borntraeger@de.ibm.com Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index e067df1fd01a..5255c9d2e053 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -74,6 +74,7 @@ #include #include +#include #ifdef CONFIG_PARAVIRT #include #endif From 71325960d16cd68ea0e22a8da15b2495b0f363f7 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Thu, 19 Jan 2012 18:28:57 -0800 Subject: [PATCH 133/380] sched/nohz: Fix nohz cpu idle load balancing state with cpu hotplug With the recent nohz scheduler changes, rq's nohz flag 'NOHZ_TICK_STOPPED' and its associated state doesn't get cleared immediately after the cpu exits idle. This gets cleared as part of the next tick seen on that cpu. For the cpu offline support, we need to clear this state manually. Fix it by registering a cpu notifier, which clears the nohz idle load balance state for this rq explicitly during the CPU_DYING notification. There won't be any nohz updates for that cpu, after the CPU_DYING notification. But lets be extra paranoid and skip updating the nohz state in the select_nohz_load_balancer() if the cpu is not in active state anymore. Reported-by: Srivatsa S. Bhat Reviewed-and-tested-by: Srivatsa S. Bhat Tested-by: Sergey Senozhatsky Signed-off-by: Suresh Siddha Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1327026538.16150.40.camel@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 84adb2d66cbd..7c6414fc669d 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4866,6 +4866,15 @@ static void nohz_balancer_kick(int cpu) return; } +static inline void clear_nohz_tick_stopped(int cpu) +{ + if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { + cpumask_clear_cpu(cpu, nohz.idle_cpus_mask); + atomic_dec(&nohz.nr_cpus); + clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); + } +} + static inline void set_cpu_sd_state_busy(void) { struct sched_domain *sd; @@ -4904,6 +4913,12 @@ void select_nohz_load_balancer(int stop_tick) { int cpu = smp_processor_id(); + /* + * If this cpu is going down, then nothing needs to be done. + */ + if (!cpu_active(cpu)) + return; + if (stop_tick) { if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu))) return; @@ -4914,6 +4929,18 @@ void select_nohz_load_balancer(int stop_tick) } return; } + +static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_DYING: + clear_nohz_tick_stopped(smp_processor_id()); + return NOTIFY_OK; + default: + return NOTIFY_DONE; + } +} #endif static DEFINE_SPINLOCK(balancing); @@ -5070,11 +5097,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu) * busy tick after returning from idle, we will update the busy stats. */ set_cpu_sd_state_busy(); - if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { - clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); - cpumask_clear_cpu(cpu, nohz.idle_cpus_mask); - atomic_dec(&nohz.nr_cpus); - } + clear_nohz_tick_stopped(cpu); /* * None are in tickless mode and hence no need for NOHZ idle load @@ -5590,6 +5613,7 @@ __init void init_sched_fair_class(void) #ifdef CONFIG_NO_HZ zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT); + cpu_notifier(sched_ilb_notifier, 0); #endif #endif /* SMP */ From 40206dd98f066d596d4280558fc5f798165861c7 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Thu, 26 Jan 2012 07:23:23 +0000 Subject: [PATCH 134/380] xen-netfront: correct MAX_TX_TARGET calculation. Signed-off-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index fa679057630f..698b905058dd 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -68,7 +68,7 @@ struct netfront_cb { #define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) #define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) -#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) +#define TX_MAX_TARGET min_t(int, NET_TX_RING_SIZE, 256) struct netfront_stats { u64 rx_packets; From 77231abe55433aa17eca712718745275853fa66d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 20 Jan 2012 12:19:43 +0000 Subject: [PATCH 135/380] ASoC: wm_hubs: Enable line out VMID buffer for single ended line outputs For optimal performance the single ended line outputs require that the line output VMID buffer be enabled. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm_hubs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 2a61094075f8..9ccc416d8cbc 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -613,6 +613,8 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"), SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0), + SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, in1l_pga, ARRAY_SIZE(in1l_pga)), SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0, @@ -834,9 +836,11 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = { }; static const struct snd_soc_dapm_route lineout1_se_routes[] = { + { "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" }, { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" }, + { "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" }, { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, @@ -853,9 +857,11 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = { }; static const struct snd_soc_dapm_route lineout2_se_routes[] = { + { "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" }, { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" }, + { "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" }, { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" }, { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, From af681cad3f79ad8f7bd6cb170b70990aeef74233 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 26 Jan 2012 11:14:42 -0800 Subject: [PATCH 136/380] Revert "tty: serial: OMAP: transmit FIFO threshold interrupts don't wake the chip" This reverts commit 43cf7c0bebf50d0b68aa42ae6d24cf08e3f24823 as Paul wants to redo it. Cc: Paul Walmsley Cc: Tomi Valkeinen Cc: Govindraj Raja Cc: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- arch/arm/plat-omap/include/plat/omap-serial.h | 1 - drivers/tty/serial/omap-serial.c | 51 +------------------ 2 files changed, 1 insertion(+), 51 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 12a64eb8c624..9ff444469f3d 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -131,7 +131,6 @@ struct uart_omap_port { u32 context_loss_cnt; u32 errata; u8 wakeups_enabled; - u8 max_tx_count; struct pm_qos_request pm_qos_request; u32 latency; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index e00ac05cfdb4..ca54f038ab45 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -88,49 +88,6 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up) serial_out(up, UART_FCR, 0); } -/** - * serial_omap_block_cpu_low_power_state - prevent MPU pwrdm from leaving ON - * @up: struct uart_omap_port * - * - * Prevent the MPU powerdomain from entering a power state lower than - * ON. (It should be sufficient to prevent it from entering INACTIVE, - * but there is presently no easy way to do this.) This works around - * a suspected silicon bug in the OMAP UART IP blocks. The UARTs should - * wake the PRCM when the transmit FIFO threshold interrupt is raised, but - * they do not. See also serial_omap_allow_cpu_low_power_state(). No - * return value. - */ -static void serial_omap_block_cpu_low_power_state(struct uart_omap_port *up) -{ -#ifdef CONFIG_CPU_IDLE - up->latency = 1; - schedule_work(&up->qos_work); -#else - up->max_tx_count = 1; -#endif -} - -/** - * serial_omap_allow_cpu_low_power_state - remove power state restriction on MPU - * @up: struct uart_omap_port * - * - * Cancel the effects of serial_omap_block_cpu_low_power_state(). - * This should allow the MPU powerdomain to enter a power state lower - * than ON, assuming the rest of the kernel is not restricting it. - * This works around a suspected silicon bug in the OMAP UART IP - * blocks. The UARTs should wake the PRCM when the transmit FIFO - * threshold interrupt is raised, but they do not. No return value. - */ -static void serial_omap_allow_cpu_low_power_state(struct uart_omap_port *up) -{ -#ifdef CONFIG_CPU_IDLE - up->latency = up->calc_latency; - schedule_work(&up->qos_work); -#else - up->max_tx_count = up->port.fifosize / 4; -#endif -} - /* * serial_omap_get_divisor - calculate divisor value * @port: uart port info @@ -206,9 +163,6 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_IER, up->ier); } - if (!up->use_dma) - serial_omap_allow_cpu_low_power_state(up); - pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); } @@ -310,7 +264,7 @@ static void transmit_chars(struct uart_omap_port *up) serial_omap_stop_tx(&up->port); return; } - count = up->max_tx_count; + count = up->port.fifosize / 4; do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -343,7 +297,6 @@ static void serial_omap_start_tx(struct uart_port *port) if (!up->use_dma) { pm_runtime_get_sync(&up->pdev->dev); - serial_omap_block_cpu_low_power_state(up); serial_omap_enable_ier_thri(up); pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); @@ -1468,8 +1421,6 @@ static int serial_omap_probe(struct platform_device *pdev) up->port.fifosize = 64; up->port.ops = &serial_omap_pops; - up->max_tx_count = up->port.fifosize / 4; - if (pdev->dev.of_node) up->port.line = of_alias_get_id(pdev->dev.of_node, "serial"); else From 8a74e9ffd97dc9de063de8c02ae32db79dd60436 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 26 Jan 2012 11:15:18 -0800 Subject: [PATCH 137/380] Revert "tty: serial: OMAP: ensure FIFO levels are set correctly in non-DMA mode" This reverts commit 0a697b22252c9d7208b5fb3e9fbd124dd229f1d2 as Paul wants to rework it. Cc: Paul Walmsley Cc: Tomi Valkeinen Cc: Govindraj Raja Cc: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 37 +++++--------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index ca54f038ab45..1c2426931484 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -46,18 +46,6 @@ #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/ -/* SCR register bitmasks */ -#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) -#define OMAP_UART_SCR_TX_TRIG_GRANU1_MASK (1 << 6) - -/* FCR register bitmasks */ -#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6 -#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6) -#define OMAP_UART_FCR_TX_FIFO_TRIG_SHIFT 4 - -/* TLR register bitmasks */ -#define OMAP_UART_TLR_TX_FIFO_TRIG_DMA_SHIFT 0 - static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; /* Forward declaration of functions */ @@ -706,7 +694,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, unsigned char efr = 0; unsigned long flags = 0; unsigned int baud, quot; - u32 tlr; switch (termios->c_cflag & CSIZE) { case CS5: @@ -824,28 +811,14 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); /* FIFO ENABLE, DMA MODE */ - - up->scr |= OMAP_UART_SCR_TX_TRIG_GRANU1_MASK; - up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK; - - if (up->use_dma) { - tlr = 0; - } else { - up->scr &= ~OMAP_UART_SCR_TX_EMPTY; - - /* Set receive FIFO threshold to 1 */ - up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; - up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT); - - /* Set TX FIFO threshold to "63" (actually 1) */ - up->fcr |= (0x3 << OMAP_UART_FCR_TX_FIFO_TRIG_SHIFT); - tlr = (0xf << OMAP_UART_TLR_TX_FIFO_TRIG_DMA_SHIFT); - } - - serial_out(up, UART_TI752_TLR, tlr); serial_out(up, UART_FCR, up->fcr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + if (up->use_dma) { + serial_out(up, UART_TI752_TLR, 0); + up->scr |= (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8); + } + serial_out(up, UART_OMAP_SCR, up->scr); serial_out(up, UART_EFR, up->efr); From 523b82e3734908fc9eff5d48de46c83e76e51641 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 26 Jan 2012 17:45:39 +0000 Subject: [PATCH 138/380] serial: Kill off Moorestown code All production devices operate in the Oaktrail configuration with legacy PC elements present and an ACPI BIOS. Continue stripping out the Moorestown elements from the tree leaving Medfield. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 9 - drivers/tty/serial/Makefile | 1 - drivers/tty/serial/max3107-aava.c | 344 ------------------------------ 3 files changed, 354 deletions(-) delete mode 100644 drivers/tty/serial/max3107-aava.c diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 0bff23897509..2de99248dfae 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -264,15 +264,6 @@ config SERIAL_MAX3107 help MAX3107 chip support -config SERIAL_MAX3107_AAVA - tristate "MAX3107 AAVA platform support" - depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB - select SERIAL_CORE - help - Support for the MAX3107 chip configuration found on the AAVA - platform. Includes the extra initialisation and GPIO support - neded for this device. - config SERIAL_DZ bool "DECstation DZ serial driver" depends on MACH_DECSTATION && 32BIT diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index a6d1ac049965..fef32e10c851 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -29,7 +29,6 @@ obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX3107) += max3107.o -obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o diff --git a/drivers/tty/serial/max3107-aava.c b/drivers/tty/serial/max3107-aava.c deleted file mode 100644 index aae772a71de6..000000000000 --- a/drivers/tty/serial/max3107-aava.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * max3107.c - spi uart protocol driver for Maxim 3107 - * Based on max3100.c - * by Christian Pellegrin - * and max3110.c - * by Feng Tang - * - * Copyright (C) Aavamobile 2009 - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "max3107.h" - -/* GPIO direction to input function */ -static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[1]; /* Buffer for SPI transfer */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return -EINVAL; - } - - /* Read current GPIO configuration register */ - buf[0] = MAX3107_GPIOCFG_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { - dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n"); - return -EIO; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - - /* Set GPIO to input */ - buf[0] &= ~(0x0001 << offset); - - /* Write new GPIO configuration register value */ - buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, NULL, 2)) { - dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n"); - return -EIO; - } - return 0; -} - -/* GPIO direction to output function */ -static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[2]; /* Buffer for SPI transfers */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return -EINVAL; - } - - /* Read current GPIO configuration and data registers */ - buf[0] = MAX3107_GPIOCFG_REG; - buf[1] = MAX3107_GPIODATA_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { - dev_err(&s->spi->dev, "SPI transfer gpio failed\n"); - return -EIO; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - buf[1] &= MAX3107_SPI_RX_DATA_MASK; - - /* Set GPIO to output */ - buf[0] |= (0x0001 << offset); - /* Set value */ - if (value) - buf[1] |= (0x0001 << offset); - else - buf[1] &= ~(0x0001 << offset); - - /* Write new GPIO configuration and data register values */ - buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); - buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, NULL, 4)) { - dev_err(&s->spi->dev, - "SPI transfer for GPIO conf data w failed\n"); - return -EIO; - } - return 0; -} - -/* GPIO value query function */ -static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[1]; /* Buffer for SPI transfer */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return -EINVAL; - } - - /* Read current GPIO data register */ - buf[0] = MAX3107_GPIODATA_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { - dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n"); - return -EIO; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - - /* Return value */ - return buf[0] & (0x0001 << offset); -} - -/* GPIO value set function */ -static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[2]; /* Buffer for SPI transfers */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return; - } - - /* Read current GPIO configuration registers*/ - buf[0] = MAX3107_GPIODATA_REG; - buf[1] = MAX3107_GPIOCFG_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { - dev_err(&s->spi->dev, - "SPI transfer for GPIO data and config read failed\n"); - return; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - buf[1] &= MAX3107_SPI_RX_DATA_MASK; - - if (!(buf[1] & (0x0001 << offset))) { - /* Configured as input, can't set value */ - dev_warn(&s->spi->dev, - "Trying to set value for input GPIO\n"); - return; - } - - /* Set value */ - if (value) - buf[0] |= (0x0001 << offset); - else - buf[0] &= ~(0x0001 << offset); - - /* Write new GPIO data register value */ - buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, NULL, 2)) - dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n"); -} - -/* GPIO chip data */ -static struct gpio_chip max3107_gpio_chip = { - .owner = THIS_MODULE, - .direction_input = max3107_gpio_direction_in, - .direction_output = max3107_gpio_direction_out, - .get = max3107_gpio_get, - .set = max3107_gpio_set, - .can_sleep = 1, - .base = MAX3107_GPIO_BASE, - .ngpio = MAX3107_GPIO_COUNT, -}; - -/** - * max3107_aava_reset - reset on AAVA systems - * @spi: The SPI device we are probing - * - * Reset the device ready for probing. - */ - -static int max3107_aava_reset(struct spi_device *spi) -{ - /* Reset the chip */ - if (gpio_request(MAX3107_RESET_GPIO, "max3107")) { - pr_err("Requesting RESET GPIO failed\n"); - return -EIO; - } - if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) { - pr_err("Setting RESET GPIO to 0 failed\n"); - gpio_free(MAX3107_RESET_GPIO); - return -EIO; - } - msleep(MAX3107_RESET_DELAY); - if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) { - pr_err("Setting RESET GPIO to 1 failed\n"); - gpio_free(MAX3107_RESET_GPIO); - return -EIO; - } - gpio_free(MAX3107_RESET_GPIO); - msleep(MAX3107_WAKEUP_DELAY); - return 0; -} - -static int max3107_aava_configure(struct max3107_port *s) -{ - int retval; - - /* Initialize GPIO chip data */ - s->chip = max3107_gpio_chip; - s->chip.label = s->spi->modalias; - s->chip.dev = &s->spi->dev; - - /* Add GPIO chip */ - retval = gpiochip_add(&s->chip); - if (retval) { - dev_err(&s->spi->dev, "Adding GPIO chip failed\n"); - return retval; - } - - /* Temporary fix for EV2 boot problems, set modem reset to 0 */ - max3107_gpio_direction_out(&s->chip, 3, 0); - return 0; -} - -#if 0 -/* This will get enabled once we have the board stuff merged for this - specific case */ - -static const struct baud_table brg13_ext[] = { - { 300, MAX3107_BRG13_B300 }, - { 600, MAX3107_BRG13_B600 }, - { 1200, MAX3107_BRG13_B1200 }, - { 2400, MAX3107_BRG13_B2400 }, - { 4800, MAX3107_BRG13_B4800 }, - { 9600, MAX3107_BRG13_B9600 }, - { 19200, MAX3107_BRG13_B19200 }, - { 57600, MAX3107_BRG13_B57600 }, - { 115200, MAX3107_BRG13_B115200 }, - { 230400, MAX3107_BRG13_B230400 }, - { 460800, MAX3107_BRG13_B460800 }, - { 921600, MAX3107_BRG13_B921600 }, - { 0, 0 } -}; - -static void max3107_aava_init(struct max3107_port *s) -{ - /*override for AAVA SC specific*/ - if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) { - if (get_koski_build_id() <= KOSKI_EV2) - if (s->ext_clk) { - s->brg_cfg = MAX3107_BRG13_B9600; - s->baud_tbl = (struct baud_table *)brg13_ext; - } - } -} -#endif - -static int __devexit max3107_aava_remove(struct spi_device *spi) -{ - struct max3107_port *s = dev_get_drvdata(&spi->dev); - - /* Remove GPIO chip */ - if (gpiochip_remove(&s->chip)) - dev_warn(&spi->dev, "Removing GPIO chip failed\n"); - - /* Then do the default remove */ - return max3107_remove(spi); -} - -/* Platform data */ -static struct max3107_plat aava_plat_data = { - .loopback = 0, - .ext_clk = 1, -/* .init = max3107_aava_init, */ - .configure = max3107_aava_configure, - .hw_suspend = max3107_hw_susp, - .polled_mode = 0, - .poll_time = 0, -}; - - -static int __devinit max3107_probe_aava(struct spi_device *spi) -{ - int err = max3107_aava_reset(spi); - if (err < 0) - return err; - return max3107_probe(spi, &aava_plat_data); -} - -/* Spi driver data */ -static struct spi_driver max3107_driver = { - .driver = { - .name = "aava-max3107", - .owner = THIS_MODULE, - }, - .probe = max3107_probe_aava, - .remove = __devexit_p(max3107_aava_remove), - .suspend = max3107_suspend, - .resume = max3107_resume, -}; - -/* Driver init function */ -static int __init max3107_init(void) -{ - return spi_register_driver(&max3107_driver); -} - -/* Driver exit function */ -static void __exit max3107_exit(void) -{ - spi_unregister_driver(&max3107_driver); -} - -module_init(max3107_init); -module_exit(max3107_exit); - -MODULE_DESCRIPTION("MAX3107 driver"); -MODULE_AUTHOR("Aavamobile"); -MODULE_ALIAS("spi:aava-max3107"); -MODULE_LICENSE("GPL v2"); From 2353f806c97020d4c7709f15eebb49b591f7306d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 26 Jan 2012 17:41:34 +0000 Subject: [PATCH 139/380] USB: ftdi_sio: Add more identifiers 0x04d8, 0x000a: Hornby Elite Signed-off-by: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 104aff536b1e..ad654f8208ef 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -797,6 +797,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 09237ffe2f33..f994503df2dd 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -531,6 +531,12 @@ #define ADI_GNICE_PID 0xF000 #define ADI_GNICEPLUS_PID 0xF001 +/* + * Hornby Elite + */ +#define HORNBY_VID 0x04D8 +#define HORNBY_ELITE_PID 0x000A + /* * RATOC REX-USB60F */ From b3ef051db763b640d1ff724b616ffba940896b44 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 26 Jan 2012 12:29:42 +0100 Subject: [PATCH 140/380] USB: Realtek cr: fix autopm scheduling while atomic Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=784345 Reported-by: Francis Moreau Reported-and-tested-by: Christian D Reported-and-tested-by: Jimmy Dorff Reported-and-tested-by: collura@ieee.org Cc: stable@vger.kernel.org # 3.2+ Signed-off-by: Stanislaw Gruszka Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/realtek_cr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 1f62723ef1a8..d32f72061c09 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -789,7 +789,7 @@ static void rts51x_suspend_timer_fn(unsigned long data) rts51x_set_stat(chip, RTS51X_STAT_SS); /* ignore mass storage interface's children */ pm_suspend_ignore_children(&us->pusb_intf->dev, true); - usb_autopm_put_interface(us->pusb_intf); + usb_autopm_put_interface_async(us->pusb_intf); US_DEBUGP("%s: RTS51X_STAT_SS 01," "intf->pm_usage_cnt:%d, power.usage:%d\n", __func__, From a0701f04846eee9976e6b3eafca09f2a9d2744ef Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 25 Jan 2012 13:52:12 -0800 Subject: [PATCH 141/380] uwb & wusb: fix kconfig error Fix UWB/WUSB kconfig error by changing 'select' to 'depends on'. drivers/usb/wusbcore/Kconfig:4:error: recursive dependency detected! drivers/usb/wusbcore/Kconfig:4: symbol USB_WUSB is selected by USB_HWA_HCD drivers/usb/host/Kconfig:559: symbol USB_HWA_HCD depends on UWB drivers/uwb/Kconfig:5: symbol UWB is selected by USB_WUSB Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig index 0ead8826ec79..f29fdd7f6d75 100644 --- a/drivers/usb/wusbcore/Kconfig +++ b/drivers/usb/wusbcore/Kconfig @@ -6,7 +6,7 @@ config USB_WUSB depends on EXPERIMENTAL depends on USB depends on PCI - select UWB + depends on UWB select CRYPTO select CRYPTO_BLKCIPHER select CRYPTO_CBC From b1375d64c539c5b76794be759b62d3f178e67c32 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 26 Jan 2012 15:01:11 -0500 Subject: [PATCH 142/380] Btrfs: fix uninit warning in backref.c Added initialization with the declaration of ret. It isn't set later on the switch-default branch (which should never be taken). Signed-off-by: Jan Schmidt Signed-off-by: Chris Mason --- fs/btrfs/backref.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index b9a843226de8..633c701a287d 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -297,7 +297,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, struct btrfs_delayed_extent_op *extent_op = head->extent_op; struct rb_node *n = &head->node.rb_node; int sgn; - int ret; + int ret = 0; if (extent_op && extent_op->update_key) btrfs_disk_key_to_cpu(info_key, &extent_op->key); @@ -392,7 +392,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, struct btrfs_key *info_key, int *info_level, struct list_head *prefs) { - int ret; + int ret = 0; int slot; struct extent_buffer *leaf; struct btrfs_key key; From 357b9784b79924a31ccded5d9a0c688f48cc28f2 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 26 Jan 2012 15:01:11 -0500 Subject: [PATCH 143/380] Btrfs: make sure a bitmap has enough bytes We have only been checking for min_bytes available in bitmap entries, but we won't successfully setup a bitmap cluster unless it has at least bytes in the bitmap, so in the common case min_bytes is 4k and we want something like 2MB, so if there are a bunch of bitmap entries with less than 2mb's in them, we'll search all them anyway, which is suboptimal. Fix this check. Thanks, Signed-off-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index efe20032e4a1..6e7406932341 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2475,7 +2475,7 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, } list_for_each_entry(entry, bitmaps, list) { - if (entry->bytes < min_bytes) + if (entry->bytes < bytes) continue; ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset, bytes, cont1_bytes, min_bytes); From 6dd70ce4eb7429c2ba6dd9fa46f78a0a2a254038 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 26 Jan 2012 15:01:11 -0500 Subject: [PATCH 144/380] btrfs: Fix busyloops in transaction waiting code wait_log_commit() and wait_for_writer() were using slightly different conditions for deciding whether they should call schedule() and whether they should continue in the wait loop. Thus it could happen that we busylooped when the first condition was not true while the second one was. That is burning CPU cycles needlessly and is deadly on UP machines... Signed-off-by: Jan Kara Signed-off-by: Chris Mason --- fs/btrfs/tree-log.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index cb877e0886a7..966cc74f5d6c 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1957,7 +1957,8 @@ static int wait_log_commit(struct btrfs_trans_handle *trans, finish_wait(&root->log_commit_wait[index], &wait); mutex_lock(&root->log_mutex); - } while (root->log_transid < transid + 2 && + } while (root->fs_info->last_trans_log_full_commit != + trans->transid && root->log_transid < transid + 2 && atomic_read(&root->log_commit[index])); return 0; } @@ -1966,7 +1967,8 @@ static int wait_for_writer(struct btrfs_trans_handle *trans, struct btrfs_root *root) { DEFINE_WAIT(wait); - while (atomic_read(&root->log_writers)) { + while (root->fs_info->last_trans_log_full_commit != + trans->transid && atomic_read(&root->log_writers)) { prepare_to_wait(&root->log_writer_wait, &wait, TASK_UNINTERRUPTIBLE); mutex_unlock(&root->log_mutex); From 8bedd51b6121c4607784d75f852828d25d119c52 Mon Sep 17 00:00:00 2001 From: Mitch Harder Date: Thu, 26 Jan 2012 15:01:11 -0500 Subject: [PATCH 145/380] Btrfs: Check for NULL page in extent_range_uptodate A user has encountered a NULL pointer kernel oops in btrfs when encountering media errors. The problem has been identified as an unhandled NULL pointer returned from find_get_page(). This modification simply checks for a NULL page, and returns with an error if found (the extent_range_uptodate() function returns 1 on errors). After testing this patch, the user reported that the error with the NULL pointer oops was solved. However, there is still a remaining problem with a thread becoming stuck in wait_on_page_locked(page) in the read_extent_buffer_pages(...) function in extent_io.c for (i = start_i; i < num_pages; i++) { page = extent_buffer_page(eb, i); wait_on_page_locked(page); if (!PageUptodate(page)) ret = -EIO; } This patch leaves the issue with the locked page yet to be resolved. Signed-off-by: Mitch Harder Signed-off-by: Chris Mason --- fs/btrfs/extent_io.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 9d09a4f81875..fcf77e1ded40 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3909,6 +3909,8 @@ int extent_range_uptodate(struct extent_io_tree *tree, while (start <= end) { index = start >> PAGE_CACHE_SHIFT; page = find_get_page(tree->mapping, index); + if (!page) + return 1; uptodate = PageUptodate(page); page_cache_release(page); if (!uptodate) { From 0b4a9d248f88e6773312f262e8185f23863d984a Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 26 Jan 2012 15:01:11 -0500 Subject: [PATCH 146/380] Btrfs: use cluster->window_start when allocating from a cluster bitmap We specifically set window_start in the cluster struct to indicate where the cluster starts in a bitmap, but we've been using min_start to indicate where we're searching from. This is usually the start of the blockgroup, so essentially means we're constantly searching from the start of any bitmap we find, which completely negates all the trouble we go to in order to setup a cluster. So start using window_start to make sure we actually use the area we found. Thanks, Signed-off-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 6e7406932341..61447a51f645 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2242,7 +2242,7 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, if (entry->bitmap) { ret = btrfs_alloc_from_bitmap(block_group, cluster, entry, bytes, - min_start); + cluster->window_start); if (ret == 0) { node = rb_next(&entry->offset_index); if (!node) From 0b485143d835c019cddc45f46e4b3873dcc9aa4e Mon Sep 17 00:00:00 2001 From: Stefan Behrens Date: Thu, 26 Jan 2012 15:01:11 -0500 Subject: [PATCH 147/380] Btrfs: fix warning for 32-bit build of fs/btrfs/check-integrity.c There have been 4 warnings on 32-bit build, they are herewith fixed. Signed-off-by: Stefan Behrens Signed-off-by: Chris Mason --- fs/btrfs/check-integrity.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index ad0b3ba735b7..b669a7d8e499 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -1662,7 +1662,7 @@ static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, block = btrfsic_block_hashtable_lookup(bdev, dev_bytenr, &state->block_hashtable); if (NULL != block) { - u64 bytenr; + u64 bytenr = 0; struct list_head *elem_ref_to; struct list_head *tmp_ref_to; @@ -2777,9 +2777,10 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh) printk(KERN_INFO "submit_bh(rw=0x%x, blocknr=%lu (bytenr %llu)," " size=%lu, data=%p, bdev=%p)\n", - rw, bh->b_blocknr, - (unsigned long long)dev_bytenr, bh->b_size, - bh->b_data, bh->b_bdev); + rw, (unsigned long)bh->b_blocknr, + (unsigned long long)dev_bytenr, + (unsigned long)bh->b_size, bh->b_data, + bh->b_bdev); btrfsic_process_written_block(dev_state, dev_bytenr, bh->b_data, bh->b_size, NULL, NULL, bh, rw); @@ -2844,7 +2845,7 @@ void btrfsic_submit_bio(int rw, struct bio *bio) printk(KERN_INFO "submit_bio(rw=0x%x, bi_vcnt=%u," " bi_sector=%lu (bytenr %llu), bi_bdev=%p)\n", - rw, bio->bi_vcnt, bio->bi_sector, + rw, bio->bi_vcnt, (unsigned long)bio->bi_sector, (unsigned long long)dev_bytenr, bio->bi_bdev); From 7ec31b548a17f773ab6289e795ed3a6820e8b56e Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Thu, 26 Jan 2012 15:01:12 -0500 Subject: [PATCH 148/380] Btrfs: do not defrag a file partially xfstests 218 complains that btrfs defrags a file partially: After: 1 Write backwards sync, but contiguous - should defrag to 1 extent Before: 10 -After: 1 +After: 2 To fix this, we need to set max_to_defrag count properly. Signed-off-by: Liu Bo Signed-off-by: Chris Mason --- fs/btrfs/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 6834be4c8709..0b06a5ca8afc 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1066,7 +1066,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, i = range->start >> PAGE_CACHE_SHIFT; } if (!max_to_defrag) - max_to_defrag = last_index; + max_to_defrag = last_index + 1; /* * make writeback starts from i, so the defrag range can be From 9e622d6bea0202e9fe267955362c01918562c09b Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Thu, 26 Jan 2012 15:01:12 -0500 Subject: [PATCH 149/380] Btrfs: fix enospc error caused by wrong checks of the chunk When we did sysbench test for inline files, enospc error happened easily though there was lots of free disk space which could be allocated for new chunks. Reproduce steps: # mkfs.btrfs -b $((2 * 1024 * 1024 * 1024)) # mount /mnt # ulimit -n 102400 # cd /mnt # sysbench --num-threads=1 --test=fileio --file-num=81920 \ > --file-total-size=80M --file-block-size=1K --file-io-mode=sync \ > --file-test-mode=seqwr prepare # sysbench --num-threads=1 --test=fileio --file-num=81920 \ > --file-total-size=80M --file-block-size=1K --file-io-mode=sync \ > --file-test-mode=seqwr run The reason of this bug is: Now, we can reserve space which is larger than the free space in the chunks if we have enough free disk space which can be used for new chunks. By this way, the space allocator should allocate a new chunk by force if there is no free space in the free space cache. But there are two wrong checks which break this operation. One is if (ret == -ENOSPC && num_bytes > min_alloc_size) in btrfs_reserve_extent(), it is wrong, we should try to allocate a new chunk even we fail to allocate free space by minimum allocable size. The other is if (space_info->force_alloc) force = space_info->force_alloc; in do_chunk_alloc(). It makes the allocator ignore CHUNK_ALLOC_FORCE If someone sets ->force_alloc to CHUNK_ALLOC_LIMITED, and makes the enospc error happen. Fix these two wrong checks. Especially the second one, we fix it by changing the value of CHUNK_ALLOC_LIMITED and CHUNK_ALLOC_FORCE, and make CHUNK_ALLOC_FORCE greater than CHUNK_ALLOC_LIMITED since CHUNK_ALLOC_FORCE has higher priority. And if the value which is passed in by the caller is greater than ->force_alloc, use the passed value. Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 47 +++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 700879ed64cf..283af7a676a3 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -34,23 +34,24 @@ #include "locking.h" #include "free-space-cache.h" -/* control flags for do_chunk_alloc's force field +/* + * control flags for do_chunk_alloc's force field * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk * if we really need one. * - * CHUNK_ALLOC_FORCE means it must try to allocate one - * * CHUNK_ALLOC_LIMITED means to only try and allocate one * if we have very few chunks already allocated. This is * used as part of the clustering code to help make sure * we have a good pool of storage to cluster in, without * filling the FS with empty chunks * + * CHUNK_ALLOC_FORCE means it must try to allocate one + * */ enum { CHUNK_ALLOC_NO_FORCE = 0, - CHUNK_ALLOC_FORCE = 1, - CHUNK_ALLOC_LIMITED = 2, + CHUNK_ALLOC_LIMITED = 1, + CHUNK_ALLOC_FORCE = 2, }; /* @@ -3414,7 +3415,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, again: spin_lock(&space_info->lock); - if (space_info->force_alloc) + if (force < space_info->force_alloc) force = space_info->force_alloc; if (space_info->full) { spin_unlock(&space_info->lock); @@ -5794,6 +5795,7 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans, u64 search_end, struct btrfs_key *ins, u64 data) { + bool final_tried = false; int ret; u64 search_start = 0; @@ -5813,22 +5815,25 @@ again: search_start, search_end, hint_byte, ins, data); - if (ret == -ENOSPC && num_bytes > min_alloc_size) { - num_bytes = num_bytes >> 1; - num_bytes = num_bytes & ~(root->sectorsize - 1); - num_bytes = max(num_bytes, min_alloc_size); - do_chunk_alloc(trans, root->fs_info->extent_root, - num_bytes, data, CHUNK_ALLOC_FORCE); - goto again; - } - if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) { - struct btrfs_space_info *sinfo; + if (ret == -ENOSPC) { + if (!final_tried) { + num_bytes = num_bytes >> 1; + num_bytes = num_bytes & ~(root->sectorsize - 1); + num_bytes = max(num_bytes, min_alloc_size); + do_chunk_alloc(trans, root->fs_info->extent_root, + num_bytes, data, CHUNK_ALLOC_FORCE); + if (num_bytes == min_alloc_size) + final_tried = true; + goto again; + } else if (btrfs_test_opt(root, ENOSPC_DEBUG)) { + struct btrfs_space_info *sinfo; - sinfo = __find_space_info(root->fs_info, data); - printk(KERN_ERR "btrfs allocation failed flags %llu, " - "wanted %llu\n", (unsigned long long)data, - (unsigned long long)num_bytes); - dump_space_info(sinfo, num_bytes, 1); + sinfo = __find_space_info(root->fs_info, data); + printk(KERN_ERR "btrfs allocation failed flags %llu, " + "wanted %llu\n", (unsigned long long)data, + (unsigned long long)num_bytes); + dump_space_info(sinfo, num_bytes, 1); + } } trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset); From 0c4e538bccc106872d31b1514570b4dac95fb7f2 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Thu, 26 Jan 2012 15:01:12 -0500 Subject: [PATCH 150/380] btrfs: mask out gfp flags in releasepage btree_releasepage is a callback and can be passed unknown gfp flags and then they may end up in kmem_cache_alloc called from alloc_extent_state, slab allocator will BUG_ON when there is HIGHMEM or DMA32 flag set. This may happen when btrfs is mounted from a loop device, which masks out __GFP_IO flag. The check in try_release_extent_state 3399 if ((mask & GFP_NOFS) == GFP_NOFS) 3400 mask = GFP_NOFS; will not work and passes unfiltered flags further resulting in crash at mm/slab.c:2963 [<000000000024ae4c>] cache_alloc_refill+0x3b4/0x5c8 [<000000000024c810>] kmem_cache_alloc+0x204/0x294 [<00000000001fd3c2>] mempool_alloc+0x52/0x170 [<000003c000ced0b0>] alloc_extent_state+0x40/0xd4 [btrfs] [<000003c000cee5ae>] __clear_extent_bit+0x38a/0x4cc [btrfs] [<000003c000cee78c>] try_release_extent_state+0x9c/0xd4 [btrfs] [<000003c000cc4c66>] btree_releasepage+0x7e/0xd0 [btrfs] [<0000000000210d84>] shrink_page_list+0x6a0/0x724 [<0000000000211394>] shrink_inactive_list+0x230/0x578 [<0000000000211bb8>] shrink_list+0x6c/0x120 [<0000000000211e4e>] shrink_zone+0x1e2/0x228 [<0000000000211f24>] shrink_zones+0x90/0x254 [<0000000000213410>] do_try_to_free_pages+0xac/0x420 [<0000000000213ae0>] try_to_free_pages+0x13c/0x1b0 [<0000000000204e6c>] __alloc_pages_nodemask+0x5b4/0x9a8 [<00000000001fb04a>] grab_cache_page_write_begin+0x7e/0xe8 Signed-off-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index da4457f84d78..4c867112b4c8 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -961,6 +961,13 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags) tree = &BTRFS_I(page->mapping->host)->io_tree; map = &BTRFS_I(page->mapping->host)->extent_tree; + /* + * We need to mask out eg. __GFP_HIGHMEM and __GFP_DMA32 as we're doing + * slab allocation from alloc_extent_state down the callchain where + * it'd hit a BUG_ON as those flags are not allowed. + */ + gfp_flags &= ~GFP_SLAB_BUG_MASK; + ret = try_release_extent_state(map, tree, page, gfp_flags); if (!ret) return 0; From 9b23062840e7c685ef0a0b561285d6e3a3b6811b Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 26 Jan 2012 15:01:12 -0500 Subject: [PATCH 151/380] Btrfs: advance window_start if we're using a bitmap If we span a long area in a bitmap we could end up taking a lot of time searching to the next free area if we're searching from the original window_start, so advance window_start in order to make sure we don't do any superficial searching. Thanks, Signed-off-by: Josef Bacik Signed-off-by: Chris Mason --- fs/btrfs/free-space-cache.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 61447a51f645..5802b1473c3d 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2251,6 +2251,7 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, offset_index); continue; } + cluster->window_start += bytes; } else { ret = entry->offset; From fc395b9291925b1880e0afc61274fe2f6ddc1269 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 26 Jan 2012 15:47:37 +0000 Subject: [PATCH 152/380] x86: Properly parenthesize cmpxchg() macro arguments Quite oddly, all of the arguments passed through from the top level macros to the second level which didn't need parentheses had them, while the only expression (involving a parameter) needing them didn't. Very recently I got bitten by the lack thereof when using something like "array + index" for the first operand, with "array" being an array more narrow than int. Signed-off-by: Jan Beulich Cc: Linus Torvalds Link: http://lkml.kernel.org/r/4F2183A9020000780006F3E6@nat28.tlf.novell.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cmpxchg.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h index 0c9fa2745f13..b3b733262909 100644 --- a/arch/x86/include/asm/cmpxchg.h +++ b/arch/x86/include/asm/cmpxchg.h @@ -145,13 +145,13 @@ extern void __add_wrong_size(void) #ifdef __HAVE_ARCH_CMPXCHG #define cmpxchg(ptr, old, new) \ - __cmpxchg((ptr), (old), (new), sizeof(*ptr)) + __cmpxchg(ptr, old, new, sizeof(*(ptr))) #define sync_cmpxchg(ptr, old, new) \ - __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr)) + __sync_cmpxchg(ptr, old, new, sizeof(*(ptr))) #define cmpxchg_local(ptr, old, new) \ - __cmpxchg_local((ptr), (old), (new), sizeof(*ptr)) + __cmpxchg_local(ptr, old, new, sizeof(*(ptr))) #endif /* From b0f4c4b32c8e3aa0d44fc4dd6c40a9a9a8d66b63 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Thu, 26 Jan 2012 08:55:34 -0500 Subject: [PATCH 153/380] bugs, x86: Fix printk levels for panic, softlockups and stack dumps rsyslog will display KERN_EMERG messages on a connected terminal. However, these messages are useless/undecipherable for a general user. For example, after a softlockup we get: Message from syslogd@intel-s3e37-04 at Jan 25 14:18:06 ... kernel:Stack: Message from syslogd@intel-s3e37-04 at Jan 25 14:18:06 ... kernel:Call Trace: Message from syslogd@intel-s3e37-04 at Jan 25 14:18:06 ... kernel:Code: ff ff a8 08 75 25 31 d2 48 8d 86 38 e0 ff ff 48 89 d1 0f 01 c8 0f ae f0 48 8b 86 38 e0 ff ff a8 08 75 08 b1 01 4c 89 e0 0f 01 c9 ea 69 dd ff 4c 29 e8 48 89 c7 e8 0f bc da ff 49 89 c4 49 89 This happens because the printk levels for these messages are incorrect. Only an informational message should be displayed on a terminal. I modified the printk levels for various messages in the kernel and tested the output by using the drivers/misc/lkdtm.c kernel modules (ie, softlockups, panics, hard lockups, etc.) and confirmed that the console output was still the same and that the output to the terminals was correct. For example, in the case of a softlockup we now see the much more informative: Message from syslogd@intel-s3e37-04 at Jan 25 10:18:06 ... BUG: soft lockup - CPU4 stuck for 60s! instead of the above confusing messages. AFAICT, the messages no longer have to be KERN_EMERG. In the most important case of a panic we set console_verbose(). As for the other less severe cases the correct data is output to the console and /var/log/messages. Successfully tested by me using the drivers/misc/lkdtm.c module. Signed-off-by: Prarit Bhargava Cc: dzickus@redhat.com Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/r/1327586134-11926-1-git-send-email-prarit@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/dumpstack.c | 3 ++- arch/x86/kernel/dumpstack_64.c | 6 +++--- arch/x86/mm/fault.c | 4 ++-- kernel/watchdog.c | 2 +- lib/bug.c | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 1aae78f775fc..4025fe4f928f 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -252,7 +252,8 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err) unsigned short ss; unsigned long sp; #endif - printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); + printk(KERN_DEFAULT + "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); #ifdef CONFIG_PREEMPT printk("PREEMPT "); #endif diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 6d728d9284bd..42b2bca0b72c 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -269,11 +269,11 @@ void show_registers(struct pt_regs *regs) unsigned char c; u8 *ip; - printk(KERN_EMERG "Stack:\n"); + printk(KERN_DEFAULT "Stack:\n"); show_stack_log_lvl(NULL, regs, (unsigned long *)sp, - 0, KERN_EMERG); + 0, KERN_DEFAULT); - printk(KERN_EMERG "Code: "); + printk(KERN_DEFAULT "Code: "); ip = (u8 *)regs->ip - code_prologue; if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 9d74824a708d..f0b4caf85c1a 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -673,7 +673,7 @@ no_context(struct pt_regs *regs, unsigned long error_code, stackend = end_of_stack(tsk); if (tsk != &init_task && *stackend != STACK_END_MAGIC) - printk(KERN_ALERT "Thread overran stack, or stack corrupted\n"); + printk(KERN_EMERG "Thread overran stack, or stack corrupted\n"); tsk->thread.cr2 = address; tsk->thread.trap_no = 14; @@ -684,7 +684,7 @@ no_context(struct pt_regs *regs, unsigned long error_code, sig = 0; /* Executive summary in case the body of the oops scrolled away */ - printk(KERN_EMERG "CR2: %016lx\n", address); + printk(KERN_DEFAULT "CR2: %016lx\n", address); oops_end(flags, regs, sig); } diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 1d7bca7f4f52..d117262deba3 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -296,7 +296,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) if (__this_cpu_read(soft_watchdog_warn) == true) return HRTIMER_RESTART; - printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", + printk(KERN_EMERG "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", smp_processor_id(), duration, current->comm, task_pid_nr(current)); print_modules(); diff --git a/lib/bug.c b/lib/bug.c index 19552096d16b..a28c1415357c 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -169,7 +169,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs) return BUG_TRAP_TYPE_WARN; } - printk(KERN_EMERG "------------[ cut here ]------------\n"); + printk(KERN_DEFAULT "------------[ cut here ]------------\n"); if (file) printk(KERN_CRIT "kernel BUG at %s:%u!\n", From f2b3ee9e4200b32d113b1bd3c93f9a836c97357c Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 26 Jan 2012 10:34:35 +0000 Subject: [PATCH 154/380] ipv6: Fix ip_gre lockless xmits. Tunnel devices set NETIF_F_LLTX to bypass HARD_TX_LOCK. Sit and ipip set this unconditionally in ops->setup, but gre enables it conditionally after parameter passing in ops->newlink. This is not called during tunnel setup as below, however, so GRE tunnels are still taking the lock. modprobe ip_gre ip tunnel add test0 mode gre remote 10.5.1.1 dev lo ip link set test0 up ip addr add 10.6.0.1 dev test0 # cat /sys/class/net/test0/features # $DIR/test_tunnel_xmit 10 10.5.2.1 ip route add 10.5.2.0/24 dev test0 ip tunnel del test0 The newlink callback is only called in rtnl_netlink, and only if the device is new, as it calls register_netdevice internally. Gre tunnels are created at 'ip tunnel add' with ioctl SIOCADDTUNNEL, which calls ipgre_tunnel_locate, which calls register_netdev. rtnl_newlink is called at 'ip link set', but skips ops->newlink and the device is up with locking still enabled. The equivalent ipip tunnel works fine, btw (just substitute 'method gre' for 'method ipip'). On kernels before /sys/class/net/*/features was removed [1], the first commented out line returns 0x6000 with method gre, which indicates that NETIF_F_LLTX (0x1000) is not set. With ipip, it reports 0x7000. This test cannot be used on recent kernels where the sysfs file is removed (and ETHTOOL_GFEATURES does not currently work for tunnel devices, because they lack dev->ethtool_ops). The second commented out line calls a simple transmission test [2] that sends on 24 cores at maximum rate. Results of a single run: ipip: 19,372,306 gre before patch: 4,839,753 gre after patch: 19,133,873 This patch replicates the condition check in ipgre_newlink to ipgre_tunnel_locate. It works for me, both with oseq on and off. This is the first time I looked at rtnetlink and iproute2 code, though, so someone more knowledgeable should probably check the patch. Thanks. The tail of both functions is now identical, by the way. To avoid code duplication, I'll be happy to rework this and merge the two. [1] http://patchwork.ozlabs.org/patch/104610/ [2] http://kernel.googlecode.com/files/xmit_udp_parallel.c Signed-off-by: Willem de Bruijn Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 2b53a1f7abf6..6b3ca5ba4450 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -422,6 +422,10 @@ static struct ip_tunnel *ipgre_tunnel_locate(struct net *net, if (register_netdevice(dev) < 0) goto failed_free; + /* Can use a lockless transmit, unless we generate output sequences */ + if (!(nt->parms.o_flags & GRE_SEQ)) + dev->features |= NETIF_F_LLTX; + dev_hold(dev); ipgre_tunnel_link(ign, nt); return nt; From f18da14565819ba43b8321237e2426a2914cc2ef Mon Sep 17 00:00:00 2001 From: Stefan Gula Date: Thu, 26 Jan 2012 11:01:06 +0000 Subject: [PATCH 155/380] net: RTNETLINK adjusting values of min_ifinfo_dump_size Setting link parameters on a netdevice changes the value of if_nlmsg_size(), therefore it is necessary to recalculate min_ifinfo_dump_size. Signed-off-by: Stefan Gula Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f16444bc6cbb..65aebd450027 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1509,6 +1509,9 @@ errout: if (send_addr_notify) call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + min_ifinfo_dump_size = max_t(u16, if_nlmsg_size(dev), + min_ifinfo_dump_size); + return err; } From d1bb399ad03c11e792f6dea198d3b1e23061f094 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 26 Jan 2012 22:05:58 +0100 Subject: [PATCH 156/380] firewire: ohci: add reset packet quirk for SB Audigy The Audigy's SB1394 controller is actually from Texas Instruments and has the same bus reset packet generation bug, so it needs the same quirk entry. Signed-off-by: Clemens Ladisch Cc: 2.6.36+ Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 6628feaa7622..21250eca28d1 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -263,6 +263,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) static char ohci_driver_name[] = KBUILD_MODNAME; #define PCI_DEVICE_ID_AGERE_FW643 0x5901 +#define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380 #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 #define PCI_DEVICE_ID_TI_TSB12LV26 0x8020 @@ -289,6 +290,9 @@ static const struct { {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6, QUIRK_NO_MSI}, + {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID, + QUIRK_RESET_PACKET}, + {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID, QUIRK_NO_MSI}, From 9018e93948c6f8f95fbcc9fa05f6c403d6adb406 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Thu, 26 Jan 2012 12:09:28 +0000 Subject: [PATCH 157/380] net: explicitly add jump_label.h header to sock.h Commit 36a1211970193ce215de50ed1e4e1272bc814df1 removed linux/module.h include statement from one of the headers that end up in net/sock.h. It was providing us with static_branch() definition implicitly, so after its removal the build got broken. To fix this, and avoid having this happening in the future, let me do the right thing and include linux/jump_label.h explicitly in sock.h. Signed-off-by: Glauber Costa Reported-by: Randy Dunlap CC: David S. Miller Signed-off-by: David S. Miller --- include/net/sock.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/sock.h b/include/net/sock.h index 4c69ac165e6b..91c1c8baf020 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -55,6 +55,7 @@ #include #include #include +#include #include #include From d22b086970c3ee2d327d7dfdcb436254f7f72204 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 21 Jan 2012 13:29:27 -0500 Subject: [PATCH 158/380] MAINTAINERS: Add hwmon entries for Wolfson The actual driver code seems to have been lost in the shuffle. Signed-off-by: Mark Brown Signed-off-by: Guenter Roeck --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 89b70df91f4f..8cc2d457a91b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7357,6 +7357,7 @@ S: Supported F: Documentation/hwmon/wm83?? F: arch/arm/mach-s3c64xx/mach-crag6410* F: drivers/leds/leds-wm83*.c +F: drivers/hwmon/wm83??-hwmon.c F: drivers/input/misc/wm831x-on.c F: drivers/input/touchscreen/wm831x-ts.c F: drivers/input/touchscreen/wm97*.c From cba9384b3c53d1a302206f68134a6cbfbae1d686 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 20 Jan 2012 02:01:11 -0800 Subject: [PATCH 159/380] MAINTAINERS: Drop maintainer for MAX1668 hwmon driver David no longer has access to MAX1688 hardware, so drop him from the maintainers list. Cc: David George Signed-off-by: Guenter Roeck Acked-by: David George Acked-by: Jean Delvare --- MAINTAINERS | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8cc2d457a91b..686c652e1ae1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4267,13 +4267,6 @@ S: Orphan F: drivers/video/matrox/matroxfb_* F: include/linux/matroxfb.h -MAX1668 TEMPERATURE SENSOR DRIVER -M: "David George" -L: lm-sensors@lm-sensors.org -S: Maintained -F: Documentation/hwmon/max1668 -F: drivers/hwmon/max1668.c - MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER M: "Hans J. Koch" L: lm-sensors@lm-sensors.org From 5d32d4868ad87a5be8571b22b3d732576504dfb0 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 27 Dec 2011 15:01:28 +0100 Subject: [PATCH 160/380] watchdog: imx2_wdt.c: use devm_request_and_ioremap Reimplement a call to devm_request_mem_region followed by a call to ioremap or ioremap_nocache by a call to devm_request_and_ioremap. The variable res_size is then no longer needed. The semantic patch that makes this transformation is as follows: (http://coccinelle.lip6.fr/) // @nm@ expression myname; identifier i; @@ struct platform_driver i = { .driver = { .name = myname } }; @@ expression dev,res,size; expression nm.myname; @@ -if (!devm_request_mem_region(dev, res->start, size, - \(res->name\|dev_name(dev)\|myname\))) { - ... - return ...; -} ... when != res->start ( -devm_ioremap(dev,res->start,size) +devm_request_and_ioremap(dev,res) | -devm_ioremap_nocache(dev,res->start,size) +devm_request_and_ioremap(dev,res) ) ... when any when != res->start // Signed-off-by: Julia Lawall Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/imx2_wdt.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index b8ef2c6dca7c..c44c3334003a 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -247,7 +247,6 @@ static struct miscdevice imx2_wdt_miscdev = { static int __init imx2_wdt_probe(struct platform_device *pdev) { int ret; - int res_size; struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -256,15 +255,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) return -ENODEV; } - res_size = resource_size(res); - if (!devm_request_mem_region(&pdev->dev, res->start, res_size, - res->name)) { - dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n", - res_size, res->start); - return -ENOMEM; - } - - imx2_wdt.base = devm_ioremap_nocache(&pdev->dev, res->start, res_size); + imx2_wdt.base = devm_request_and_ioremap(&pdev->dev, res); if (!imx2_wdt.base) { dev_err(&pdev->dev, "ioremap failed\n"); return -ENOMEM; From 52ea9a7d7946c03aa1f9eeb71adb0191402724dd Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 27 Dec 2011 15:01:29 +0100 Subject: [PATCH 161/380] watchdog: dw_wdt.c: use devm_request_and_ioremap Reimplement a call to devm_request_mem_region followed by a call to ioremap or ioremap_nocache by a call to devm_request_and_ioremap. The semantic patch that makes this transformation is as follows: (http://coccinelle.lip6.fr/) // @nm@ expression myname; identifier i; @@ struct platform_driver i = { .driver = { .name = myname } }; @@ expression dev,res,size; expression nm.myname; @@ -if (!devm_request_mem_region(dev, res->start, size, - \(res->name\|dev_name(dev)\|myname\))) { - ... - return ...; -} ... when != res->start ( -devm_ioremap(dev,res->start,size) +devm_request_and_ioremap(dev,res) | -devm_ioremap_nocache(dev,res->start,size) +devm_request_and_ioremap(dev,res) ) ... when any when != res->start // Signed-off-by: Julia Lawall Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/dw_wdt.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 1b0e3dd81c1a..63d7b58f1c7d 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -300,11 +300,7 @@ static int __devinit dw_wdt_drv_probe(struct platform_device *pdev) if (!mem) return -EINVAL; - if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), - "dw_wdt")) - return -ENOMEM; - - dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); + dw_wdt.regs = devm_request_and_ioremap(&pdev->dev, mem); if (!dw_wdt.regs) return -ENOMEM; From 12c583d8dca3320f36afe51e514dfa709ac0662e Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Wed, 11 Jan 2012 19:50:18 +0530 Subject: [PATCH 162/380] watchdog: omap_wdt.c: Fix the mismatch of pm_runtime enable and disable Currently the watchdog driver calls the pm_runtime_enable and never the disable. This may cause a warning when pm_runtime_enable checks for the count match. Also fixes the error /build/watchdog # insmod omap_wdt.ko [ 44.999389] omap_wdt omap_wdt: Unbalanced pm_runtime_enable! [ 45.011047] OMAP Watchdog Timer Rev 0x00: initial timeout 60 sec /build/watchdog # Attempting to fix the same by calling pm_runtime_disable. Signed-off-by: Shubhrajyoti D Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/omap_wdt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 4b33e3fd726b..d19ff5145e82 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -339,6 +339,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) return 0; err_misc: + pm_runtime_disable(wdev->dev); platform_set_drvdata(pdev, NULL); iounmap(wdev->base); @@ -371,6 +372,7 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev) struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pm_runtime_disable(wdev->dev); if (!res) return -ENOENT; From 0318e286f9a73547dedfd9f733671f4941efb0e2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 14 Jan 2012 19:34:34 +0800 Subject: [PATCH 163/380] watchdog: via_wdt: Staticise wdt_pci_table It is only used in this driver, so no need to make the symbol global. Signed-off-by: Axel Lin Acked-by: Marc Vertes Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/via_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c index 026b4bbfa0aa..8b24b000062e 100644 --- a/drivers/watchdog/via_wdt.c +++ b/drivers/watchdog/via_wdt.c @@ -233,7 +233,7 @@ static void __devexit wdt_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = { +static DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700) }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800) }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) }, From e352829a67c1a80c73dfad33ba9dca8ddf2ef0fd Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Jan 2012 10:45:20 +0800 Subject: [PATCH 164/380] watchdog: Staticise nuc900_wdt It is only used in this driver, so no need to make the symbol global. Signed-off-by: Axel Lin Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/nuc900_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c index 50359bad9177..2cce8568bd21 100644 --- a/drivers/watchdog/nuc900_wdt.c +++ b/drivers/watchdog/nuc900_wdt.c @@ -72,7 +72,7 @@ struct nuc900_wdt { }; static unsigned long nuc900wdt_busy; -struct nuc900_wdt *nuc900_wdt; +static struct nuc900_wdt *nuc900_wdt; static inline void nuc900_wdt_keepalive(void) { From 2865e770c9dddd40676eadf7c3dfe80aee7628e4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Jan 2012 10:46:52 +0800 Subject: [PATCH 165/380] watchdog: Return proper error in nuc900wdt_probe if misc_register fails Return proper error instead of 0 if misc_register fails Signed-off-by: Axel Lin Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/nuc900_wdt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c index 2cce8568bd21..529085b8b8fb 100644 --- a/drivers/watchdog/nuc900_wdt.c +++ b/drivers/watchdog/nuc900_wdt.c @@ -287,7 +287,8 @@ static int __devinit nuc900wdt_probe(struct platform_device *pdev) setup_timer(&nuc900_wdt->timer, nuc900_wdt_timer_ping, 0); - if (misc_register(&nuc900wdt_miscdev)) { + ret = misc_register(&nuc900wdt_miscdev); + if (ret) { dev_err(&pdev->dev, "err register miscdev on minor=%d (%d)\n", WATCHDOG_MINOR, ret); goto err_clk; From ebe06e826faed9d710c3d49fe336c74b5f3a5f2a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Jan 2012 19:25:01 +0800 Subject: [PATCH 166/380] watchdog: wm8350_wdt: Fix handling WDIOS_DISABLECARD/WDIOS_ENABLECARD options While receiving WDIOS_DISABLECARD option for WDIOC_SETOPTIONS command, call wm8350_wdt_stop() to disable watchdog. Call wm8350_wdt_start() while receiving WDIOS_ENABLECARD option. Current code has reverse behavior. Signed-off-by: Axel Lin Acked-by: Mark Brown Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wm8350_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c index 909c78650d3e..5d7113c7e501 100644 --- a/drivers/watchdog/wm8350_wdt.c +++ b/drivers/watchdog/wm8350_wdt.c @@ -212,10 +212,10 @@ static long wm8350_wdt_ioctl(struct file *file, unsigned int cmd, /* Setting both simultaneously means at least one must fail */ if (options == WDIOS_DISABLECARD) - ret = wm8350_wdt_start(wm8350); + ret = wm8350_wdt_stop(wm8350); if (options == WDIOS_ENABLECARD) - ret = wm8350_wdt_stop(wm8350); + ret = wm8350_wdt_start(wm8350); break; } From 8a062ac693d5597b3c5d0e347ce7d1d82b967698 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Jan 2012 19:26:43 +0800 Subject: [PATCH 167/380] watchdog: wafer5823wdt: Fix handling WDIOS_DISABLECARD/WDIOS_ENABLECARD options While receiving WDIOS_DISABLECARD option for WDIOC_SETOPTIONS command, call wafwdt_stop() to disable watchdog. Call wafwdt_start() while receiving WDIOS_ENABLECARD option. Current code has reverse behavior. Signed-off-by: Axel Lin Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wafer5823wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c index 42e940c23891..c3c3188c34d7 100644 --- a/drivers/watchdog/wafer5823wdt.c +++ b/drivers/watchdog/wafer5823wdt.c @@ -152,12 +152,12 @@ static long wafwdt_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (options & WDIOS_DISABLECARD) { - wafwdt_start(); + wafwdt_stop(); retval = 0; } if (options & WDIOS_ENABLECARD) { - wafwdt_stop(); + wafwdt_start(); retval = 0; } From b1785dfd4fcd4011834f914810c1acb46b007a44 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 20 Jan 2012 23:56:19 +0900 Subject: [PATCH 168/380] watchdog: Fix typo "unexpectdly" Correct typo "unexpectdly" to "unexpectedly" in pnx4008_wdt.c and stmp3xxx_wdt.c Signed-off-by: Masanari Iida Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pnx4008_wdt.c | 2 +- drivers/watchdog/stmp3xxx_wdt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index bd143c9dd3e6..8e210aafdfd0 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -226,7 +226,7 @@ static long pnx4008_wdt_ioctl(struct file *file, unsigned int cmd, static int pnx4008_wdt_release(struct inode *inode, struct file *file) { if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) - printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n"); + printk(KERN_WARNING "WATCHDOG: Device closed unexpectedly\n"); wdt_disable(); clk_disable(wdt_clk); diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c index 4c2a4e8698f9..e37d81178b9e 100644 --- a/drivers/watchdog/stmp3xxx_wdt.c +++ b/drivers/watchdog/stmp3xxx_wdt.c @@ -174,7 +174,7 @@ static int stmp3xxx_wdt_release(struct inode *inode, struct file *file) if (!nowayout) { if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { wdt_ping(); - pr_debug("%s: Device closed unexpectdly\n", __func__); + pr_debug("%s: Device closed unexpectedly\n", __func__); ret = -EINVAL; } else { wdt_disable(); From f6dd94f8194408e11df4e33e1f7113612e84ca17 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 21 Jan 2012 15:08:38 +0800 Subject: [PATCH 169/380] watchdog: via_wdt: Set min_timeout and max_timeout for wdt_dev Let the watchdog core to check the valid value range of min_timeout/max_timeout. Signed-off-by: Axel Lin Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/via_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c index 8b24b000062e..8f07dd4bd94a 100644 --- a/drivers/watchdog/via_wdt.c +++ b/drivers/watchdog/via_wdt.c @@ -124,8 +124,6 @@ static int wdt_stop(struct watchdog_device *wdd) static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int new_timeout) { - if (new_timeout < 1 || new_timeout > WDT_TIMEOUT_MAX) - return -EINVAL; writel(new_timeout, wdt_mem + VIA_WDT_COUNT); timeout = new_timeout; return 0; @@ -150,6 +148,8 @@ static const struct watchdog_ops wdt_ops = { static struct watchdog_device wdt_dev = { .info = &wdt_info, .ops = &wdt_ops, + .min_timeout = 1, + .max_timeout = WDT_TIMEOUT_MAX, }; static int __devinit wdt_probe(struct pci_dev *pdev, From 84e83c2846ffb42772056a0f825d8578dc92d586 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Mon, 23 Jan 2012 16:40:55 -0800 Subject: [PATCH 170/380] watchdog: iTCO_wdt: add Intel Lynx Point DeviceIDs This patch adds the TCO Watchdog DeviceIDs for the Intel Lynx Point PCH. Signed-off-by: Seth Heasley Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 99796c5d913d..bdf401b240b5 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -36,6 +36,7 @@ * document number TBD : Patsburg (PBG) * document number TBD : DH89xxCC * document number TBD : Panther Point + * document number TBD : Lynx Point */ /* @@ -126,6 +127,7 @@ enum iTCO_chipsets { TCO_PBG, /* Patsburg */ TCO_DH89XXCC, /* DH89xxCC */ TCO_PPT, /* Panther Point */ + TCO_LPT, /* Lynx Point */ }; static struct { @@ -189,6 +191,7 @@ static struct { {"Patsburg", 2}, {"DH89xxCC", 2}, {"Panther Point", 2}, + {"Lynx Point", 2}, {NULL, 0} }; @@ -331,6 +334,38 @@ static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = { { PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT}, { PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT}, { PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT}, + { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c43), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c44), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c45), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c46), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c47), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c48), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c49), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4a), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4b), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4c), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4d), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4e), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4f), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c50), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c51), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c52), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c53), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c54), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c55), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c56), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c57), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c58), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c59), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5a), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5b), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5c), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5d), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5e), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5f), TCO_LPT}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); From b5740f4b2cb3503b436925eb2242bc3d75cd3dfe Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Tue, 17 Jan 2012 17:40:31 +0900 Subject: [PATCH 171/380] sched: Fix ancient race in do_exit() try_to_wake_up() has a problem which may change status from TASK_DEAD to TASK_RUNNING in race condition with SMI or guest environment of virtual machine. As a result, exited task is scheduled() again and panic occurs. Here is the sequence how it occurs: ----------------------------------+----------------------------- | CPU A | CPU B ----------------------------------+----------------------------- TASK A calls exit().... do_exit() exit_mm() down_read(mm->mmap_sem); rwsem_down_failed_common() set TASK_UNINTERRUPTIBLE set waiter.task <= task A list_add to sem->wait_list : raw_spin_unlock_irq() (I/O interruption occured) __rwsem_do_wake(mmap_sem) list_del(&waiter->list); waiter->task = NULL wake_up_process(task A) try_to_wake_up() (task is still TASK_UNINTERRUPTIBLE) p->on_rq is still 1.) ttwu_do_wakeup() (*A) : (I/O interruption handler finished) if (!waiter.task) schedule() is not called due to waiter.task is NULL. tsk->state = TASK_RUNNING : check_preempt_curr(); : task->state = TASK_DEAD (*B) <--- set TASK_RUNNING (*C) schedule() (exit task is running again) BUG_ON() is called! -------------------------------------------------------- The execution time between (*A) and (*B) is usually very short, because the interruption is disabled, and setting TASK_RUNNING at (*C) must be executed before setting TASK_DEAD. HOWEVER, if SMI is interrupted between (*A) and (*B), (*C) is able to execute AFTER setting TASK_DEAD! Then, exited task is scheduled again, and BUG_ON() is called.... If the system works on guest system of virtual machine, the time between (*A) and (*B) may be also long due to scheduling of hypervisor, and same phenomenon can occur. By this patch, do_exit() waits for releasing task->pi_lock which is used in try_to_wake_up(). It guarantees the task becomes TASK_DEAD after waking up. Signed-off-by: Yasunori Goto Acked-by: Oleg Nesterov Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/r/20120117174031.3118.E1E9C6FF@jp.fujitsu.com Signed-off-by: Ingo Molnar --- kernel/exit.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/kernel/exit.c b/kernel/exit.c index 294b1709170d..4b4042f9bc6a 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1038,6 +1038,22 @@ void do_exit(long code) if (tsk->nr_dirtied) __this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied); exit_rcu(); + + /* + * The setting of TASK_RUNNING by try_to_wake_up() may be delayed + * when the following two conditions become true. + * - There is race condition of mmap_sem (It is acquired by + * exit_mm()), and + * - SMI occurs before setting TASK_RUNINNG. + * (or hypervisor of virtual machine switches to other guest) + * As a result, we may become TASK_RUNNING after becoming TASK_DEAD + * + * To avoid it, we have to wait for releasing tsk->pi_lock which + * is held by try_to_wake_up() + */ + smp_mb(); + raw_spin_unlock_wait(&tsk->pi_lock); + /* causes final put_task_struct in finish_task_switch(). */ tsk->state = TASK_DEAD; tsk->flags |= PF_NOFREEZE; /* tell freezer to ignore us */ From e050e3f0a71bf7dc2c148b35caff0234decc8198 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Thu, 26 Jan 2012 17:03:19 +0100 Subject: [PATCH 172/380] perf: Fix broken interrupt rate throttling This patch fixes the sampling interrupt throttling mechanism. It was broken in v3.2. Events were not being unthrottled. The unthrottling mechanism required that events be checked at each timer tick. This patch solves this problem and also separates: - unthrottling - multiplexing - frequency-mode period adjustments Not all of them need to be executed at each timer tick. This third version of the patch is based on my original patch + PeterZ proposal (https://lkml.org/lkml/2012/1/7/87). At each timer tick, for each context: - if the current CPU has throttled events, we unthrottle events - if context has frequency-based events, we adjust sampling periods - if we have reached the jiffies interval, we multiplex (rotate) We decoupled rotation (multiplexing) from frequency-mode sampling period adjustments. They should not necessarily happen at the same rate. Multiplexing is subject to jiffies_interval (currently at 1 but could be higher once the tunable is exposed via sysfs). We have grouped frequency-mode adjustment and unthrottling into the same routine to minimize code duplication. When throttled while in frequency mode, we scan the events only once. We have fixed the threshold enforcement code in __perf_event_overflow(). There was a bug whereby it would allow more than the authorized rate because an increment of hwc->interrupts was not executed at the right place. The patch was tested with low sampling limit (2000) and fixed periods, frequency mode, overcommitted PMU. On a 2.1GHz AMD CPU: $ cat /proc/sys/kernel/perf_event_max_sample_rate 2000 We set a rate of 3000 samples/sec (2.1GHz/3000 = 700000): $ perf record -e cycles,cycles -c 700000 noploop 10 $ perf report -D | tail -21 Aggregated stats: TOTAL events: 80086 MMAP events: 88 COMM events: 2 EXIT events: 4 THROTTLE events: 19996 UNTHROTTLE events: 19996 SAMPLE events: 40000 cycles stats: TOTAL events: 40006 MMAP events: 5 COMM events: 1 EXIT events: 4 THROTTLE events: 9998 UNTHROTTLE events: 9998 SAMPLE events: 20000 cycles stats: TOTAL events: 39996 THROTTLE events: 9998 UNTHROTTLE events: 9998 SAMPLE events: 20000 For 10s, the cap is 2x2000x10 = 40000 samples. We get exactly that: 20000 samples/event. Signed-off-by: Stephane Eranian Cc: # v3.2+ Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120126160319.GA5655@quad Signed-off-by: Ingo Molnar --- include/linux/perf_event.h | 1 + kernel/events/core.c | 104 +++++++++++++++++++++++-------------- 2 files changed, 67 insertions(+), 38 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 08855613ceb3..abb2776be1ba 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -587,6 +587,7 @@ struct hw_perf_event { u64 sample_period; u64 last_period; local64_t period_left; + u64 interrupts_seq; u64 interrupts; u64 freq_time_stamp; diff --git a/kernel/events/core.c b/kernel/events/core.c index 32b48c889711..ba36013cfb21 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2300,6 +2300,9 @@ do { \ return div64_u64(dividend, divisor); } +static DEFINE_PER_CPU(int, perf_throttled_count); +static DEFINE_PER_CPU(u64, perf_throttled_seq); + static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) { struct hw_perf_event *hwc = &event->hw; @@ -2325,16 +2328,29 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) } } -static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period) +/* + * combine freq adjustment with unthrottling to avoid two passes over the + * events. At the same time, make sure, having freq events does not change + * the rate of unthrottling as that would introduce bias. + */ +static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx, + int needs_unthr) { struct perf_event *event; struct hw_perf_event *hwc; - u64 interrupts, now; + u64 now, period = TICK_NSEC; s64 delta; - if (!ctx->nr_freq) + /* + * only need to iterate over all events iff: + * - context have events in frequency mode (needs freq adjust) + * - there are events to unthrottle on this cpu + */ + if (!(ctx->nr_freq || needs_unthr)) return; + raw_spin_lock(&ctx->lock); + list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { if (event->state != PERF_EVENT_STATE_ACTIVE) continue; @@ -2344,13 +2360,8 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period) hwc = &event->hw; - interrupts = hwc->interrupts; - hwc->interrupts = 0; - - /* - * unthrottle events on the tick - */ - if (interrupts == MAX_INTERRUPTS) { + if (needs_unthr && hwc->interrupts == MAX_INTERRUPTS) { + hwc->interrupts = 0; perf_log_throttle(event, 1); event->pmu->start(event, 0); } @@ -2358,14 +2369,26 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period) if (!event->attr.freq || !event->attr.sample_freq) continue; - event->pmu->read(event); + /* + * stop the event and update event->count + */ + event->pmu->stop(event, PERF_EF_UPDATE); + now = local64_read(&event->count); delta = now - hwc->freq_count_stamp; hwc->freq_count_stamp = now; + /* + * restart the event + * reload only if value has changed + */ if (delta > 0) perf_adjust_period(event, period, delta); + + event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0); } + + raw_spin_unlock(&ctx->lock); } /* @@ -2388,16 +2411,13 @@ static void rotate_ctx(struct perf_event_context *ctx) */ static void perf_rotate_context(struct perf_cpu_context *cpuctx) { - u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC; struct perf_event_context *ctx = NULL; - int rotate = 0, remove = 1, freq = 0; + int rotate = 0, remove = 1; if (cpuctx->ctx.nr_events) { remove = 0; if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active) rotate = 1; - if (cpuctx->ctx.nr_freq) - freq = 1; } ctx = cpuctx->task_ctx; @@ -2405,37 +2425,26 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx) remove = 0; if (ctx->nr_events != ctx->nr_active) rotate = 1; - if (ctx->nr_freq) - freq = 1; } - if (!rotate && !freq) + if (!rotate) goto done; perf_ctx_lock(cpuctx, cpuctx->task_ctx); perf_pmu_disable(cpuctx->ctx.pmu); - if (freq) { - perf_ctx_adjust_freq(&cpuctx->ctx, interval); - if (ctx) - perf_ctx_adjust_freq(ctx, interval); - } + cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); + if (ctx) + ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); - if (rotate) { - cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); - if (ctx) - ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); + rotate_ctx(&cpuctx->ctx); + if (ctx) + rotate_ctx(ctx); - rotate_ctx(&cpuctx->ctx); - if (ctx) - rotate_ctx(ctx); - - perf_event_sched_in(cpuctx, ctx, current); - } + perf_event_sched_in(cpuctx, ctx, current); perf_pmu_enable(cpuctx->ctx.pmu); perf_ctx_unlock(cpuctx, cpuctx->task_ctx); - done: if (remove) list_del_init(&cpuctx->rotation_list); @@ -2445,10 +2454,22 @@ void perf_event_task_tick(void) { struct list_head *head = &__get_cpu_var(rotation_list); struct perf_cpu_context *cpuctx, *tmp; + struct perf_event_context *ctx; + int throttled; WARN_ON(!irqs_disabled()); + __this_cpu_inc(perf_throttled_seq); + throttled = __this_cpu_xchg(perf_throttled_count, 0); + list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) { + ctx = &cpuctx->ctx; + perf_adjust_freq_unthr_context(ctx, throttled); + + ctx = cpuctx->task_ctx; + if (ctx) + perf_adjust_freq_unthr_context(ctx, throttled); + if (cpuctx->jiffies_interval == 1 || !(jiffies % cpuctx->jiffies_interval)) perf_rotate_context(cpuctx); @@ -4509,6 +4530,7 @@ static int __perf_event_overflow(struct perf_event *event, { int events = atomic_read(&event->event_limit); struct hw_perf_event *hwc = &event->hw; + u64 seq; int ret = 0; /* @@ -4518,14 +4540,20 @@ static int __perf_event_overflow(struct perf_event *event, if (unlikely(!is_sampling_event(event))) return 0; - if (unlikely(hwc->interrupts >= max_samples_per_tick)) { - if (throttle) { + seq = __this_cpu_read(perf_throttled_seq); + if (seq != hwc->interrupts_seq) { + hwc->interrupts_seq = seq; + hwc->interrupts = 1; + } else { + hwc->interrupts++; + if (unlikely(throttle + && hwc->interrupts >= max_samples_per_tick)) { + __this_cpu_inc(perf_throttled_count); hwc->interrupts = MAX_INTERRUPTS; perf_log_throttle(event, 0); ret = 1; } - } else - hwc->interrupts++; + } if (event->attr.freq) { u64 now = perf_clock(); From cb297a3e433dbdcf7ad81e0564e7b804c941ff0d Mon Sep 17 00:00:00 2001 From: Chanho Min Date: Thu, 5 Jan 2012 20:00:19 +0900 Subject: [PATCH 173/380] sched/rt: Fix task stack corruption under __ARCH_WANT_INTERRUPTS_ON_CTXSW This issue happens under the following conditions: 1. preemption is off 2. __ARCH_WANT_INTERRUPTS_ON_CTXSW is defined 3. RT scheduling class 4. SMP system Sequence is as follows: 1.suppose current task is A. start schedule() 2.task A is enqueued pushable task at the entry of schedule() __schedule prev = rq->curr; ... put_prev_task put_prev_task_rt enqueue_pushable_task 4.pick the task B as next task. next = pick_next_task(rq); 3.rq->curr set to task B and context_switch is started. rq->curr = next; 4.At the entry of context_swtich, release this cpu's rq->lock. context_switch prepare_task_switch prepare_lock_switch raw_spin_unlock_irq(&rq->lock); 5.Shortly after rq->lock is released, interrupt is occurred and start IRQ context 6.try_to_wake_up() which called by ISR acquires rq->lock try_to_wake_up ttwu_remote rq = __task_rq_lock(p) ttwu_do_wakeup(rq, p, wake_flags); task_woken_rt 7.push_rt_task picks the task A which is enqueued before. task_woken_rt push_rt_tasks(rq) next_task = pick_next_pushable_task(rq) 8.At find_lock_lowest_rq(), If double_lock_balance() returns 0, lowest_rq can be the remote rq. (But,If preemption is on, double_lock_balance always return 1 and it does't happen.) push_rt_task find_lock_lowest_rq if (double_lock_balance(rq, lowest_rq)).. 9.find_lock_lowest_rq return the available rq. task A is migrated to the remote cpu/rq. push_rt_task ... deactivate_task(rq, next_task, 0); set_task_cpu(next_task, lowest_rq->cpu); activate_task(lowest_rq, next_task, 0); 10. But, task A is on irq context at this cpu. So, task A is scheduled by two cpus at the same time until restore from IRQ. Task A's stack is corrupted. To fix it, don't migrate an RT task if it's still running. Signed-off-by: Chanho Min Signed-off-by: Peter Zijlstra Acked-by: Steven Rostedt Cc: Link: http://lkml.kernel.org/r/CAOAMb1BHA=5fm7KTewYyke6u-8DP0iUuJMpgQw54vNeXFsGpoQ@mail.gmail.com Signed-off-by: Ingo Molnar --- kernel/sched/rt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 3640ebbb466b..f42ae7fb5ec5 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1587,6 +1587,11 @@ static int push_rt_task(struct rq *rq) if (!next_task) return 0; +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW + if (unlikely(task_running(rq, next_task))) + return 0; +#endif + retry: if (unlikely(next_task == rq->curr)) { WARN_ON(1); From a389d67cf9849aff1722ed73186a584e2196a873 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Fri, 27 Jan 2012 14:31:19 +0100 Subject: [PATCH 174/380] ALSA: HDA: Remove quirk for Asus N53Jq The user reports that he needs to add model=auto for audio to work properly. In fact, since node 0x15 is not even a pin node, the existing fixup is definitely wrong. Relevant information can be found in the buglink below. Cc: stable@kernel.org (3.2+) BugLink: https://bugs.launchpad.net/bugs/918254 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0db1dc49382b..a7f17becbd7c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5377,7 +5377,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", ALC269_FIXUP_AMIC), SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC), SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC), SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC), SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC), From 9998eb703490589c3e8f1bf09b15203156776edb Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 25 Jan 2012 13:47:40 -0500 Subject: [PATCH 175/380] Btrfs: fix reservations in btrfs_page_mkwrite Josef fixed btrfs_page_mkwrite to properly release reserved extents if there was an error. But if we fail to get a reservation and we fail to dirty the inode (for ENOSPC reasons), we'll end up trying to release a reservation we never had. This makes sure we only release if we were able to reserve. Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5977987abdb1..7405753ec5d7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6401,18 +6401,23 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) unsigned long zero_start; loff_t size; int ret; + int reserved = 0; u64 page_start; u64 page_end; ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); - if (!ret) + if (!ret) { ret = btrfs_update_time(vma->vm_file); + reserved = 1; + } if (ret) { if (ret == -ENOMEM) ret = VM_FAULT_OOM; else /* -ENOSPC, -EIO, etc */ ret = VM_FAULT_SIGBUS; - goto out; + if (reserved) + goto out; + goto out_noreserve; } ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */ @@ -6495,6 +6500,7 @@ out_unlock: unlock_page(page); out: btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE); +out_noreserve: return ret; } From 69e8f430e243d657c2053f097efebc2e2cd559f0 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 25 Jan 2012 00:13:20 -0500 Subject: [PATCH 176/380] xen/granttable: Disable grant v2 for HVM domains. As proper scaffolding for supporting error status is not yet implemented. BUG: unable to handle kernel NULL pointer dereference at 0000000000000400 IP: [] gnttab_end_foreign_access_ref_v2+0x29/0x40 PGD 32aa3067 PUD 32a87067 PMD 0 Oops: 0000 [#1] PREEMPT SMP CPU 0 Modules linked in: sg sr_mod cdrom ata_generic ata_piix libata scsi_mod xen_blkfront xen_netfront fb_sys_fops sysimgblt sysfillrect syscopyarea xen_kbdfront cmd Pid: 2307, comm: ip Not tainted 3.3.0-rc1 #1 Xen HVM domU RIP: 0010:[] [] gnttab_end_foreign_access_ref_v2+0x29/0x40 RSP: 0018:ffff88003be03d38 EFLAGS: 00010206 RAX: 0000000000000000 RBX: ffff880033210640 RCX: 0000000000000040 RDX: 0000000000002000 RSI: 0000000000000000 RDI: 0000000000000200 RBP: ffff88003be03d38 R08: 0000000000000101 R09: 0000000000000000 R10: dead000000100100 R11: 0000000000000000 R12: ffff88003be03e48 R13: 0000000000000001 R14: ffff880039461c00 R15: 0000000000000200 FS: 00007fb1f84ec700(0000) GS:ffff88003be00000(0000) knlGS:0000000000000000 ... Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/grant-table.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 1cd94daa71db..b4d4eac761db 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -948,9 +948,12 @@ static void gnttab_request_version(void) int rc; struct gnttab_set_version gsv; - gsv.version = 2; + if (xen_hvm_domain()) + gsv.version = 1; + else + gsv.version = 2; rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); - if (rc == 0) { + if (rc == 0 && gsv.version == 2) { grant_table_version = 2; gnttab_interface = &gnttab_v2_ops; } else if (grant_table_version == 2) { From e47e321a35c741ee41b67976f8c6a3a7a42bc5c0 Mon Sep 17 00:00:00 2001 From: Bernd Schubert Date: Fri, 20 Jan 2012 18:43:54 +0000 Subject: [PATCH 177/380] RDMA/core: Fix kernel panic by always initializing qp->usecnt We have just been investigating kernel panics related to cq->ibcq.event_handler() completion calls. The problem is that ib_destroy_qp() fails with -EBUSY. Further investigation revealed qp->usecnt is not initialized. This counter was introduced in linux-3.2 by commit 0e0ec7e0638e ("RDMA/core: Export ib_open_qp() to share XRC TGT QPs") but it only gets initialized for IB_QPT_XRC_TGT, but it is checked in ib_destroy_qp() for any QP type. Fix this by initializing qp->usecnt for every QP we create. Signed-off-by: Bernd Schubert Signed-off-by: Sven Breuner [ Initialize qp->usecnt in uverbs too. - Sean ] Signed-off-by: Sean Hefty Cc: Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 1 + drivers/infiniband/core/verbs.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index b930da4c0c63..4d27e4c3fe34 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1485,6 +1485,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, qp->event_handler = attr.event_handler; qp->qp_context = attr.qp_context; qp->qp_type = attr.qp_type; + atomic_set(&qp->usecnt, 0); atomic_inc(&pd->usecnt); atomic_inc(&attr.send_cq->usecnt); if (attr.recv_cq) diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 602b1bd723a9..575b78045aaf 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -421,6 +421,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, qp->uobject = NULL; qp->qp_type = qp_init_attr->qp_type; + atomic_set(&qp->usecnt, 0); if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) { qp->event_handler = __ib_shared_qp_event_handler; qp->qp_context = qp; @@ -430,7 +431,6 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, qp->xrcd = qp_init_attr->xrcd; atomic_inc(&qp_init_attr->xrcd->usecnt); INIT_LIST_HEAD(&qp->open_list); - atomic_set(&qp->usecnt, 0); real_qp = qp; qp = __ib_open_qp(real_qp, qp_init_attr->event_handler, From ef5352875a12a0a45be8bca29fc218a94786d920 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 26 Jan 2012 09:15:29 +0300 Subject: [PATCH 178/380] IB/ipath: Calling PTR_ERR() on right variable in create_file() "dentry" is a valid pointer. "*dentry" was intended. Signed-off-by: Dan Carpenter Acked-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index b7d4216db3c3..a4de9d58e9b4 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -89,7 +89,7 @@ static int create_file(const char *name, umode_t mode, error = ipathfs_mknod(parent->d_inode, *dentry, mode, fops, data); else - error = PTR_ERR(dentry); + error = PTR_ERR(*dentry); mutex_unlock(&parent->d_inode->i_mutex); return error; From 81f99dcc93226c7accfe5c4edad1749b8aebf7db Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Tue, 17 Jan 2012 10:17:30 -0600 Subject: [PATCH 179/380] RDMA/nes: Fix for sending MPA reject frame Set a reject flag, when sending MPA reject message to inform the peer that the application has rejected the connection. Signed-off-by: Tatyana Nikolova Signed-off-by: Faisal Latif Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_cm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 425065b36b8c..183f7ab120db 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -233,6 +233,7 @@ static int send_mpa_reject(struct nes_cm_node *cm_node) u8 *start_ptr = &start_addr; u8 **start_buff = &start_ptr; u16 buff_len = 0; + struct ietf_mpa_v1 *mpa_frame; skb = dev_alloc_skb(MAX_CM_BUFFER); if (!skb) { @@ -242,6 +243,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node) /* send an MPA reject frame */ cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY); + mpa_frame = (struct ietf_mpa_v1 *)*start_buff; + mpa_frame->flags |= IETF_MPA_FLAGS_REJECT; form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN); cm_node->state = NES_CM_STATE_FIN_WAIT1; From 7525c85be0e6d18596390e7e2b17a206cd9777f6 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 27 Jan 2012 09:54:30 -0800 Subject: [PATCH 180/380] RDMA/nes: Add missing rcu_read_unlock() in nes_addr_resolve_neigh() Make sure all exit paths from this function unlock everything. Reported-by: Bart Van Assche Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_cm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 183f7ab120db..271279cccad8 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1363,8 +1363,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi if (!memcmp(nesadapter->arp_table[arpindex].mac_addr, neigh->ha, ETH_ALEN)) { /* Mac address same as in nes_arp_table */ - ip_rt_put(rt); - return rc; + goto out; } nes_manage_arp_cache(nesvnic->netdev, @@ -1380,6 +1379,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi neigh_event_send(neigh, NULL); } } + +out: rcu_read_unlock(); ip_rt_put(rt); return rc; From 0f3696eb21ef39b7bb7ea7d0160e925904309281 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 9 Jan 2012 10:40:47 +0100 Subject: [PATCH 181/380] IB/qib: Use GFP_ATOMIC when locks are held alloc_dummy_hdrq() is called with locks held and thus should not use GFP_KERNEL. The semantic patch that makes this report is available in scripts/coccinelle/locks/call_kern.cocci. Signed-off-by: Julia Lawall Acked-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_iba6120.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 4f18e2d332df..d0c64d514813 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -2105,7 +2105,7 @@ static void alloc_dummy_hdrq(struct qib_devdata *dd) dd->cspec->dummy_hdrq = dma_alloc_coherent(&dd->pcidev->dev, dd->rcd[0]->rcvhdrq_size, &dd->cspec->dummy_hdrq_phys, - GFP_KERNEL | __GFP_COMP); + GFP_ATOMIC | __GFP_COMP); if (!dd->cspec->dummy_hdrq) { qib_devinfo(dd->pcidev, "Couldn't allocate dummy hdrq\n"); /* fallback to just 0'ing */ From b6bfefb0410dc49853bccd9673ead896d317c082 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Thu, 12 Jan 2012 21:29:59 -0500 Subject: [PATCH 182/380] IB/qib: Roll back PCIe tuning change Commit 8d4548f2b ("IB/qib: Default some module parameters optimally") introduced an issue with older root complexes. They cannot handle the pcie_caps of 0x51 (MaxReadReq 4096, MaxPayload=256). A typical diagnostic in this situation reported by syslog contains the text: [PCIe Poisoned TLP][Send DMA memory read] Restore the module paramter default to zero with will avoid any changes in the root complex. Reviewed-by: Mark Debbage Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_pcie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index f695061d688e..0fde788e1100 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -560,7 +560,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd) * BIOS may not set PCIe bus-utilization parameters for best performance. * Check and optionally adjust them to maximize our throughput. */ -static int qib_pcie_caps = 0x51; +static int qib_pcie_caps; module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO); MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)"); From 9ced69ca5296567033804950d8d2161f454c5012 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Tue, 10 Jan 2012 23:53:41 +0000 Subject: [PATCH 183/380] RDMA/ucma: Discard all events for new connections until accepted After reporting a new connection request to user space, the rdma_ucm will discard subsequent events until the user has associated a user space idenfier with the kernel cm_id. This is needed to avoid reporting a reject/disconnect event to the user for a request that they may not have processed. The user space identifier is set once the user tries to accept the connection request. However, the following race exists in ucma_accept(): ctx->uid = cmd.uid; ret = rdma_accept(ctx->cm_id, ...); Once ctx->uid has been set, new events may be reported to the user. While the above mentioned race is avoided, there is an issue that the user _may_ receive a reject/disconnect event if rdma_accept() fails, depending on when the event is processed. To simplify the use of rdma_accept(), discard all events unless rdma_accept() succeeds. This problem was discovered based on questions from Roland Dreier . Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/ucma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index b37b0c02a7b9..5034a87cc72d 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -808,9 +808,12 @@ static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf, return PTR_ERR(ctx); if (cmd.conn_param.valid) { - ctx->uid = cmd.uid; ucma_copy_conn_param(&conn_param, &cmd.conn_param); + mutex_lock(&file->mut); ret = rdma_accept(ctx->cm_id, &conn_param); + if (!ret) + ctx->uid = cmd.uid; + mutex_unlock(&file->mut); } else ret = rdma_accept(ctx->cm_id, NULL); From 94f622bdac82dd0542741382ea8c9359fd9c163b Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Fri, 6 Jan 2012 18:15:01 -0600 Subject: [PATCH 184/380] RDMA/nes: Fix fast memory registration length Zero high order word of fast memory registration (FMR) length field. FMR length field is 32 bits, so high word should always be zero. Signed-off-by: Tatyana Nikolova Signed-off-by: Donald Wood Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_verbs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 5095bc41c6cc..ba2eb002fd29 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -3427,6 +3427,8 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX, ib_wr->wr.fast_reg.length); + set_wqe_32bit_value(wqe->wqe_words, + NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0); set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX, ib_wr->wr.fast_reg.rkey); From 4a4b03f4efdcf9f4dd8ce68f305c5fb8ff8e56c4 Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Fri, 6 Jan 2012 18:17:19 -0600 Subject: [PATCH 185/380] RDMA/nes: Fix fast memory registration opcode Fix fast memory registration opcode in local invalidate completion. Signed-off-by: Tatyana Nikolova Signed-off-by: Donald Wood Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_verbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index ba2eb002fd29..3875365a284b 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -3726,7 +3726,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) entry->opcode = IB_WC_SEND; break; case NES_IWARP_SQ_OP_LOCINV: - entry->opcode = IB_WR_LOCAL_INV; + entry->opcode = IB_WC_LOCAL_INV; break; case NES_IWARP_SQ_OP_FAST_REG: entry->opcode = IB_WC_FAST_REG_MR; From 114395c61ad2eb5a7a5cd163fcadb2414e48245a Mon Sep 17 00:00:00 2001 From: UK KIM Date: Sat, 28 Jan 2012 01:52:22 +0900 Subject: [PATCH 186/380] ASoC: wm_hubs: fix wrong bits for LINEOUT2 N/P mixer Signed-off-by: UK KIM Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm_hubs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 9ccc416d8cbc..ea2672455d07 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -592,8 +592,8 @@ SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), }; static const struct snd_kcontrol_new line2n_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), +SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), +SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0), }; static const struct snd_kcontrol_new line2p_mix[] = { From 4dbc5d9f4f791df8a5879f4a655f517adc7f56d1 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 20 Jan 2012 16:16:59 +0800 Subject: [PATCH 187/380] virtio: fix typos of memory barriers Note: this fixes a bug introduced recently in 7b21e34fd1c272e3a8c3846168f2f6287a4cd72b. Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: Rusty Russell --- drivers/virtio/virtio_ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 79e1b292c030..78428a863b46 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -35,7 +35,7 @@ #define virtio_rmb(vq) \ do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0) #define virtio_wmb(vq) \ - do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0) + do { if ((vq)->weak_barriers) smp_wmb(); else wmb(); } while(0) #else /* We must force memory ordering even if guest is UP since host could be * running on another CPU, but SMP barriers are defined to barrier() in that From a72caae21803b74e04e2afda5e035f149d4ea118 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 20 Jan 2012 16:17:08 +0800 Subject: [PATCH 188/380] virtio: correct the memory barrier in virtqueue_kick_prepare() Use virtio_mb() to make sure the available index to be exposed before checking the the avail event. Otherwise we may get stale value of avail event in guest and never kick the host after. Note: this fixes a bug introduced by ee7cd8981e15bcb365fc762afe3fc47b8242f630. Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: Rusty Russell Cc: stable@kernel.org --- drivers/virtio/virtio_ring.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 78428a863b46..5aa43c3392a2 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -308,9 +308,9 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq) bool needs_kick; START_USE(vq); - /* Descriptors and available array need to be set before we expose the - * new available array entries. */ - virtio_wmb(vq); + /* We need to expose available array entries before checking avail + * event. */ + virtio_mb(vq); old = vq->vring.avail->idx - vq->num_added; new = vq->vring.avail->idx; From 13289d5f2b2ee73583e6c65c46a1e0cd48c3ddc0 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 28 Jan 2012 08:10:23 +1030 Subject: [PATCH 189/380] lguest: remove reference from Documentation/virtual/00-INDEX We're in tools/lguest now. Reported-by: Stephen Hemminger Signed-off-by: Rusty Russell --- Documentation/virtual/00-INDEX | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/virtual/00-INDEX b/Documentation/virtual/00-INDEX index 8e601991d91c..924bd462675e 100644 --- a/Documentation/virtual/00-INDEX +++ b/Documentation/virtual/00-INDEX @@ -4,8 +4,6 @@ Virtualization support in the Linux kernel. - this file. kvm/ - Kernel Virtual Machine. See also http://linux-kvm.org -lguest/ - - Extremely simple hypervisor for experimental/educational use. uml/ - User Mode Linux, builds/runs Linux kernel as a userspace program. virtio.txt From 5ee4433efe99b9f39f6eff5052a177bbcfe72cea Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 26 Jan 2012 14:02:55 +0000 Subject: [PATCH 190/380] netns: Fail conspicously if someone uses net_generic at an inappropriate time. By definition net_generic should never be called when it can return NULL. Fail conspicously with a BUG_ON to make it clear when people mess up that a NULL return should never happen. Recently there was a bug in the CAIF subsystem where it was registered with register_pernet_device instead of register_pernet_subsys. It was erroneously concluded that net_generic could validly return NULL and that net_assign_generic was buggy (when it was just inefficient). Hopefully this BUG_ON will prevent people to coming to similar erroneous conclusions in the futrue. Signed-off-by: Eric W. Biederman Tested-by: Sasha Levin Signed-off-by: David S. Miller --- include/net/netns/generic.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h index 3419bf5cd154..d55f43443335 100644 --- a/include/net/netns/generic.h +++ b/include/net/netns/generic.h @@ -41,6 +41,7 @@ static inline void *net_generic(const struct net *net, int id) ptr = ng->ptr[id - 1]; rcu_read_unlock(); + BUG_ON(!ptr); return ptr; } #endif From 8a8ee9aff6c3077dd9c2c7a77478e8ed362b96c6 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 26 Jan 2012 14:04:53 +0000 Subject: [PATCH 191/380] net caif: Register properly as a pernet subsystem. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit caif is a subsystem and as such it needs to register with register_pernet_subsys instead of register_pernet_device. Among other problems using register_pernet_device was resulting in net_generic being called before the caif_net structure was allocated. Which has been causing net_generic to fail with either BUG_ON's or by return NULL pointers. A more ugly problem that could be caused is packets in flight why the subsystem is shutting down. To remove confusion also remove the cruft cause by inappropriately trying to fix this bug. With the aid of the previous patch I have tested this patch and confirmed that using register_pernet_subsys makes the failure go away as it should. Signed-off-by: Eric W. Biederman Acked-by: Sjur Brændeland Tested-by: Sasha Levin Signed-off-by: David S. Miller --- net/caif/caif_dev.c | 22 ++-------------------- net/caif/cfcnfg.c | 1 - 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 673728add60b..82c57069415f 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -59,8 +59,6 @@ struct cfcnfg *get_cfcnfg(struct net *net) { struct caif_net *caifn; caifn = net_generic(net, caif_net_id); - if (!caifn) - return NULL; return caifn->cfg; } EXPORT_SYMBOL(get_cfcnfg); @@ -69,8 +67,6 @@ static struct caif_device_entry_list *caif_device_list(struct net *net) { struct caif_net *caifn; caifn = net_generic(net, caif_net_id); - if (!caifn) - return NULL; return &caifn->caifdevs; } @@ -99,8 +95,6 @@ static struct caif_device_entry *caif_device_alloc(struct net_device *dev) struct caif_device_entry *caifd; caifdevs = caif_device_list(dev_net(dev)); - if (!caifdevs) - return NULL; caifd = kzalloc(sizeof(*caifd), GFP_KERNEL); if (!caifd) @@ -120,8 +114,6 @@ static struct caif_device_entry *caif_get(struct net_device *dev) struct caif_device_entry_list *caifdevs = caif_device_list(dev_net(dev)); struct caif_device_entry *caifd; - if (!caifdevs) - return NULL; list_for_each_entry_rcu(caifd, &caifdevs->list, list) { if (caifd->netdev == dev) @@ -321,8 +313,6 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, struct caif_device_entry_list *caifdevs; caifdevs = caif_device_list(dev_net(dev)); - if (!cfg || !caifdevs) - return; caifd = caif_device_alloc(dev); if (!caifd) return; @@ -374,8 +364,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, cfg = get_cfcnfg(dev_net(dev)); caifdevs = caif_device_list(dev_net(dev)); - if (!cfg || !caifdevs) - return 0; caifd = caif_get(dev); if (caifd == NULL && dev->type != ARPHRD_CAIF) @@ -507,9 +495,6 @@ static struct notifier_block caif_device_notifier = { static int caif_init_net(struct net *net) { struct caif_net *caifn = net_generic(net, caif_net_id); - if (WARN_ON(!caifn)) - return -EINVAL; - INIT_LIST_HEAD(&caifn->caifdevs.list); mutex_init(&caifn->caifdevs.lock); @@ -527,9 +512,6 @@ static void caif_exit_net(struct net *net) caif_device_list(net); struct cfcnfg *cfg = get_cfcnfg(net); - if (!cfg || !caifdevs) - return; - rtnl_lock(); mutex_lock(&caifdevs->lock); @@ -569,7 +551,7 @@ static int __init caif_device_init(void) { int result; - result = register_pernet_device(&caif_net_ops); + result = register_pernet_subsys(&caif_net_ops); if (result) return result; @@ -582,7 +564,7 @@ static int __init caif_device_init(void) static void __exit caif_device_exit(void) { - unregister_pernet_device(&caif_net_ops); + unregister_pernet_subsys(&caif_net_ops); unregister_netdevice_notifier(&caif_device_notifier); dev_remove_pack(&caif_packet_type); } diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 598aafb4cb51..ba9cfd47778a 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -309,7 +309,6 @@ int caif_connect_client(struct net *net, struct caif_connect_request *conn_req, int err; struct cfctrl_link_param param; struct cfcnfg *cfg = get_cfcnfg(net); - caif_assert(cfg != NULL); rcu_read_lock(); err = caif_connect_req_to_link_param(cfg, conn_req, ¶m); From 96150606e2fb82d242c9e4a414e4e922849f7bf7 Mon Sep 17 00:00:00 2001 From: Prasad Joshi Date: Sat, 26 Nov 2011 11:00:47 +0530 Subject: [PATCH 192/380] logfs: update page reference count for pined pages LogFS sets PG_private flag to indicate a pined page. We assumed that marking a page as private is enough to ensure its existence. But instead it is necessary to hold a reference count to the page. The change resolves the following BUG BUG: Bad page state in process flush-253:16 pfn:6a6d0 page flags: 0x100000000000808(uptodate|private) Suggested-and-Acked-by: Joern Engel Signed-off-by: Prasad Joshi --- fs/logfs/readwrite.c | 29 ++++++++++++++++++++++------- fs/logfs/segment.c | 37 +++++++++++++++++++++++++++++-------- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 2ac4217b7901..6d663e8ea6da 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -560,8 +560,13 @@ static void inode_free_block(struct super_block *sb, struct logfs_block *block) static void indirect_free_block(struct super_block *sb, struct logfs_block *block) { - ClearPagePrivate(block->page); - block->page->private = 0; + struct page *page = block->page; + + if (PagePrivate(page)) { + ClearPagePrivate(page); + page_cache_release(page); + set_page_private(page, 0); + } __free_block(sb, block); } @@ -650,8 +655,11 @@ static void alloc_data_block(struct inode *inode, struct page *page) logfs_unpack_index(page->index, &bix, &level); block = __alloc_block(inode->i_sb, inode->i_ino, bix, level); block->page = page; + SetPagePrivate(page); - page->private = (unsigned long)block; + page_cache_get(page); + set_page_private(page, (unsigned long) block); + block->ops = &indirect_block_ops; } @@ -1901,8 +1909,11 @@ static void move_page_to_inode(struct inode *inode, struct page *page) li->li_block = block; block->page = NULL; - page->private = 0; - ClearPagePrivate(page); + if (PagePrivate(page)) { + ClearPagePrivate(page); + page_cache_release(page); + set_page_private(page, 0); + } } static void move_inode_to_page(struct page *page, struct inode *inode) @@ -1918,8 +1929,12 @@ static void move_inode_to_page(struct page *page, struct inode *inode) BUG_ON(PagePrivate(page)); block->ops = &indirect_block_ops; block->page = page; - page->private = (unsigned long)block; - SetPagePrivate(page); + + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + set_page_private(page, (unsigned long) block); + } block->inode = NULL; li->li_block = NULL; diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c index 9d5187353255..6aee6092860d 100644 --- a/fs/logfs/segment.c +++ b/fs/logfs/segment.c @@ -86,7 +86,11 @@ int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, BUG_ON(!page); /* FIXME: reserve a pool */ SetPageUptodate(page); memcpy(page_address(page) + offset, buf, copylen); - SetPagePrivate(page); + + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + } page_cache_release(page); buf += copylen; @@ -110,7 +114,10 @@ static void pad_partial_page(struct logfs_area *area) page = get_mapping_page(sb, index, 0); BUG_ON(!page); /* FIXME: reserve a pool */ memset(page_address(page) + offset, 0xff, len); - SetPagePrivate(page); + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + } page_cache_release(page); } } @@ -130,7 +137,10 @@ static void pad_full_pages(struct logfs_area *area) BUG_ON(!page); /* FIXME: reserve a pool */ SetPageUptodate(page); memset(page_address(page), 0xff, PAGE_CACHE_SIZE); - SetPagePrivate(page); + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + } page_cache_release(page); index++; no_indizes--; @@ -485,8 +495,12 @@ static void move_btree_to_page(struct inode *inode, struct page *page, mempool_free(item, super->s_alias_pool); } block->page = page; - SetPagePrivate(page); - page->private = (unsigned long)block; + + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + set_page_private(page, (unsigned long) block); + } block->ops = &indirect_block_ops; initialize_block_counters(page, block, data, 0); } @@ -536,8 +550,12 @@ void move_page_to_btree(struct page *page) list_add(&item->list, &block->item_list); } block->page = NULL; - ClearPagePrivate(page); - page->private = 0; + + if (PagePrivate(page)) { + ClearPagePrivate(page); + page_cache_release(page); + set_page_private(page, 0); + } block->ops = &btree_block_ops; err = alias_tree_insert(block->sb, block->ino, block->bix, block->level, block); @@ -702,7 +720,10 @@ void freeseg(struct super_block *sb, u32 segno) page = find_get_page(mapping, ofs >> PAGE_SHIFT); if (!page) continue; - ClearPagePrivate(page); + if (PagePrivate(page)) { + ClearPagePrivate(page); + page_cache_release(page); + } page_cache_release(page); } } From 934eed395d201bf0901ca0c0cc3703b18729d0ce Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Sun, 20 Nov 2011 22:29:01 +0530 Subject: [PATCH 193/380] logfs: Prevent memory corruption This is a bad one. I wonder whether we were so far protected by no_free_segments(sb) usually being smaller than LOGFS_NO_AREAS. Found by Dan Carpenter using smatch. Signed-off-by: Joern Engel Signed-off-by: Prasad Joshi --- fs/logfs/gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c index caa4419285dc..d4efb061bdc5 100644 --- a/fs/logfs/gc.c +++ b/fs/logfs/gc.c @@ -367,7 +367,7 @@ static struct gc_candidate *get_candidate(struct super_block *sb) int i, max_dist; struct gc_candidate *cand = NULL, *this; - max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS); + max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1); for (i = max_dist; i >= 0; i--) { this = first_in_list(&super->s_low_list[i]); From 13ced29cb28996a9bc4f68e43ff0c57eafdb1e21 Mon Sep 17 00:00:00 2001 From: Prasad Joshi Date: Sat, 28 Jan 2012 11:36:06 +0530 Subject: [PATCH 194/380] logfs: take write mutex lock during fsync and sync LogFS uses super->s_write_mutex while writing data to disk. Taking the same mutex lock in sync and fsync code path solves the following BUG: ------------[ cut here ]------------ kernel BUG at /home/prasad/logfs/dev_bdev.c:134! Pid: 2387, comm: flush-253:16 Not tainted 3.0.0+ #4 Bochs Bochs RIP: 0010:[] [] bdev_writeseg+0x25d/0x270 [logfs] Call Trace: [] logfs_open_area+0x91/0x150 [logfs] [] ? find_level.clone.9+0x62/0x100 [] __logfs_segment_write.clone.20+0x5c/0x190 [logfs] [] ? mempool_kmalloc+0x15/0x20 [] ? mempool_alloc+0x53/0x130 [] logfs_segment_write+0x1d4/0x230 [logfs] [] logfs_write_i0+0x12e/0x190 [logfs] [] __logfs_write_rec+0x140/0x220 [logfs] [] logfs_write_rec+0x64/0xd0 [logfs] [] __logfs_write_buf+0x106/0x110 [logfs] [] logfs_write_buf+0x4e/0x80 [logfs] [] __logfs_writepage+0x23/0x80 [logfs] [] logfs_writepage+0xdc/0x110 [logfs] [] __writepage+0x17/0x40 [] write_cache_pages+0x208/0x4f0 [] ? set_page_dirty+0x70/0x70 [] generic_writepages+0x4a/0x70 [] do_writepages+0x21/0x40 [] writeback_single_inode+0x101/0x250 [] writeback_sb_inodes+0xed/0x1c0 [] writeback_inodes_wb+0x7b/0x1e0 [] wb_writeback+0x4c3/0x530 [] ? sub_preempt_count+0x9d/0xd0 [] wb_do_writeback+0xdb/0x290 [] ? sub_preempt_count+0x9d/0xd0 [] ? _raw_spin_unlock_irqrestore+0x18/0x40 [] ? del_timer+0x8a/0x120 [] bdi_writeback_thread+0x8c/0x2e0 [] ? wb_do_writeback+0x290/0x290 [] kthread+0x96/0xa0 [] kernel_thread_helper+0x4/0x10 [] ? kthread_worker_fn+0x190/0x190 [] ? gs_change+0xb/0xb RIP [] bdev_writeseg+0x25d/0x270 [logfs] ---[ end trace 0211ad60a57657c4 ]--- Reviewed-by: Joern Engel Signed-off-by: Prasad Joshi --- fs/logfs/file.c | 2 ++ fs/logfs/inode.c | 2 ++ fs/logfs/logfs.h | 2 ++ fs/logfs/readwrite.c | 6 ++---- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/logfs/file.c b/fs/logfs/file.c index b548c87a86f1..3886cded283c 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c @@ -230,7 +230,9 @@ int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) return ret; mutex_lock(&inode->i_mutex); + logfs_get_wblocks(sb, NULL, WF_LOCK); logfs_write_anchor(sb); + logfs_put_wblocks(sb, NULL, WF_LOCK); mutex_unlock(&inode->i_mutex); return 0; diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 7e441ad5f792..388d7c5a7bed 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c @@ -364,7 +364,9 @@ static void logfs_init_once(void *_li) static int logfs_sync_fs(struct super_block *sb, int wait) { + logfs_get_wblocks(sb, NULL, WF_LOCK); logfs_write_anchor(sb); + logfs_put_wblocks(sb, NULL, WF_LOCK); return 0; } diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 398ecff6e548..bb4340850c1b 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h @@ -577,6 +577,8 @@ void initialize_block_counters(struct page *page, struct logfs_block *block, __be64 *array, int page_is_empty); int logfs_exist_block(struct inode *inode, u64 bix); int get_page_reserve(struct inode *inode, struct page *page); +void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock); +void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock); extern struct logfs_block_ops indirect_block_ops; /* segment.c */ diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 6d663e8ea6da..7b10e8aecced 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -244,8 +244,7 @@ static void preunlock_page(struct super_block *sb, struct page *page, int lock) * is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked * in addition to PG_locked. */ -static void logfs_get_wblocks(struct super_block *sb, struct page *page, - int lock) +void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock) { struct logfs_super *super = logfs_super(sb); @@ -260,8 +259,7 @@ static void logfs_get_wblocks(struct super_block *sb, struct page *page, } } -static void logfs_put_wblocks(struct super_block *sb, struct page *page, - int lock) +void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock) { struct logfs_super *super = logfs_super(sb); From ecfd890991a26e70547e025673580923a004c5e4 Mon Sep 17 00:00:00 2001 From: Prasad Joshi Date: Sun, 30 Oct 2011 22:15:32 +0530 Subject: [PATCH 195/380] logfs: set superblock shutdown flag after generic sb shutdown While unmounting the file system LogFS calls generic_shutdown_super. The function does file system independent superblock shutdown. However, it might result in call file system specific inode eviction. LogFS marks FS shutting down by setting bit LOGFS_SB_FLAG_SHUTDOWN in super->s_flags. Since, inode eviction might call truncate on inode, following BUG is observed when file system is unmounted: ------------[ cut here ]------------ kernel BUG at /home/prasad/logfs/segment.c:362! invalid opcode: 0000 [#1] PREEMPT SMP CPU 3 Modules linked in: logfs binfmt_misc ppdev virtio_blk parport_pc lp parport psmouse floppy virtio_pci serio_raw virtio_ring virtio Pid: 1933, comm: umount Not tainted 3.0.0+ #4 Bochs Bochs RIP: 0010:[] [] logfs_segment_write+0x211/0x230 [logfs] RSP: 0018:ffff880062d7b9e8 EFLAGS: 00010202 RAX: 000000000000000e RBX: ffff88006eca9000 RCX: 0000000000000000 RDX: ffff88006fd87c40 RSI: ffffea00014ff468 RDI: ffff88007b68e000 RBP: ffff880062d7ba48 R08: 8000000020451430 R09: 0000000000000000 R10: dead000000100100 R11: 0000000000000000 R12: ffff88006fd87c40 R13: ffffea00014ff468 R14: ffff88005ad0a460 R15: 0000000000000000 FS: 00007f25d50ea760(0000) GS:ffff88007fd80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000d05e48 CR3: 0000000062c72000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process umount (pid: 1933, threadinfo ffff880062d7a000, task ffff880070b44500) Stack: ffff880062d7ba38 ffff88005ad0a508 0000000000001000 0000000000000000 8000000020451430 ffffea00014ff468 ffff880062d7ba48 ffff88005ad0a460 ffff880062d7bad8 ffffea00014ff468 ffff88006fd87c40 0000000000000000 Call Trace: [] logfs_write_i0+0x12e/0x190 [logfs] [] __logfs_write_rec+0x140/0x220 [logfs] [] __logfs_write_rec+0xf2/0x220 [logfs] [] logfs_write_rec+0x64/0xd0 [logfs] [] __logfs_write_buf+0x106/0x110 [logfs] [] logfs_write_buf+0x4e/0x80 [logfs] [] __logfs_write_inode+0x98/0x110 [logfs] [] logfs_truncate+0x54/0x290 [logfs] [] logfs_evict_inode+0xdc/0x190 [logfs] [] evict+0x85/0x170 [] iput+0xe6/0x1b0 [] shrink_dcache_for_umount_subtree+0x218/0x280 [] shrink_dcache_for_umount+0x51/0x90 [] generic_shutdown_super+0x2c/0x100 [] logfs_kill_sb+0x57/0xf0 [logfs] [] deactivate_locked_super+0x45/0x70 [] deactivate_super+0x4a/0x70 [] mntput_no_expire+0xa4/0xf0 [] sys_umount+0x6f/0x380 [] system_call_fastpath+0x16/0x1b Code: 55 c8 49 8d b6 a8 00 00 00 45 89 f9 45 89 e8 4c 89 e1 4c 89 55 b8 c7 04 24 00 00 00 00 e8 68 fc ff ff 4c 8b 55 b8 e9 3c ff ff ff <0f> 0b 0f 0b c7 45 c0 00 00 00 00 e9 44 fe ff ff 66 66 66 66 66 RIP [] logfs_segment_write+0x211/0x230 [logfs] RSP ---[ end trace fe6b040cea952290 ]--- Therefore, move super->s_flags setting after the fs-indenpendent work has been finished. Reviewed-by: Joern Engel Signed-off-by: Prasad Joshi --- fs/logfs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/logfs/super.c b/fs/logfs/super.c index e795c234ea33..f9b7a30b00a3 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c @@ -491,9 +491,9 @@ static void logfs_kill_sb(struct super_block *sb) * From this point on alias entries are simply dropped - and any * writes to the object store are considered bugs. */ - super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN; log_super("LogFS: Now in shutdown\n"); generic_shutdown_super(sb); + super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN; BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes); From 0bd90387ed5a8abbcf43391b480efdc211721cfe Mon Sep 17 00:00:00 2001 From: Prasad Joshi Date: Sun, 2 Oct 2011 23:46:51 +0530 Subject: [PATCH 196/380] logfs: Propagate page parameter to __logfs_write_inode During GC LogFS has to rewrite each valid block to a separate segment. Rewrite operation reads data from an old segment and writes it to a newly allocated segment. Since every write operation changes data block pointers maintained in inode, inode should also be rewritten. In GC path to avoid AB-BA deadlock LogFS marks a page with PG_pre_locked in addition to locking the page (PG_locked). The page lock is ignored iff the page is pre-locked. LogFS uses a special file called segment file. The segment file maintains an 8 bytes entry for every segment. It keeps track of erase count, level etc. for every segment. Bad things happen with a segment belonging to the segment file is GCed ------------[ cut here ]------------ kernel BUG at /home/prasad/logfs/readwrite.c:297! invalid opcode: 0000 [#1] SMP Modules linked in: logfs joydev usbhid hid psmouse e1000 i2c_piix4 serio_raw [last unloaded: logfs] Pid: 20161, comm: mount Not tainted 3.1.0-rc3+ #3 innotek GmbH VirtualBox EIP: 0060:[] EFLAGS: 00010292 CPU: 0 EIP is at logfs_lock_write_page+0x6a/0x70 [logfs] EAX: 00000027 EBX: f73f5b20 ECX: c16007c8 EDX: 00000094 ESI: 00000000 EDI: e59be6e4 EBP: c7337b28 ESP: c7337b18 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Process mount (pid: 20161, ti=c7336000 task=eb323f70 task.ti=c7336000) Stack: f8099a3d c7337b24 f73f5b20 00001002 c7337b50 f8091f6d f8099a4d f80994e4 00000003 00000000 c7337b68 00000000 c67e4400 00001000 c7337b80 f80935e5 00000000 00000000 00000000 00000000 e1fcf000 0000000f e59be618 c70bf900 Call Trace: [] logfs_get_write_page.clone.16+0xdd/0x100 [logfs] [] logfs_mod_segment_entry+0x55/0x110 [logfs] [] logfs_get_segment_entry+0x1d/0x20 [logfs] [] ? logfs_cleanup_journal+0x50/0x50 [logfs] [] ostore_get_erase_count+0x1b/0x40 [logfs] [] logfs_open_area+0xc8/0x150 [logfs] [] ? kmemleak_alloc+0x2c/0x60 [] __logfs_segment_write.clone.16+0x4e/0x1b0 [logfs] [] ? mempool_kmalloc+0x13/0x20 [] ? mempool_kmalloc+0x13/0x20 [] logfs_segment_write+0x17f/0x1d0 [logfs] [] logfs_write_i0+0x11c/0x180 [logfs] [] logfs_write_direct+0x45/0x90 [logfs] [] __logfs_write_buf+0xbd/0xf0 [logfs] [] ? kmap_atomic_prot+0x4e/0xe0 [] logfs_write_buf+0x3b/0x60 [logfs] [] __logfs_write_inode+0xa9/0x110 [logfs] [] logfs_rewrite_block+0xc0/0x110 [logfs] [] ? get_mapping_page+0x10/0x60 [logfs] [] ? logfs_load_object_aliases+0x2e0/0x2f0 [logfs] [] logfs_gc_segment+0x2ad/0x310 [logfs] [] __logfs_gc_once+0x4a/0x80 [logfs] [] logfs_gc_pass+0x683/0x6a0 [logfs] [] logfs_mount+0x5a9/0x680 [logfs] [] mount_fs+0x21/0xd0 [] ? __alloc_percpu+0xf/0x20 [] ? alloc_vfsmnt+0xb1/0x130 [] vfs_kern_mount+0x4b/0xa0 [] do_kern_mount+0x3e/0xe0 [] do_mount+0x34d/0x670 [] ? strndup_user+0x49/0x70 [] sys_mount+0x6b/0xa0 [] syscall_call+0x7/0xb Code: f8 e8 8b 93 39 c9 8b 45 f8 3e 0f ba 28 00 19 d2 85 d2 74 ca eb d0 0f 0b 8d 45 fc 89 44 24 04 c7 04 24 3d 9a 09 f8 e8 09 92 39 c9 <0f> 0b 8d 74 26 00 55 89 e5 3e 8d 74 26 00 8b 10 80 e6 01 74 09 EIP: [] logfs_lock_write_page+0x6a/0x70 [logfs] SS:ESP 0068:c7337b18 ---[ end trace 96e67d5b3aa3d6ca ]--- The patch passes locked page to __logfs_write_inode. It calls function logfs_get_wblocks() to pre-lock the page. This ensures any further attempts to lock the page are ignored (esp from get_erase_count). Acked-by: Joern Engel Signed-off-by: Prasad Joshi --- fs/logfs/dir.c | 2 +- fs/logfs/inode.c | 2 +- fs/logfs/logfs.h | 2 +- fs/logfs/readwrite.c | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index b7d7f67cee5a..b6404898da83 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c @@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd, static int write_inode(struct inode *inode) { - return __logfs_write_inode(inode, WF_LOCK); + return __logfs_write_inode(inode, NULL, WF_LOCK); } static s64 dir_seek_data(struct inode *inode, s64 pos) diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 388d7c5a7bed..7c42c132c177 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c @@ -287,7 +287,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc) if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN) return 0; - ret = __logfs_write_inode(inode, flags); + ret = __logfs_write_inode(inode, NULL, flags); LOGFS_BUG_ON(ret, inode->i_sb); return ret; } diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index bb4340850c1b..0dec29887a8a 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h @@ -528,7 +528,7 @@ void logfs_destroy_inode_cache(void); void logfs_set_blocks(struct inode *inode, u64 no); /* these logically belong into inode.c but actually reside in readwrite.c */ int logfs_read_inode(struct inode *inode); -int __logfs_write_inode(struct inode *inode, long flags); +int __logfs_write_inode(struct inode *inode, struct page *, long flags); void logfs_evict_inode(struct inode *inode); /* journal.c */ diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 7b10e8aecced..88284c67ba97 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -422,7 +422,7 @@ static void inode_write_block(struct logfs_block *block) if (inode->i_ino == LOGFS_INO_MASTER) logfs_write_anchor(inode->i_sb); else { - ret = __logfs_write_inode(inode, 0); + ret = __logfs_write_inode(inode, NULL, 0); /* see indirect_write_block comment */ BUG_ON(ret); } @@ -1629,7 +1629,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs, if (inode->i_ino == LOGFS_INO_MASTER) logfs_write_anchor(inode->i_sb); else { - err = __logfs_write_inode(inode, flags); + err = __logfs_write_inode(inode, page, flags); } } } @@ -1879,7 +1879,7 @@ int logfs_truncate(struct inode *inode, u64 target) logfs_get_wblocks(sb, NULL, 1); err = __logfs_truncate(inode, size); if (!err) - err = __logfs_write_inode(inode, 0); + err = __logfs_write_inode(inode, NULL, 0); logfs_put_wblocks(sb, NULL, 1); } @@ -2119,14 +2119,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec) ec_level); } -int __logfs_write_inode(struct inode *inode, long flags) +int __logfs_write_inode(struct inode *inode, struct page *page, long flags) { struct super_block *sb = inode->i_sb; int ret; - logfs_get_wblocks(sb, NULL, flags & WF_LOCK); + logfs_get_wblocks(sb, page, flags & WF_LOCK); ret = do_write_inode(inode); - logfs_put_wblocks(sb, NULL, flags & WF_LOCK); + logfs_put_wblocks(sb, page, flags & WF_LOCK); return ret; } From 756ccb3c351e425ad5544ff1a92cfe6bec83b904 Mon Sep 17 00:00:00 2001 From: Prasad Joshi Date: Tue, 13 Sep 2011 23:04:11 +0530 Subject: [PATCH 197/380] MAINTAINERS: Add Prasad Joshi in LogFS maintiners Acked-by: Joern Engel Signed-off-by: Prasad Joshi --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0e7a80aefa0c..ce7029b79cf5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4116,6 +4116,7 @@ F: fs/partitions/ldm.* LogFS M: Joern Engel +M: Prasad Joshi L: logfs@logfs.org W: logfs.org S: Maintained From 6c69494f6b442834f26377e02d43fc8e1272221d Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Mon, 12 Sep 2011 21:09:16 +0530 Subject: [PATCH 198/380] logfs: remove useless BUG_ON It prevents write sizes >4k. Signed-off-by: Joern Engel --- fs/logfs/journal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c index 9da29706f91c..1e1c369df22b 100644 --- a/fs/logfs/journal.c +++ b/fs/logfs/journal.c @@ -612,7 +612,6 @@ static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type, if (len == 0) return logfs_write_header(super, header, 0, type); - BUG_ON(len > sb->s_blocksize); compr_len = logfs_compress(buf, data, len, sb->s_blocksize); if (compr_len < 0 || type == JE_ANCHOR) { memcpy(data, buf, len); From 1bcceaff8cbe5e5698ccf1015c9a938aa72718c4 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Fri, 5 Aug 2011 11:18:19 +0200 Subject: [PATCH 199/380] logfs: Free areas before calling generic_shutdown_super() Or hit an assertion in map_invalidatepage() instead. Signed-off-by: Joern Engel --- fs/logfs/logfs.h | 1 + fs/logfs/segment.c | 14 ++++++++++---- fs/logfs/super.c | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 0dec29887a8a..59ed32cd62d1 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h @@ -596,6 +596,7 @@ int logfs_init_mapping(struct super_block *sb); void logfs_sync_area(struct logfs_area *area); void logfs_sync_segments(struct super_block *sb); void freeseg(struct super_block *sb, u32 segno); +void free_areas(struct super_block *sb); /* area handling */ int logfs_init_areas(struct super_block *sb); diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c index 6aee6092860d..ab798ed1cc88 100644 --- a/fs/logfs/segment.c +++ b/fs/logfs/segment.c @@ -862,6 +862,16 @@ static void free_area(struct logfs_area *area) kfree(area); } +void free_areas(struct super_block *sb) +{ + struct logfs_super *super = logfs_super(sb); + int i; + + for_each_area(i) + free_area(super->s_area[i]); + free_area(super->s_journal_area); +} + static struct logfs_area *alloc_area(struct super_block *sb) { struct logfs_area *area; @@ -944,10 +954,6 @@ err: void logfs_cleanup_areas(struct super_block *sb) { struct logfs_super *super = logfs_super(sb); - int i; btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias); - for_each_area(i) - free_area(super->s_area[i]); - free_area(super->s_journal_area); } diff --git a/fs/logfs/super.c b/fs/logfs/super.c index f9b7a30b00a3..c9ee7f5d1caf 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c @@ -486,6 +486,7 @@ static void logfs_kill_sb(struct super_block *sb) /* Alias entries slow down mount, so evict as many as possible */ sync_filesystem(sb); logfs_write_anchor(sb); + free_areas(sb); /* * From this point on alias entries are simply dropped - and any From bbe01387129f76fa4bec17904eb14c4bdc3c179f Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Fri, 5 Aug 2011 11:13:30 +0200 Subject: [PATCH 200/380] logfs: Grow inode in delete path Can be necessary if an inode gets deleted (through -ENOSPC) before being written. Might be better to move this into logfs_write_rec(), but for now go with the stupid&safe patch. Signed-off-by: Joern Engel --- fs/logfs/readwrite.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 88284c67ba97..4153e65b0148 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -1576,11 +1576,15 @@ int logfs_write_buf(struct inode *inode, struct page *page, long flags) static int __logfs_delete(struct inode *inode, struct page *page) { long flags = WF_DELETE; + int err; inode->i_ctime = inode->i_mtime = CURRENT_TIME; if (page->index < I0_BLOCKS) return logfs_write_direct(inode, page, flags); + err = grow_inode(inode, page->index, 0); + if (err) + return err; return logfs_write_rec(inode, page, page->index, 0, flags); } From f2933e86ad93a8d1287079d59e67afd6f4166a9d Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Fri, 5 Aug 2011 11:09:55 +0200 Subject: [PATCH 201/380] Logfs: Allow NULL block_isbad() methods Not all mtd drivers define block_isbad(). Let's assume no bad blocks instead of refusing to mount. Signed-off-by: Joern Engel --- fs/logfs/dev_mtd.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c index 339e17e9133d..d054d7e975ca 100644 --- a/fs/logfs/dev_mtd.c +++ b/fs/logfs/dev_mtd.c @@ -150,14 +150,13 @@ static struct page *mtd_find_first_sb(struct super_block *sb, u64 *ofs) filler_t *filler = mtd_readpage; struct mtd_info *mtd = super->s_mtd; - if (!mtd->block_isbad) - return NULL; - *ofs = 0; - while (mtd->block_isbad(mtd, *ofs)) { - *ofs += mtd->erasesize; - if (*ofs >= mtd->size) - return NULL; + if (mtd->block_isbad) { + while (mtd->block_isbad(mtd, *ofs)) { + *ofs += mtd->erasesize; + if (*ofs >= mtd->size) + return NULL; + } } BUG_ON(*ofs & ~PAGE_MASK); return read_cache_page(mapping, *ofs >> PAGE_SHIFT, filler, sb); @@ -170,14 +169,13 @@ static struct page *mtd_find_last_sb(struct super_block *sb, u64 *ofs) filler_t *filler = mtd_readpage; struct mtd_info *mtd = super->s_mtd; - if (!mtd->block_isbad) - return NULL; - *ofs = mtd->size - mtd->erasesize; - while (mtd->block_isbad(mtd, *ofs)) { - *ofs -= mtd->erasesize; - if (*ofs <= 0) - return NULL; + if (mtd->block_isbad) { + while (mtd->block_isbad(mtd, *ofs)) { + *ofs -= mtd->erasesize; + if (*ofs <= 0) + return NULL; + } } *ofs = *ofs + mtd->erasesize - 0x1000; BUG_ON(*ofs & ~PAGE_MASK); From d0caf292505d051b1026e85faf3a85e907566f31 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 28 Jan 2012 13:52:46 +0300 Subject: [PATCH 202/380] x86/dumpstack: Remove unneeded check in dump_trace() Smatch complains that we have some inconsistent NULL checking. If "task" were NULL then it would lead to a NULL dereference later. We can remove this test because earlier on in the function we have: if (!task) task = current; Signed-off-by: Dan Carpenter Acked-by: Frederic Weisbecker Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Clemens Ladisch Link: http://lkml.kernel.org/r/20120128105246.GA25092@elgon.mountain Signed-off-by: Ingo Molnar --- arch/x86/kernel/dumpstack_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 6d728d9284bd..af7785ff5aa0 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -129,7 +129,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (!stack) { if (regs) stack = (unsigned long *)regs->sp; - else if (task && task != current) + else if (task != current) stack = (unsigned long *)task->thread.sp; else stack = &dummy; From f7f5ef0afdcca69fb02ded1763c28eca74e6b54d Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Sat, 28 Jan 2012 19:35:24 +0000 Subject: [PATCH 203/380] drivers/video: compile fixes for fsl-diu-fb.c Fix a compiler errors introduced in: commit ddd3d905436b572ebadc09dcf2d12ca5b37020a0 Author: Timur Tabi drivers/video: fsl-diu-fb: merge all allocated data into one block Signed-off-by: Michael Neuling Acked-by: Timur Tabi Signed-off-by: Florian Tobias Schandinat --- drivers/video/fsl-diu-fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index acf292bfba02..6af3f16754f0 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -1432,7 +1432,7 @@ static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state) struct fsl_diu_data *data; data = dev_get_drvdata(&ofdev->dev); - disable_lcdc(data->fsl_diu_info[0]); + disable_lcdc(data->fsl_diu_info); return 0; } @@ -1442,7 +1442,7 @@ static int fsl_diu_resume(struct platform_device *ofdev) struct fsl_diu_data *data; data = dev_get_drvdata(&ofdev->dev); - enable_lcdc(data->fsl_diu_info[0]); + enable_lcdc(data->fsl_diu_info); return 0; } From 7bc1dc7174d06104fde069a3b5aef1c5b902a5c9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 27 Jan 2012 15:58:33 +0300 Subject: [PATCH 204/380] intelfb: remove some dead code The goto on the line before means the return is unreachable. The goto also returns -ENODEV so no changes are needed there. Signed-off-by: Dan Carpenter Signed-off-by: Florian Tobias Schandinat --- drivers/video/intelfb/intelfbdrv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 5ba399991050..a5947c94145f 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -529,7 +529,6 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev, if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) { ERR_MSG("Could not allocate cmap for intelfb_info.\n"); goto err_out_cmap; - return -ENODEV; } dinfo = info->par; From 9f1065032ceb7e86c7c9f16bb86518857e88a172 Mon Sep 17 00:00:00 2001 From: Hubert Feurstein Date: Mon, 9 Jan 2012 17:23:57 +0100 Subject: [PATCH 205/380] atmel_lcdfb: fix usage of CONTRAST_CTR in suspend/resume An error was existing in the saving of CONTRAST_CTR register across suspend/resume. Signed-off-by: Hubert Feurstein Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Cc: stable Signed-off-by: Florian Tobias Schandinat --- drivers/video/atmel_lcdfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 0d7b20d4285d..e40c00f2c2ba 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -1108,7 +1108,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg) */ lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); - sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); + sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR); lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); if (sinfo->atmel_lcdfb_power_control) sinfo->atmel_lcdfb_power_control(0); From 6edf3c30af01854c416f8654d3d5d2652470afd4 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 26 Jan 2012 15:59:00 -0500 Subject: [PATCH 206/380] hwmon: (sht15) fix bad error code When no platform data was supplied, returned error code was 0. Signed-off-by: Vivien Didelot Cc: stable@vger.kernel.org # 2.6.32+ Signed-off-by: Guenter Roeck --- drivers/hwmon/sht15.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 6ddeae049058..91fdd1fe18b0 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -883,7 +883,7 @@ static int sht15_invalidate_voltage(struct notifier_block *nb, static int __devinit sht15_probe(struct platform_device *pdev) { - int ret = 0; + int ret; struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL); u8 status = 0; @@ -901,6 +901,7 @@ static int __devinit sht15_probe(struct platform_device *pdev) init_waitqueue_head(&data->wait_queue); if (pdev->dev.platform_data == NULL) { + ret = -EINVAL; dev_err(&pdev->dev, "no platform data supplied\n"); goto err_free_data; } From 181e9bdef37bfcaa41f3ab6c948a2a0d60a268b5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 29 Jan 2012 20:35:52 +0100 Subject: [PATCH 207/380] PM / Hibernate: Fix s2disk regression related to freezing workqueues Commit 2aede851ddf08666f68ffc17be446420e9d2a056 PM / Hibernate: Freeze kernel threads after preallocating memory introduced a mechanism by which kernel threads were frozen after the preallocation of hibernate image memory to avoid problems with frozen kernel threads not responding to memory freeing requests. However, it overlooked the s2disk code path in which the SNAPSHOT_CREATE_IMAGE ioctl was run directly after SNAPSHOT_FREE, which caused freeze_workqueues_begin() to BUG(), because it saw that worqueues had been already frozen. Although in principle this issue might be addressed by removing the relevant BUG_ON() from freeze_workqueues_begin(), that would reintroduce the very problem that commit 2aede851ddf08666f68ffc17be4 attempted to avoid into that particular code path. For this reason, to fix the issue at hand, introduce thaw_kernel_threads() and make the SNAPSHOT_FREE ioctl execute it. Special thanks to Srivatsa S. Bhat for detailed analysis of the problem. Reported-and-tested-by: Jiri Slaby Signed-off-by: Rafael J. Wysocki Acked-by: Srivatsa S. Bhat Cc: stable@kernel.org --- include/linux/freezer.h | 2 ++ kernel/power/process.c | 19 +++++++++++++++++++ kernel/power/user.c | 9 +++++++++ 3 files changed, 30 insertions(+) diff --git a/include/linux/freezer.h b/include/linux/freezer.h index 0ab54e16a91f..d09af4b67cf1 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -39,6 +39,7 @@ extern bool __refrigerator(bool check_kthr_stop); extern int freeze_processes(void); extern int freeze_kernel_threads(void); extern void thaw_processes(void); +extern void thaw_kernel_threads(void); static inline bool try_to_freeze(void) { @@ -174,6 +175,7 @@ static inline bool __refrigerator(bool check_kthr_stop) { return false; } static inline int freeze_processes(void) { return -ENOSYS; } static inline int freeze_kernel_threads(void) { return -ENOSYS; } static inline void thaw_processes(void) {} +static inline void thaw_kernel_threads(void) {} static inline bool try_to_freeze(void) { return false; } diff --git a/kernel/power/process.c b/kernel/power/process.c index 77274c9ba2f1..eeca00311f39 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -188,3 +188,22 @@ void thaw_processes(void) printk("done.\n"); } +void thaw_kernel_threads(void) +{ + struct task_struct *g, *p; + + pm_nosig_freezing = false; + printk("Restarting kernel threads ... "); + + thaw_workqueues(); + + read_lock(&tasklist_lock); + do_each_thread(g, p) { + if (p->flags & (PF_KTHREAD | PF_WQ_WORKER)) + __thaw_task(p); + } while_each_thread(g, p); + read_unlock(&tasklist_lock); + + schedule(); + printk("done.\n"); +} diff --git a/kernel/power/user.c b/kernel/power/user.c index 6b1ab7a88522..e5a21a857302 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -274,6 +274,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, swsusp_free(); memset(&data->handle, 0, sizeof(struct snapshot_handle)); data->ready = 0; + /* + * It is necessary to thaw kernel threads here, because + * SNAPSHOT_CREATE_IMAGE may be invoked directly after + * SNAPSHOT_FREE. In that case, if kernel threads were not + * thawed, the preallocation of memory carried out by + * hibernation_snapshot() might run into problems (i.e. it + * might fail or even deadlock). + */ + thaw_kernel_threads(); break; case SNAPSHOT_PREF_IMAGE_SIZE: From ad77c3e1808f07fa70f707b1c92a683b7c7d3f85 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 27 Jan 2012 17:56:06 -0800 Subject: [PATCH 208/380] hwmon: (w83627ehf) Disable setting DC mode for pwm2, pwm3 on NCT6776F NCT6776F only supports pwm mode for pwm2 and pwm3. Return error if an attempt is made to set those pwm channels to DC mode. Signed-off-by: Guenter Roeck Acked-by: Jean Delvare Cc: stable@vger.kernel.org # 3.0+ Signed-off-by: Guenter Roeck --- drivers/hwmon/w83627ehf.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 0e0af0445222..2dfae7d7cc5b 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -1319,6 +1319,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, { struct w83627ehf_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct w83627ehf_sio_data *sio_data = dev->platform_data; int nr = sensor_attr->index; unsigned long val; int err; @@ -1330,6 +1331,11 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, if (val > 1) return -EINVAL; + + /* On NCT67766F, DC mode is only supported for pwm1 */ + if (sio_data->kind == nct6776 && nr && val != 1) + return -EINVAL; + mutex_lock(&data->update_lock); reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]); data->pwm_mode[nr] = val; From 8422fa110334cea79ab16c474902edb21a8b3168 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 30 Jan 2012 17:10:58 +0800 Subject: [PATCH 209/380] ALSA: Add #ifdef CONFIG_PCI guard for snd_pci_quirk_* functions This fixes below build warning when CONFIG_PCI is not set. CC sound/sound_core.o In file included from sound/sound_core.c:15: include/sound/core.h:454: warning: 'struct pci_dev' declared inside parameter list include/sound/core.h:454: warning: its scope is only this definition or declaration, which is probably not what you want Signed-off-by: Axel Lin Signed-off-by: Takashi Iwai --- include/sound/core.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sound/core.h b/include/sound/core.h index 5ab255f196cc..cea1b5426dfa 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -417,6 +417,7 @@ static inline int __snd_bug_on(int cond) #define gameport_get_port_data(gp) (gp)->port_data #endif +#ifdef CONFIG_PCI /* PCI quirk list helper */ struct snd_pci_quirk { unsigned short subvendor; /* PCI subvendor ID */ @@ -456,5 +457,6 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list); const struct snd_pci_quirk * snd_pci_quirk_lookup_id(u16 vendor, u16 device, const struct snd_pci_quirk *list); +#endif #endif /* __SOUND_CORE_H */ From 6e877b576ddf7cde5db2e9a6dcb56fef0ea77e64 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 29 Jan 2012 17:05:52 +0100 Subject: [PATCH 210/380] Revert "drm/i810: cleanup reclaim_buffers" This reverts commit 87499ffdcb1c70f66988cd8febc4ead0ba2f9118. Where is that paper bag ... ah here. I've failed to take an odd interaction between my other cleanups and this reclaim_buffers patch into account and also failed to properly test it. Looks like there are more dragons and hidden trapdoors in the drm release path than actual lines of code. Until I get a clue, let's just revert this. Signed-Off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/i810/i810_dma.c | 17 ++++++----------- drivers/gpu/drm/i810/i810_drv.c | 1 + drivers/gpu/drm/i810/i810_drv.h | 6 ++++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index f7c17b239833..7f4b4e10246e 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -886,7 +886,7 @@ static int i810_flush_queue(struct drm_device *dev) } /* Must be called with the lock held */ -void i810_driver_reclaim_buffers(struct drm_device *dev, +static void i810_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; @@ -1223,17 +1223,12 @@ void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) if (dev_priv->page_flipping) i810_do_cleanup_pageflip(dev); } +} - if (file_priv->master && file_priv->master->lock.hw_lock) { - drm_idlelock_take(&file_priv->master->lock); - i810_driver_reclaim_buffers(dev, file_priv); - drm_idlelock_release(&file_priv->master->lock); - } else { - /* master disappeared, clean up stuff anyway and hope nothing - * goes wrong */ - i810_driver_reclaim_buffers(dev, file_priv); - } - +void i810_driver_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv) +{ + i810_reclaim_buffers(dev, file_priv); } int i810_driver_dma_quiescent(struct drm_device *dev) diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index 053f1ee58393..ec12f7dc717a 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -63,6 +63,7 @@ static struct drm_driver driver = { .lastclose = i810_driver_lastclose, .preclose = i810_driver_preclose, .device_is_agp = i810_driver_device_is_agp, + .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, .dma_quiescent = i810_driver_dma_quiescent, .ioctls = i810_ioctls, .fops = &i810_driver_fops, diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h index 6e0acad9e0f5..c9339f481795 100644 --- a/drivers/gpu/drm/i810/i810_drv.h +++ b/drivers/gpu/drm/i810/i810_drv.h @@ -116,12 +116,14 @@ typedef struct drm_i810_private { /* i810_dma.c */ extern int i810_driver_dma_quiescent(struct drm_device *dev); -void i810_driver_reclaim_buffers(struct drm_device *dev, - struct drm_file *file_priv); +extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv); extern int i810_driver_load(struct drm_device *, unsigned long flags); extern void i810_driver_lastclose(struct drm_device *dev); extern void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv); +extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv); extern int i810_driver_device_is_agp(struct drm_device *dev); extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg); From dd8bc93d45c0ac4f64bf074d4be72418aac1609b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 29 Jan 2012 16:45:32 +0000 Subject: [PATCH 211/380] drm: Pass the real error code back during GEM bo initialisation In particular, I found I was hitting the max-file limit in the VFS, and the EFILE was being magically transformed into ENOMEM. Confusion reigns. Signed-off-by: Chris Wilson Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 396e60ce8114..f8625e290728 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -140,7 +140,7 @@ int drm_gem_object_init(struct drm_device *dev, obj->dev = dev; obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); if (IS_ERR(obj->filp)) - return -ENOMEM; + return PTR_ERR(obj->filp); kref_init(&obj->refcount); atomic_set(&obj->handle_count, 0); From 1ffd57c1da2a73b0a0e5cd7a6dd52cc49e36bef9 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 28 Jan 2012 11:10:38 +0100 Subject: [PATCH 212/380] drm/radeon/kms: Fix device tree linkage of i2c buses Properly set the parent device of i2c buses before registering them so that they will show at the right place in the device tree (rather than in /sys/devices directly.) Signed-off-by: Jean Delvare Cc: Dave Airlie Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_i2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 7bb1b079f480..e2a393ff0c44 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -897,6 +897,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, i2c->rec = *rec; i2c->adapter.owner = THIS_MODULE; i2c->adapter.class = I2C_CLASS_DDC; + i2c->adapter.dev.parent = &dev->pdev->dev; i2c->dev = dev; i2c_set_adapdata(&i2c->adapter, i2c); if (rec->mm_i2c || From bf9c05d5b6d19b3e4c9fe21047694e94f48db89b Mon Sep 17 00:00:00 2001 From: Ryan Mallon Date: Sat, 28 Jan 2012 08:51:40 +1100 Subject: [PATCH 213/380] vmwgfx: Fix assignment in vmw_framebuffer_create_handle The assignment of handle in vmw_framebuffer_create_handle doesn't actually do anything useful and is incorrectly assigning an integer value to a pointer argument. It appears that this is a typo and should be dereferencing handle rather than assigning to it directly. This fixes a bug where an undefined handle value is potentially returned to user-space. Signed-off-by: Ryan Mallon Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 0af6ebdf205d..b66ef0e3cde1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -378,7 +378,7 @@ int vmw_framebuffer_create_handle(struct drm_framebuffer *fb, unsigned int *handle) { if (handle) - handle = 0; + *handle = 0; return 0; } From 5955633e91bfc5cd0a41d8d82259e1d8b32980ef Mon Sep 17 00:00:00 2001 From: Michael D Labriola Date: Sun, 29 Jan 2012 14:17:22 -0500 Subject: [PATCH 214/380] x86/reboot: Skip DMI checks if reboot set by user Skip DMI checks for vendor specific reboot quirks if the user passed in a reboot= arg on the command line - we should never override user choices. Signed-off-by: Michael D Labriola Cc: Alan Cox Cc: Michael D Labriola Cc: Matthew Garrett Cc: Linus Torvalds Link: http://lkml.kernel.org/r/87wr8ab9od.fsf@gmail.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/reboot.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 37a458b521a6..b257f0e28824 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -39,6 +39,14 @@ static int reboot_mode; enum reboot_type reboot_type = BOOT_ACPI; int reboot_force; +/* This variable is used privately to keep track of whether or not + * reboot_type is still set to its default value (i.e., reboot= hasn't + * been set on the command line). This is needed so that we can + * suppress DMI scanning for reboot quirks. Without it, it's + * impossible to override a faulty reboot quirk without recompiling. + */ +static int reboot_default = 1; + #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) static int reboot_cpu = -1; #endif @@ -67,6 +75,12 @@ bool port_cf9_safe = false; static int __init reboot_setup(char *str) { for (;;) { + /* Having anything passed on the command line via + * reboot= will cause us to disable DMI checking + * below. + */ + reboot_default = 0; + switch (*str) { case 'w': reboot_mode = 0x1234; @@ -316,7 +330,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { static int __init reboot_init(void) { - dmi_check_system(reboot_dmi_table); + /* Only do the DMI check if reboot_type hasn't been overridden + * on the command line + */ + if (reboot_default) { + dmi_check_system(reboot_dmi_table); + } return 0; } core_initcall(reboot_init); @@ -465,7 +484,12 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { static int __init pci_reboot_init(void) { - dmi_check_system(pci_reboot_dmi_table); + /* Only do the DMI check if reboot_type hasn't been overridden + * on the command line + */ + if (reboot_default) { + dmi_check_system(pci_reboot_dmi_table); + } return 0; } core_initcall(pci_reboot_init); From e6d36a653becc7bbc643c399a77882e02bf552cb Mon Sep 17 00:00:00 2001 From: Michael D Labriola Date: Sun, 29 Jan 2012 14:21:17 -0500 Subject: [PATCH 215/380] x86/reboot: Remove VersaLogic Menlow reboot quirk This commit removes the reboot quirk originally added by commit e19e074 ("x86: Fix reboot problem on VersaLogic Menlow boards"). Testing with a VersaLogic Ocelot (VL-EPMs-21a rev 1.00 w/ BIOS 6.5.102) revealed the following regarding the reboot hang problem: - v2.6.37 reboot=bios was needed. - v2.6.38-rc1: behavior changed, reboot=acpi is needed, reboot=kbd and reboot=bios results in system hang. - v2.6.38: VersaLogic patch (e19e074 "x86: Fix reboot problem on VersaLogic Menlow boards") was applied prior to v2.6.38-rc7. This patch sets a quirk for VersaLogic Menlow boards that forces the use of reboot=bios, which doesn't work anymore. - v3.2: It seems that commit 660e34c ("x86: Reorder reboot method preferences") changed the default reboot method to acpi prior to v3.0-rc1, which means the default behavior is appropriate for the Ocelot. No VersaLogic quirk is required. The Ocelot board used for testing can successfully reboot w/out having to pass any reboot= arguments for all 3 current versions of the BIOS. Signed-off-by: Michael D Labriola Cc: Matthew Garrett Cc: Michael D Labriola Cc: Kushal Koolwal Cc: Linus Torvalds Link: http://lkml.kernel.org/r/87vcnub9hu.fsf@gmail.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/reboot.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index b257f0e28824..d840e69a853c 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -309,14 +309,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "P4S800"), }, }, - { /* Handle problems with rebooting on VersaLogic Menlow boards */ - .callback = set_bios_reboot, - .ident = "VersaLogic Menlow based board", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"), - DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"), - }, - }, { /* Handle reboot issue on Acer Aspire one */ .callback = set_kbd_reboot, .ident = "Acer Aspire One A110", From 05df1f3c2afaef5672627f2b7095f0d4c4dbc3a0 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 26 Jan 2012 18:25:37 +0100 Subject: [PATCH 216/380] iommu/msm: Fix error handling in msm_iommu_unmap() Error handling in msm_iommu_unmap() is broken. On some error conditions retval is set to a non-zero value which causes the function to return 'len' at the end. This hides the error from the user. Zero should be returned in those error cases. Cc: David Brown Cc: Stepan Moskovchenko Cc: stable@vger.kernel.org # >= 3.1 Signed-off-by: Joerg Roedel Acked-by: David Brown --- drivers/iommu/msm_iommu.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 08a90b88e40d..cee307e86606 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -482,23 +482,19 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va, priv = domain->priv; - if (!priv) { - ret = -ENODEV; + if (!priv) goto fail; - } fl_table = priv->pgtable; if (len != SZ_16M && len != SZ_1M && len != SZ_64K && len != SZ_4K) { pr_debug("Bad length: %d\n", len); - ret = -EINVAL; goto fail; } if (!fl_table) { pr_debug("Null page table\n"); - ret = -EINVAL; goto fail; } @@ -507,7 +503,6 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va, if (*fl_pte == 0) { pr_debug("First level PTE is 0\n"); - ret = -ENODEV; goto fail; } From 1ae5cbc52e7c6619a3f44b87809fd25370df31bb Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Mon, 30 Jan 2012 00:31:47 +0100 Subject: [PATCH 217/380] ASoC: neo1973_wm8753: remove references to the neo1973-gta01 machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Openmoko GTA01 machine has been removed from the machine ID database, so we need to remove references to it as well. Without that fix we have: sound/soc/samsung/neo1973_wm8753.c: In function ‘neo1973_wm8753_init’: sound/soc/samsung/neo1973_wm8753.c:325:2: error: implicit declaration of function ‘machine_is_neo1973_gta01’ Signed-off-by: Denis 'GNUtoo' Carikli Signed-off-by: Mark Brown --- sound/soc/samsung/neo1973_wm8753.c | 65 +----------------------------- 1 file changed, 1 insertion(+), 64 deletions(-) diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 7ac0ba2025c3..c6012ff5bd3e 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -230,8 +230,6 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { /* GTA02 specific routes and controls */ -#ifdef CONFIG_MACH_NEO1973_GTA02 - static int gta02_speaker_enabled; static int lm4853_set_spk(struct snd_kcontrol *kcontrol, @@ -311,10 +309,6 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) return 0; } -#else -static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; } -#endif - static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; @@ -322,10 +316,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) int ret; /* set up NC codec pins */ - if (machine_is_neo1973_gta01()) { - snd_soc_dapm_nc_pin(dapm, "LOUT2"); - snd_soc_dapm_nc_pin(dapm, "ROUT2"); - } snd_soc_dapm_nc_pin(dapm, "OUT3"); snd_soc_dapm_nc_pin(dapm, "OUT4"); snd_soc_dapm_nc_pin(dapm, "LINE1"); @@ -370,50 +360,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) return 0; } -/* GTA01 specific controls */ - -#ifdef CONFIG_MACH_NEO1973_GTA01 - -static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = { - {"Amp IN", NULL, "ROUT1"}, - {"Amp IN", NULL, "LOUT1"}, - - {"Handset Spk", NULL, "Amp EP"}, - {"Stereo Out", NULL, "Amp LS"}, - {"Headphone", NULL, "Amp HP"}, -}; - -static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Handset Spk", NULL), - SND_SOC_DAPM_SPK("Stereo Out", NULL), - SND_SOC_DAPM_HP("Headphone", NULL), -}; - -static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) -{ - int ret; - - ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets, - ARRAY_SIZE(neo1973_lm4857_dapm_widgets)); - if (ret) - return ret; - - ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes, - ARRAY_SIZE(neo1973_lm4857_routes)); - if (ret) - return ret; - - snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); - snd_soc_dapm_ignore_suspend(dapm, "Headphone"); - - return 0; -} - -#else -static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; }; -#endif - static struct snd_soc_dai_link neo1973_dai[] = { { /* Hifi Playback - for similatious use with voice below */ .name = "WM8753", @@ -440,11 +386,6 @@ static struct snd_soc_aux_dev neo1973_aux_devs[] = { .name = "dfbmcs320", .codec_name = "dfbmcs320.0", }, - { - .name = "lm4857", - .codec_name = "lm4857.0-007c", - .init = neo1973_lm4857_init, - }, }; static struct snd_soc_codec_conf neo1973_codec_conf[] = { @@ -454,14 +395,10 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = { }, }; -#ifdef CONFIG_MACH_NEO1973_GTA02 static const struct gpio neo1973_gta02_gpios[] = { { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" }, { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" }, }; -#else -static const struct gpio neo1973_gta02_gpios[] = {}; -#endif static struct snd_soc_card neo1973 = { .name = "neo1973", @@ -480,7 +417,7 @@ static int __init neo1973_init(void) { int ret; - if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02()) + if (!machine_is_neo1973_gta02()) return -ENODEV; if (machine_is_neo1973_gta02()) { From 1a30871fe635d3e92972e6b93e39ff65bb57e52d Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 16 Jan 2012 11:07:16 +0200 Subject: [PATCH 218/380] mtd: fix MTD suspend Commits 3fe4bae88460869a8e553397cd9057a4ee7ca341 and 079c985e7a6f4ce60f931cebfdd5ee3c3 broke MTD suspend in 2 ways: 1. When the '->suspend' method is not present, we return -EOPNOTSUPP, but the callers of 'mtd_suspend()' expects 0 instead. 2. Checking of the 'mtd' parameter against NULL has been incorrectly removed in 'mtd_cls_suspend()'. This patch fixes the breakages. This has been found, analyzed, reported and tested by Rafael J. Wysocki . Note, this patch is not needed in the stable tree because it causes a regression introduced during the v3.3 merge window. Reported-by: Rafael J. Wysocki Tested-by: Rafael J. Wysocki Tested-by: Russell King Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/mtdcore.c | 2 +- include/linux/mtd/mtd.h | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 6ae9ca01388b..9a9ce71a71fc 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -119,7 +119,7 @@ static int mtd_cls_suspend(struct device *dev, pm_message_t state) { struct mtd_info *mtd = dev_get_drvdata(dev); - return mtd_suspend(mtd); + return mtd ? mtd_suspend(mtd) : 0; } static int mtd_cls_resume(struct device *dev) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 1a81fde8f333..d8c7aad7331c 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -427,9 +427,7 @@ static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) static inline int mtd_suspend(struct mtd_info *mtd) { - if (!mtd->suspend) - return -EOPNOTSUPP; - return mtd->suspend(mtd); + return mtd->suspend ? mtd->suspend(mtd) : 0; } static inline void mtd_resume(struct mtd_info *mtd) From 31150f2327cbb66363f38e13ca1be973d2f9203a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 30 Jan 2012 10:54:08 +0100 Subject: [PATCH 219/380] ALSA: hda - Apply 0x0f-VREF fix to all ASUS laptops with ALC861/660 It turned out that other ASUS laptops require the similar fix to enable the VREF on the pin 0x0f for the secret output amp, not only ASUS A6Rp. Moreover, it's required even when the pin is being used as the output. Thus, writing a fixed value doesn't work always. This patch applies the VREF-fix for all ASUS laptops with ALC861/660 in a fixup function that checks the current value and turns on only the VREF value no matter whether input or output direction is set. The automute function is modified as well to keep the pin VREF upon muting/unmuting via pin-control; otherwise the pin VREF is reset at plugging/unplugging a jack. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42588 Cc: [v3.2+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 43 ++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a7f17becbd7c..42b6a01e17db 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -177,6 +177,7 @@ struct alc_spec { unsigned int detect_lo:1; /* Line-out detection enabled */ unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */ unsigned int automute_lo_possible:1; /* there are line outs and HP */ + unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */ /* other flags */ unsigned int no_analog :1; /* digital I/O only */ @@ -495,13 +496,24 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins, for (i = 0; i < num_pins; i++) { hda_nid_t nid = pins[i]; + unsigned int val; if (!nid) break; switch (spec->automute_mode) { case ALC_AUTOMUTE_PIN: + /* don't reset VREF value in case it's controlling + * the amp (see alc861_fixup_asus_amp_vref_0f()) + */ + if (spec->keep_vref_in_automute) { + val = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + val &= ~PIN_HP; + } else + val = 0; + val |= pin_bits; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_bits); + val); break; case ALC_AUTOMUTE_AMP: snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, @@ -5588,6 +5600,25 @@ enum { PINFIX_ASUS_A6RP, }; +/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ +static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + unsigned int val; + + if (action != ALC_FIXUP_ACT_INIT) + return; + val = snd_hda_codec_read(codec, 0x0f, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))) + val |= AC_PINCTL_IN_EN; + val |= AC_PINCTL_VREF_50; + snd_hda_codec_write(codec, 0x0f, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, val); + spec->keep_vref_in_automute = 1; +} + static const struct alc_fixup alc861_fixups[] = { [PINFIX_FSC_AMILO_PI1505] = { .type = ALC_FIXUP_PINS, @@ -5598,17 +5629,13 @@ static const struct alc_fixup alc861_fixups[] = { } }, [PINFIX_ASUS_A6RP] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* node 0x0f VREF seems controlling the master output */ - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, - { } - }, + .type = ALC_FIXUP_FUNC, + .v.func = alc861_fixup_asus_amp_vref_0f, }, }; static const struct snd_pci_quirk alc861_fixup_tbl[] = { - SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", PINFIX_ASUS_A6RP), + SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP), SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP), SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505), {} From 4acb41903b2f99f3dffd4c3df9acc84ca5942cb2 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Mon, 30 Jan 2012 01:20:17 +0000 Subject: [PATCH 220/380] net/tcp: Fix tcp memory limits initialization when !CONFIG_SYSCTL sysctl_tcp_mem() initialization was moved to sysctl_tcp_ipv4.c in commit 3dc43e3e4d0b52197d3205214fe8f162f9e0c334, since it became a per-ns value. That code, however, will never run when CONFIG_SYSCTL is disabled, leading to bogus values on those fields - causing hung TCP sockets. This patch fixes it by keeping an initialization code in tcp_init(). It will be overwritten by the first net namespace init if CONFIG_SYSCTL is compiled in, and do the right thing if it is compiled out. It is also named properly as tcp_init_mem(), to properly signal its non-sysctl side effect on TCP limits. Reported-by: Ingo Molnar Signed-off-by: Glauber Costa Cc: David S. Miller Link: http://lkml.kernel.org/r/4F22D05A.8030604@parallels.com [ renamed the function, tidied up the changelog a bit ] Signed-off-by: Ingo Molnar Signed-off-by: David S. Miller --- include/net/tcp.h | 2 ++ net/ipv4/sysctl_net_ipv4.c | 1 + net/ipv4/tcp.c | 16 +++++++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 0118ea999f67..d49db0113a06 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -311,6 +311,8 @@ extern struct proto tcp_prot; #define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val) #define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val) +extern void tcp_init_mem(struct net *net); + extern void tcp_v4_err(struct sk_buff *skb, u32); extern void tcp_shutdown (struct sock *sk, int how); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 4aa7e9dc0cbb..4cb9cd2f2c39 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -814,6 +814,7 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) net->ipv4.sysctl_rt_cache_rebuild_count = 4; + tcp_init_mem(net); limit = nr_free_buffer_pages() / 8; limit = max(limit, 128UL); net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 9bcdec3ad772..06373b4a449a 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3216,6 +3216,16 @@ static int __init set_thash_entries(char *str) } __setup("thash_entries=", set_thash_entries); +void tcp_init_mem(struct net *net) +{ + /* Set per-socket limits to no more than 1/128 the pressure threshold */ + unsigned long limit = nr_free_buffer_pages() / 8; + limit = max(limit, 128UL); + net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3; + net->ipv4.sysctl_tcp_mem[1] = limit; + net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2; +} + void __init tcp_init(void) { struct sk_buff *skb = NULL; @@ -3276,9 +3286,9 @@ void __init tcp_init(void) sysctl_tcp_max_orphans = cnt / 2; sysctl_max_syn_backlog = max(128, cnt / 256); - /* Set per-socket limits to no more than 1/128 the pressure threshold */ - limit = ((unsigned long)init_net.ipv4.sysctl_tcp_mem[1]) - << (PAGE_SHIFT - 7); + tcp_init_mem(&init_net); + limit = nr_free_buffer_pages() / 8; + limit = max(limit, 128UL); max_share = min(4UL*1024*1024, limit); sysctl_tcp_wmem[0] = SK_MEM_QUANTUM; From 5b35e1e6e9ca651e6b291c96d1106043c9af314a Mon Sep 17 00:00:00 2001 From: Neal Cardwell Date: Sat, 28 Jan 2012 17:29:46 +0000 Subject: [PATCH 221/380] tcp: fix tcp_trim_head() to adjust segment count with skb MSS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes tcp_trim_head() to recalculate the number of segments in the skb with the skb's existing MSS, so trimming the head causes the skb segment count to be monotonically non-increasing - it should stay the same or go down, but not increase. Previously tcp_trim_head() used the current MSS of the connection. But if there was a decrease in MSS between original transmission and ACK (e.g. due to PMTUD), this could cause tcp_trim_head() to counter-intuitively increase the segment count when trimming bytes off the head of an skb. This violated assumptions in tcp_tso_acked() that tcp_trim_head() only decreases the packet count, so that packets_acked in tcp_tso_acked() could underflow, leading tcp_clean_rtx_queue() to pass u32 pkts_acked values as large as 0xffffffff to ca_ops->pkts_acked(). As an aside, if tcp_trim_head() had really wanted the skb to reflect the current MSS, it should have called tcp_set_skb_tso_segs() unconditionally, since a decrease in MSS would mean that a single-packet skb should now be sliced into multiple segments. Signed-off-by: Neal Cardwell Acked-by: Nandita Dukkipati Acked-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8c8de2780c7a..4ff3b6dc74fc 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1141,11 +1141,9 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) sk_mem_uncharge(sk, len); sock_set_flag(sk, SOCK_QUEUE_SHRUNK); - /* Any change of skb->len requires recalculation of tso - * factor and mss. - */ + /* Any change of skb->len requires recalculation of tso factor. */ if (tcp_skb_pcount(skb) > 1) - tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk)); + tcp_set_skb_tso_segs(sk, skb, tcp_skb_mss(skb)); return 0; } From 6f01fd6e6f6809061b56e78f1e8d143099716d70 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 28 Jan 2012 16:11:03 +0000 Subject: [PATCH 222/380] af_unix: fix EPOLLET regression for stream sockets Commit 0884d7aa24 (AF_UNIX: Fix poll blocking problem when reading from a stream socket) added a regression for epoll() in Edge Triggered mode (EPOLLET) Appropriate fix is to use skb_peek()/skb_unlink() instead of skb_dequeue(), and only call skb_unlink() when skb is fully consumed. This remove the need to requeue a partial skb into sk_receive_queue head and the extra sk->sk_data_ready() calls that added the regression. This is safe because once skb is given to sk_receive_queue, it is not modified by a writer, and readers are serialized by u->readlock mutex. This also reduce number of spinlock acquisition for small reads or MSG_PEEK users so should improve overall performance. Reported-by: Nick Mathewson Signed-off-by: Eric Dumazet Cc: Alexey Moiseytsev Signed-off-by: David S. Miller --- net/unix/af_unix.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index aad8fb699989..85d3bb7490aa 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1918,7 +1918,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; unix_state_lock(sk); - skb = skb_dequeue(&sk->sk_receive_queue); + skb = skb_peek(&sk->sk_receive_queue); if (skb == NULL) { unix_sk(sk)->recursion_level = 0; if (copied >= target) @@ -1958,11 +1958,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (check_creds) { /* Never glue messages from different writers */ if ((UNIXCB(skb).pid != siocb->scm->pid) || - (UNIXCB(skb).cred != siocb->scm->cred)) { - skb_queue_head(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); + (UNIXCB(skb).cred != siocb->scm->cred)) break; - } } else { /* Copy credentials */ scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); @@ -1977,8 +1974,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, chunk = min_t(unsigned int, skb->len, size); if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { - skb_queue_head(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); if (copied == 0) copied = -EFAULT; break; @@ -1993,13 +1988,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (UNIXCB(skb).fp) unix_detach_fds(siocb->scm, skb); - /* put the skb back if we didn't use it up.. */ - if (skb->len) { - skb_queue_head(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); + if (skb->len) break; - } + skb_unlink(skb, &sk->sk_receive_queue); consume_skb(skb); if (siocb->scm->fp) @@ -2010,9 +2002,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (UNIXCB(skb).fp) siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); - /* put message back and return */ - skb_queue_head(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); break; } } while (size); From 320cfa6ce0b3dc794fedfa4bae54c0f65077234d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 29 Jan 2012 12:41:15 +0100 Subject: [PATCH 223/380] firewire: ohci: disable MSI on Ricoh controllers The PCIe device FireWire (IEEE 1394) [0c00]: Ricoh Co Ltd FireWire Host Controller [1180:e832] (prog-if 10 [OHCI]) is unable to access attached FireWire devices when MSI is enabled but works if MSI is disabled. http://www.mail-archive.com/alsa-user@lists.sourceforge.net/msg28251.html Hence add the "disable MSI" quirks flag for this device, or in fact for safety and simplicity for all current (R5U230, R5U231, R5U240) and future Ricoh PCIe 1394 controllers. Reported-by: Stefan Thomas Cc: 2.6.36+ Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 21250eca28d1..7f5f0da726da 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -303,7 +303,7 @@ static const struct { QUIRK_NO_MSI}, {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID, - QUIRK_CYCLE_TIMER}, + QUIRK_CYCLE_TIMER | QUIRK_NO_MSI}, {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID, QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A}, From 34f8ac6d79e5446c6242e4bcb474f152c857c5c6 Mon Sep 17 00:00:00 2001 From: Jonathan Brassow Date: Fri, 27 Jan 2012 14:53:53 -0600 Subject: [PATCH 224/380] Prevent DM RAID from loading bitmap twice. The life cycle of a device-mapper target is: 1) create 2) resume 3) suspend *) possibly repeat from 2 4) destroy The dm-raid target is unconditionally calling MD's bitmap_load function upon every resume. If steps 2 & 3 above are repeated, bitmap_load is called multiple times. It is only written to be called once; otherwise, it allocates new memory for the bitmap (without freeing the old) and incrementing the number of pages it thinks it has without zeroing first. This ultimately leads to access beyond allocated memory and lost memory. Simply avoiding the bitmap_load call upon resume is not sufficient. If the target was suspended while the initial recovery was only partially complete, it needs to be restarted when the target is resumed. This is why 'md_wakeup_thread' is called before issuing the 'mddev_resume'. Signed-off-by: Jonathan Brassow Signed-off-by: NeilBrown --- drivers/md/dm-raid.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index c2907d836e4e..86cb7e5d83d5 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -56,7 +56,8 @@ struct raid_dev { struct raid_set { struct dm_target *ti; - uint64_t print_flags; + uint32_t bitmap_loaded; + uint32_t print_flags; struct mddev md; struct raid_type *raid_type; @@ -1085,7 +1086,7 @@ static int raid_status(struct dm_target *ti, status_type_t type, raid_param_cnt += 2; } - raid_param_cnt += (hweight64(rs->print_flags & ~DMPF_REBUILD) * 2); + raid_param_cnt += (hweight32(rs->print_flags & ~DMPF_REBUILD) * 2); if (rs->print_flags & (DMPF_SYNC | DMPF_NOSYNC)) raid_param_cnt--; @@ -1197,7 +1198,12 @@ static void raid_resume(struct dm_target *ti) { struct raid_set *rs = ti->private; - bitmap_load(&rs->md); + if (!rs->bitmap_loaded) { + bitmap_load(&rs->md); + rs->bitmap_loaded = 1; + } else + md_wakeup_thread(rs->md.thread); + mddev_resume(&rs->md); } From a6f7feae6d19e84253918d88b04153af09d3a243 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Thu, 26 Jan 2012 16:41:33 +0200 Subject: [PATCH 225/380] IB/mlx4: pass SMP vendor-specific attribute MADs to firmware In the current code, vendor-specific MADs (e.g with the FDR-10 attribute) are silently dropped by the driver, resulting in timeouts at the sending side and inability to query/configure the relevant feature. However, the ConnectX firmware is able to handle such MADs. For unsupported attributes, the firmware returns a GET_RESPONSE MAD containing an error status. For example, for a FDR-10 node with LID 11: # ibstat mlx4_0 1 CA: 'mlx4_0' Port 1: State: Active Physical state: LinkUp Rate: 40 (FDR10) Base lid: 11 LMC: 0 SM lid: 24 Capability mask: 0x02514868 Port GUID: 0x0002c903002e65d1 Link layer: InfiniBand Extended Port Query (EPI) vendor mad timeouts before the patch: # smpquery MEPI 11 -d ibwarn: [4196] smp_query_via: attr 0xff90 mod 0x0 route Lid 11 ibwarn: [4196] _do_madrpc: retry 1 (timeout 1000 ms) ibwarn: [4196] _do_madrpc: retry 2 (timeout 1000 ms) ibwarn: [4196] _do_madrpc: timeout after 3 retries, 3000 ms ibwarn: [4196] mad_rpc: _do_madrpc failed; dport (Lid 11) smpquery: iberror: [pid 4196] main: failed: operation EPI: ext port info query failed EPI query works OK with the patch: # smpquery MEPI 11 -d ibwarn: [6548] smp_query_via: attr 0xff90 mod 0x0 route Lid 11 ibwarn: [6548] mad_rpc: data offs 64 sz 64 mad data 0000 0000 0000 0001 0000 0001 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 # Ext Port info: Lid 11 port 0 StateChangeEnable:...............0x00 LinkSpeedSupported:..............0x01 LinkSpeedEnabled:................0x01 LinkSpeedActive:.................0x01 Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Acked-by: Ira Weiny Cc: Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/mad.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 95c94d8f0254..259b0670b51c 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -257,12 +257,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, return IB_MAD_RESULT_SUCCESS; /* - * Don't process SMInfo queries or vendor-specific - * MADs -- the SMA can't handle them. + * Don't process SMInfo queries -- the SMA can't handle them. */ - if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO || - ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) == - IB_SMP_ATTR_VENDOR_MASK)) + if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO) return IB_MAD_RESULT_SUCCESS; } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT || in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1 || From c5488c571f08b2e21b060a1b43aa840d0a3c6e7a Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Mon, 28 Nov 2011 14:22:29 -0600 Subject: [PATCH 226/380] RDMA/nes: Copyright update Update copyright information in the source files. Signed-off-by: Tatyana Nikolova Signed-off-by: Faisal Latif Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes.c | 2 +- drivers/infiniband/hw/nes/nes.h | 2 +- drivers/infiniband/hw/nes/nes_cm.c | 2 +- drivers/infiniband/hw/nes/nes_cm.h | 2 +- drivers/infiniband/hw/nes/nes_context.h | 2 +- drivers/infiniband/hw/nes/nes_hw.c | 2 +- drivers/infiniband/hw/nes/nes_hw.h | 2 +- drivers/infiniband/hw/nes/nes_mgt.c | 2 +- drivers/infiniband/hw/nes/nes_mgt.h | 2 +- drivers/infiniband/hw/nes/nes_nic.c | 2 +- drivers/infiniband/hw/nes/nes_user.h | 2 +- drivers/infiniband/hw/nes/nes_utils.c | 2 +- drivers/infiniband/hw/nes/nes_verbs.c | 2 +- drivers/infiniband/hw/nes/nes_verbs.h | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 7013da5e9eda..7140199f562e 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 568b4f11380a..c438e4691b3c 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 271279cccad8..a4972abedef1 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index bdfa1fbb35fc..4646e6666087 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_context.h b/drivers/infiniband/hw/nes/nes_context.h index b4393a16099d..a69eef16d72d 100644 --- a/drivers/infiniband/hw/nes/nes_context.h +++ b/drivers/infiniband/hw/nes/nes_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 055f4b545df0..d42c9f435b1b 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 0b590e152c6a..d748e4b31b8d 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. +* Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c index b3b2a240c6e9..3ba7be369452 100644 --- a/drivers/infiniband/hw/nes/nes_mgt.c +++ b/drivers/infiniband/hw/nes/nes_mgt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel-NE, Inc. All rights reserved. + * Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_mgt.h b/drivers/infiniband/hw/nes/nes_mgt.h index 8c8af254555a..4f7f701c4a81 100644 --- a/drivers/infiniband/hw/nes/nes_mgt.h +++ b/drivers/infiniband/hw/nes/nes_mgt.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2010 Intel-NE, Inc. All rights reserved. +* Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 4b3fa711a247..f3a3ecf8d09e 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_user.h b/drivers/infiniband/hw/nes/nes_user.h index 71e133ab209b..4926de744488 100644 --- a/drivers/infiniband/hw/nes/nes_user.h +++ b/drivers/infiniband/hw/nes/nes_user.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * Copyright (c) 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Cisco Systems. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c index 8b4c2ff54888..e98f4fc0b768 100644 --- a/drivers/infiniband/hw/nes/nes_utils.c +++ b/drivers/infiniband/hw/nes/nes_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 3875365a284b..0927b5cc65d3 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index fe6b6e92fa90..0eff7c44d76b 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two From 0a84f007f97ce6fc7c07a481a5b9808b187a0193 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 17 Jan 2012 13:41:01 -0800 Subject: [PATCH 227/380] perf tools: Fix broken build by defining _GNU_SOURCE in Makefile When building on my Debian/mips system, util/util.c fails to build because commit 1aed2671738785e8f5aea663a6fda91aa7ef59b5 (perf kvm: Do guest-only counting by default) indirectly includes stdio.h before the feature selection in util.h is done. This prevents _GNU_SOURCE in util.h from enabling the declaration of getline(), from now second inclusion of stdio.h, and the build is broken. There is another breakage in util/evsel.c caused by include ordering, but I didn't fully track down the commit that caused it. The root cause of all this is an inconsistent definition of _GNU_SOURCE, so I move the definition into the Makefile so that it is passed to all invocations of the compiler and used uniformly for all system header files. All other #define and #undef of _GNU_SOURCE are removed as they cause conflicts with the definition passed to the compiler. All the features.h definitions (_LARGEFILE64_SOURCE _FILE_OFFSET_BITS=64 and _GNU_SOURCE) are needed by the python glue code too, so they are moved to BASIC_CFLAGS, and the misleading comments about BASIC_CFLAGS are removed. This gives me a clean build on x86_64 (fc12) and mips (Debian). Cc: David Daney Cc: Ingo Molnar Cc: Joerg Roedel Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1326836461-11952-1-git-send-email-ddaney.cavm@gmail.com Signed-off-by: David Daney Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 7 ++----- tools/perf/builtin-probe.c | 2 -- tools/perf/util/probe-event.c | 2 -- tools/perf/util/symbol.c | 1 - tools/perf/util/trace-event-parse.c | 3 +-- tools/perf/util/ui/browsers/hists.c | 2 -- tools/perf/util/ui/helpline.c | 1 - tools/perf/util/util.h | 1 - 8 files changed, 3 insertions(+), 16 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index ac86d67b636e..7c12650165ae 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -104,7 +104,7 @@ endif CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) EXTLIBS = -lpthread -lrt -lelf -lm -ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE ALL_LDFLAGS = $(LDFLAGS) STRIP ?= strip @@ -168,10 +168,7 @@ endif ### --- END CONFIGURATION SECTION --- -# Those must not be GNU-specific; they are shared with perl/ which may -# be built by a different compiler. (Note that this is an artifact now -# but it still might be nice to keep that distinction.) -BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include +BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE BASIC_LDFLAGS = # Guard against environment variables diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 59d43abfbfec..fb8566181f27 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -20,7 +20,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ -#define _GNU_SOURCE #include #include #include @@ -31,7 +30,6 @@ #include #include -#undef _GNU_SOURCE #include "perf.h" #include "builtin.h" #include "util/util.h" diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index eb25900e2211..29cb65459811 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -19,7 +19,6 @@ * */ -#define _GNU_SOURCE #include #include #include @@ -33,7 +32,6 @@ #include #include -#undef _GNU_SOURCE #include "util.h" #include "event.h" #include "string.h" diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 215d50f2042e..0975438c3e72 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1,4 +1,3 @@ -#define _GNU_SOURCE #include #include #include diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 6c164dc9ee95..1a8d4dc4f386 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -21,14 +21,13 @@ * The parts for function graph printing was taken and modified from the * Linux Kernel that were written by Frederic Weisbecker. */ -#define _GNU_SOURCE + #include #include #include #include #include -#undef _GNU_SOURCE #include "../perf.h" #include "util.h" #include "trace-event.h" diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index 1212a386a033..e81aef1f2569 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -1,6 +1,4 @@ -#define _GNU_SOURCE #include -#undef _GNU_SOURCE #include "../libslang.h" #include #include diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c index 6ef3c5691762..4f48f5901b30 100644 --- a/tools/perf/util/ui/helpline.c +++ b/tools/perf/util/ui/helpline.c @@ -1,4 +1,3 @@ -#define _GNU_SOURCE #include #include #include diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index b9c530cce79a..ecf9898169c8 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -40,7 +40,6 @@ #define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) #define _ALL_SOURCE 1 -#define _GNU_SOURCE 1 #define _BSD_SOURCE 1 #define HAS_BOOL From d8d9c282a1abbe2baf6d22f959e6adf4c90629bf Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Fri, 20 Jan 2012 10:49:12 +0100 Subject: [PATCH 228/380] perf tools: Fix strlen() bug in perf_event__synthesize_event_type() The event_type record has a max length for the event name. It's called MAX_EVENT_NAME. The name may be truncated to fit the max length. But the header.size still reflects the original name length. If that length is > MAX_EVENT_NAME, then the header.size field is bogus. Fix this by using the length of the name after the potential truncation. Cc: David Ahern Cc: Ingo Molnar Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20120120094912.GA4882@quad Signed-off-by: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 3e7e0b09c12c..ecd7f4dd7eea 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2105,7 +2105,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool, strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; - size = strlen(name); + size = strlen(ev.event_type.event_type.name); size = ALIGN(size, sizeof(u64)); ev.event_type.header.size = sizeof(ev.event_type) - (sizeof(ev.event_type.event_type.name) - size); From 509605dbe9395ce1abbfac1dba375f074ff57a53 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 30 Jan 2012 11:50:37 +0100 Subject: [PATCH 229/380] perf top: Fix number of samples displayed In recent versions of perf top, pressing the 'e' key to change the number of displayed samples had no effect. The number of samples was still dictated by the size of the terminal (stdio mode). That was quite annoying because typically only the first dozen samples really matter. This patch fixes this. Cc: David Ahern Cc: Ingo Molnar Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20120130105037.GA5160@quad Signed-off-by: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 8f80df896038..dd162aa24baa 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -89,8 +89,6 @@ void get_term_dimensions(struct winsize *ws) static void perf_top__update_print_entries(struct perf_top *top) { - top->print_entries = top->winsize.ws_row; - if (top->print_entries > 9) top->print_entries -= 9; } @@ -100,6 +98,13 @@ static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *ar struct perf_top *top = arg; get_term_dimensions(&top->winsize); + if (!top->print_entries + || (top->print_entries+4) > top->winsize.ws_row) { + top->print_entries = top->winsize.ws_row; + } else { + top->print_entries += 4; + top->winsize.ws_row = top->print_entries; + } perf_top__update_print_entries(top); } @@ -453,8 +458,10 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) }; perf_top__sig_winch(SIGWINCH, NULL, top); sigaction(SIGWINCH, &act, NULL); - } else + } else { + perf_top__sig_winch(SIGWINCH, NULL, top); signal(SIGWINCH, SIG_DFL); + } break; case 'E': if (top->evlist->nr_entries > 1) { From bda3a47c886664e86ee14eb79e9072b9e341f575 Mon Sep 17 00:00:00 2001 From: Nikolaus Voss Date: Tue, 17 Jan 2012 10:28:33 +0100 Subject: [PATCH 230/380] at_hdmac: bugfix for enabling channel irq commit 463894705e4089d0ff69e7d877312d496ac70e5b deleted redundant chan_id and chancnt initialization in dma drivers as this is done in dma_async_device_register(). However, atc_enable_irq() relied on chan_id set before registering the device, what left only channel 0 functional for this driver. This patch introduces atc_enable/disable_chan_irq() as a variant of atc_enable/disable_irq() with the channel as explicit argument. Signed-off-by: Nikolaus Voss Signed-off-by: Nicolas Ferre Cc: stable Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 4 ++-- drivers/dma/at_hdmac_regs.h | 17 ++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 97f87b29b9f3..f4aed5fc2cb6 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1343,7 +1343,7 @@ static int __init at_dma_probe(struct platform_device *pdev) tasklet_init(&atchan->tasklet, atc_tasklet, (unsigned long)atchan); - atc_enable_irq(atchan); + atc_enable_chan_irq(atdma, i); } /* set base routines */ @@ -1410,7 +1410,7 @@ static int __exit at_dma_remove(struct platform_device *pdev) struct at_dma_chan *atchan = to_at_dma_chan(chan); /* Disable interrupts */ - atc_disable_irq(atchan); + atc_disable_chan_irq(atdma, chan->chan_id); tasklet_disable(&atchan->tasklet); tasklet_kill(&atchan->tasklet); diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index dcaedfc181cf..a8d3277d60b5 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -327,28 +327,27 @@ static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli) } -static void atc_setup_irq(struct at_dma_chan *atchan, int on) +static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on) { - struct at_dma *atdma = to_at_dma(atchan->chan_common.device); - u32 ebci; + u32 ebci; /* enable interrupts on buffer transfer completion & error */ - ebci = AT_DMA_BTC(atchan->chan_common.chan_id) - | AT_DMA_ERR(atchan->chan_common.chan_id); + ebci = AT_DMA_BTC(chan_id) + | AT_DMA_ERR(chan_id); if (on) dma_writel(atdma, EBCIER, ebci); else dma_writel(atdma, EBCIDR, ebci); } -static inline void atc_enable_irq(struct at_dma_chan *atchan) +static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id) { - atc_setup_irq(atchan, 1); + atc_setup_irq(atdma, chan_id, 1); } -static inline void atc_disable_irq(struct at_dma_chan *atchan) +static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id) { - atc_setup_irq(atchan, 0); + atc_setup_irq(atdma, chan_id, 0); } From 9afc416517f36b3b0b109e6590d0b74468fd80f9 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Jan 2012 10:53:08 +0100 Subject: [PATCH 231/380] Revert "microblaze: Add topology init" This reverts commit d761f0c521868e59cd0bc59159cbdb4686fe210d. Patch: "cpu: Register a generic CPU device on architectures that currently do not" (sha1: 9f13a1fd452f11c18004ba2422a6384b424ec8a9) selects GENERIC_CPU_DEVICES for Microblaze which register cpu. My patch was done in the same time that's why cpu was registered twice which caused this warning log: ------------[ cut here ]------------ WARNING: at fs/sysfs/dir.c:481 sysfs_add_one+0xb0/0xdc() sysfs: cannot create duplicate filename '/devices/system/cpu/cpu0' Modules linked in: ... Signed-off-by: Michal Simek --- arch/microblaze/kernel/setup.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index d4fc1a971779..604cd9dd1333 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -227,23 +226,5 @@ static int __init setup_bus_notifier(void) return 0; } + arch_initcall(setup_bus_notifier); - -static DEFINE_PER_CPU(struct cpu, cpu_devices); - -static int __init topology_init(void) -{ - int i, ret; - - for_each_present_cpu(i) { - struct cpu *c = &per_cpu(cpu_devices, i); - - ret = register_cpu(c, i); - if (ret) - printk(KERN_WARNING "topology_init: register_cpu %d " - "failed (%d)\n", i, ret); - } - - return 0; -} -subsys_initcall(topology_init); From ee76744c51ec342df9822b4a85dbbfc3887b6d60 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jan 2012 11:55:32 +0000 Subject: [PATCH 232/380] ASoC: wm_hubs: Fix routing of input PGAs to line output mixer IN1L/R is routed to both line output mixers, we don't route IN1 to LINEOUT1 and IN2 to LINEOUT2. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm_hubs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index ea2672455d07..c1a3f8c39691 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -586,8 +586,8 @@ SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), }; static const struct snd_kcontrol_new line2_mix[] = { -SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0), +SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 2, 1, 0), +SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 1, 1, 0), SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), }; @@ -848,8 +848,8 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = { }; static const struct snd_soc_dapm_route lineout2_diff_routes[] = { - { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" }, - { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" }, + { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" }, + { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" }, { "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" }, { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" }, From 4991a5faab7368daac463181e786608b4eb63675 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 31 Jan 2012 11:52:01 +0300 Subject: [PATCH 233/380] cifs: check offset in decode_ntlmssp_challenge() We should check that we're not copying memory from beyond the end of the blob. Signed-off-by: Dan Carpenter Reviewed-by: Jeff Layton --- fs/cifs/sess.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index d85efad5765f..eb767412177d 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -395,6 +395,10 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags); tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); tilen = le16_to_cpu(pblob->TargetInfoArray.Length); + if (tioffset > blob_len || tioffset + tilen > blob_len) { + cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen); + return -EINVAL; + } if (tilen) { ses->auth_key.response = kmalloc(tilen, GFP_KERNEL); if (!ses->auth_key.response) { From 000f9bb83968ebd6959ff76870f16fc8f766ebd3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 30 Jan 2012 19:50:01 -0800 Subject: [PATCH 234/380] cifs: fix printk format warnings Fix printk format warnings for ssize_t variables: fs/cifs/connect.c:2145:3: warning: format '%ld' expects type 'long int', but argument 3 has type 'ssize_t' fs/cifs/connect.c:2152:3: warning: format '%ld' expects type 'long int', but argument 3 has type 'ssize_t' fs/cifs/connect.c:2160:3: warning: format '%ld' expects type 'long int', but argument 3 has type 'ssize_t' fs/cifs/connect.c:2170:3: warning: format '%ld' expects type 'long int', but argument 3 has type 'ssize_t' Signed-off-by: Randy Dunlap Acked-by: Jeff Layton Cc: linux-cifs@vger.kernel.org --- fs/cifs/connect.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 026d6464335b..9c288653e6d6 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2142,14 +2142,14 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) len = delim - payload; if (len > MAX_USERNAME_SIZE || len <= 0) { - cFYI(1, "Bad value from username search (len=%ld)", len); + cFYI(1, "Bad value from username search (len=%zd)", len); rc = -EINVAL; goto out_key_put; } vol->username = kstrndup(payload, len, GFP_KERNEL); if (!vol->username) { - cFYI(1, "Unable to allocate %ld bytes for username", len); + cFYI(1, "Unable to allocate %zd bytes for username", len); rc = -ENOMEM; goto out_key_put; } @@ -2157,7 +2157,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) len = key->datalen - (len + 1); if (len > MAX_PASSWORD_SIZE || len <= 0) { - cFYI(1, "Bad len for password search (len=%ld)", len); + cFYI(1, "Bad len for password search (len=%zd)", len); rc = -EINVAL; kfree(vol->username); vol->username = NULL; @@ -2167,7 +2167,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) ++delim; vol->password = kstrndup(delim, len, GFP_KERNEL); if (!vol->password) { - cFYI(1, "Unable to allocate %ld bytes for password", len); + cFYI(1, "Unable to allocate %zd bytes for password", len); rc = -ENOMEM; kfree(vol->username); vol->username = NULL; From 05c3b36e539627b7aed67d038381d0d9fa9d61e7 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 31 Jan 2012 09:04:15 +0100 Subject: [PATCH 235/380] ALSA: HDA: Fix jack creation for codecs with front and rear Line In If a codec has both a front and a rear Line In, two controls both named "Line Jack" will be created, which causes parsing to fail. While a long term solution might be to name the jacks differently, this extra check is consistent with what is already being done in many auto-parsers, and will also protect against other cases when two inputs have the same label. BugLink: https://bugs.launchpad.net/bugs/923409 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_jack.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index d8a35da0803f..9d819c4b4923 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -282,7 +282,8 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, - const struct auto_pin_cfg *cfg) + const struct auto_pin_cfg *cfg, + char *lastname, int *lastidx) { unsigned int def_conf, conn; char name[44]; @@ -298,6 +299,10 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, return 0; snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); + if (!strcmp(name, lastname) && idx == *lastidx) + idx++; + strncpy(lastname, name, 44); + *lastidx = idx; err = snd_hda_jack_add_kctl(codec, nid, name, idx); if (err < 0) return err; @@ -311,41 +316,42 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { const hda_nid_t *p; - int i, err; + int i, err, lastidx = 0; + char lastname[44] = ""; for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { - err = add_jack_kctl(codec, *p, cfg); + err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); if (err < 0) return err; } for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { if (*p == *cfg->line_out_pins) /* might be duplicated */ break; - err = add_jack_kctl(codec, *p, cfg); + err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); if (err < 0) return err; } for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { if (*p == *cfg->line_out_pins) /* might be duplicated */ break; - err = add_jack_kctl(codec, *p, cfg); + err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); if (err < 0) return err; } for (i = 0; i < cfg->num_inputs; i++) { - err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg); + err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx); if (err < 0) return err; } for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { - err = add_jack_kctl(codec, *p, cfg); + err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); if (err < 0) return err; } - err = add_jack_kctl(codec, cfg->dig_in_pin, cfg); + err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx); if (err < 0) return err; - err = add_jack_kctl(codec, cfg->mono_out_pin, cfg); + err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx); if (err < 0) return err; return 0; From 3422a47041b8cb8f14ac1e3926bcf711121df6dc Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 31 Jan 2012 10:31:49 +0100 Subject: [PATCH 236/380] ALSA: HDA: Remove quirk for Toshiba Qosmio G50 The user reports that model=auto works better than current handling on a 3.2 based kernel (with jack detection patches backported). Since model=auto is what we prefer these days anyway, the quirk should be removed. Alsa-info for the relevant machine: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/923316/+attachment/2702812/+files/alsa-info.txt.Pbfno2x7bp BugLink: https://bugs.launchpad.net/bugs/923316 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 42b6a01e17db..a8e82be3d2fc 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4747,7 +4747,6 @@ enum { ALC262_FIXUP_FSC_H270, ALC262_FIXUP_HP_Z200, ALC262_FIXUP_TYAN, - ALC262_FIXUP_TOSHIBA_RX1, ALC262_FIXUP_LENOVO_3000, ALC262_FIXUP_BENQ, ALC262_FIXUP_BENQ_T31, @@ -4777,16 +4776,6 @@ static const struct alc_fixup alc262_fixups[] = { { } } }, - [ALC262_FIXUP_TOSHIBA_RX1] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x90170110 }, /* speaker */ - { 0x15, 0x0421101f }, /* HP */ - { 0x1a, 0x40f000f0 }, /* N/A */ - { 0x1b, 0x40f000f0 }, /* N/A */ - { 0x1e, 0x40f000f0 }, /* N/A */ - } - }, [ALC262_FIXUP_LENOVO_3000] = { .type = ALC_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { @@ -4819,8 +4808,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ), SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ), SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN), - SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", - ALC262_FIXUP_TOSHIBA_RX1), SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270), SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000), SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ), From 67f97f5c3edad35c4d37a94f994c76111a177fb6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jan 2012 14:51:29 +0000 Subject: [PATCH 237/380] ASoC: wm8994: Remove ASoC level register cache sync Now we've switched over to regmap the ASoC level cache sync will be ineffectual and potentially harmful as there is no longer an ASoC level cache. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 93d27b660257..8623950d55f8 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2753,11 +2753,6 @@ static int wm8994_resume(struct snd_soc_codec *codec) codec->cache_only = 0; } - /* Restore the registers */ - ret = snd_soc_cache_sync(codec); - if (ret != 0) - dev_err(codec->dev, "Failed to sync cache: %d\n", ret); - wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { From 2a73ca8208197d03f78d680b3c7953b897e91eb6 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 31 Jan 2012 12:51:24 -0600 Subject: [PATCH 238/380] [CIFS] Update cifs Kconfig title to match removal of experimental dependency Removed the dependency on CONFIG_EXPERIMENTAL but forgot to update the text description to be consistent. Signed-off-by: Steve French --- fs/cifs/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0554b00a7b33..2b243af70aa3 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -139,7 +139,7 @@ config CIFS_DFS_UPCALL points. If unsure, say N. config CIFS_FSCACHE - bool "Provide CIFS client caching support (EXPERIMENTAL)" + bool "Provide CIFS client caching support" depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y help Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data @@ -147,7 +147,7 @@ config CIFS_FSCACHE manager. If unsure, say N. config CIFS_ACL - bool "Provide CIFS ACL support (EXPERIMENTAL)" + bool "Provide CIFS ACL support" depends on CIFS_XATTR && KEYS help Allows to fetch CIFS/NTFS ACL from the server. The DACL blob From 125a25da5729740b7d1dc417a3d5549321baae17 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 31 Jan 2012 15:49:10 +0000 Subject: [PATCH 239/380] ASoC: core: Better support for idle_bias_off suspend ignores If an idle_bias_off device is in any state other than off then it is still active for some reason (typically a low power function such as accessory detection). This wasn't an issue when the feature was implemented as we always went to _ON for any active function, subsequent power improvements have changed things. With the modern way of doing things we should overhaul the infrastructure to allow devices to explicitly take references for these functions but that's a much more invasive change and will require driver updates to deploy, this will bring the framework into line with the existing driver set before we do that work. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/soc-core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b5ecf6d23214..92cee24ed2dc 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -567,6 +567,17 @@ int snd_soc_suspend(struct device *dev) if (!codec->suspended && codec->driver->suspend) { switch (codec->dapm.bias_level) { case SND_SOC_BIAS_STANDBY: + /* + * If the CODEC is capable of idle + * bias off then being in STANDBY + * means it's doing something, + * otherwise fall through. + */ + if (codec->dapm.idle_bias_off) { + dev_dbg(codec->dev, + "idle_bias_off CODEC on over suspend\n"); + break; + } case SND_SOC_BIAS_OFF: codec->driver->suspend(codec); codec->suspended = 1; From b923650b84068b74b6df838aa8f9b2a350171de6 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 30 Jan 2012 00:20:48 +0200 Subject: [PATCH 240/380] lib: add NO_GENERIC_PCI_IOPORT_MAP Some architectures need to override the way IO port mapping is done on PCI devices. Supply a generic macro that calls ioport_map, and make it possible for architectures to override. Signed-off-by: Michael S. Tsirkin Acked-by: Arnd Bergmann --- include/asm-generic/pci_iomap.h | 10 ++++++++++ lib/Kconfig | 3 +++ lib/pci_iomap.c | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/pci_iomap.h b/include/asm-generic/pci_iomap.h index 8de4b73e19e2..e58fcf891370 100644 --- a/include/asm-generic/pci_iomap.h +++ b/include/asm-generic/pci_iomap.h @@ -15,6 +15,16 @@ struct pci_dev; #ifdef CONFIG_PCI /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); +/* Create a virtual mapping cookie for a port on a given PCI device. + * Do not call this directly, it exists to make it easier for architectures + * to override */ +#ifdef CONFIG_NO_GENERIC_PCI_IOPORT_MAP +extern void __iomem *__pci_ioport_map(struct pci_dev *dev, unsigned long port, + unsigned int nr); +#else +#define __pci_ioport_map(dev, port, nr) ioport_map((port), (nr)) +#endif + #else static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) { diff --git a/lib/Kconfig b/lib/Kconfig index 169eb7c598e5..1df13883481c 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -19,6 +19,9 @@ config RATIONAL config GENERIC_FIND_FIRST_BIT bool +config NO_GENERIC_PCI_IOPORT_MAP + bool + config GENERIC_PCI_IOMAP bool diff --git a/lib/pci_iomap.c b/lib/pci_iomap.c index 4b0fdc22e688..0d83ea8a9605 100644 --- a/lib/pci_iomap.c +++ b/lib/pci_iomap.c @@ -34,7 +34,7 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) if (maxlen && len > maxlen) len = maxlen; if (flags & IORESOURCE_IO) - return ioport_map(start, len); + return __pci_ioport_map(dev, start, len); if (flags & IORESOURCE_MEM) { if (flags & IORESOURCE_CACHEABLE) return ioremap(start, len); From 0f3b3956c4946a6a991974943e3de33ae3d2523f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 30 Jan 2012 00:23:38 +0200 Subject: [PATCH 241/380] mips: use the the PCI controller's io_map_base commit eab90291d35438bcebf7c3dc85be66d0f24e3002 (mips: switch to GENERIC_PCI_IOMAP) failed to take into account the PCI controller's io_map_base for mapping IO BARs. This also caused a new warning on mips. Fix this, without re-introducing code duplication, by setting NO_GENERIC_PCI_IOPORT_MAP and supplying a mips-specific __pci_ioport_map. Reported-by: Kevin Cernekee Signed-off-by: Michael S. Tsirkin --- arch/mips/Kconfig | 1 + arch/mips/lib/iomap-pci.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c4c1312473fb..5ab6e89603c5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2356,6 +2356,7 @@ config PCI depends on HW_HAS_PCI select PCI_DOMAINS select GENERIC_PCI_IOMAP + select NO_GENERIC_PCI_IOPORT_MAP help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c index 2635b1a96333..fd35daa45314 100644 --- a/arch/mips/lib/iomap-pci.c +++ b/arch/mips/lib/iomap-pci.c @@ -10,8 +10,8 @@ #include #include -static void __iomem *ioport_map_pci(struct pci_dev *dev, - unsigned long port, unsigned int nr) +void __iomem *__pci_ioport_map(struct pci_dev *dev, + unsigned long port, unsigned int nr) { struct pci_controller *ctrl = dev->bus->sysdata; unsigned long base = ctrl->io_map_base; From 1e05b62ae4bd4c1209229de367b0989b39644f88 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 30 Jan 2012 00:29:10 +0200 Subject: [PATCH 242/380] sh: use the the PCI channels's io_map_base commit 43db595e8b5d78ce5ad2feab719814a76e3ad2e5 (sh: switch to GENERIC_PCI_IOMAP) failed to take into account the PCI channels's io_map_base for mapping IO BARs. This also caused a new warning on sh. Fix this, without re-introducing code duplication, by setting NO_GENERIC_PCI_IOPORT_MAP and supplying a sh-specific __pci_ioport_map. Reported-by: Kevin Cernekee Signed-off-by: Michael S. Tsirkin --- arch/sh/Kconfig | 1 + arch/sh/drivers/pci/pci.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 3c8db65c89e5..713fb58ca507 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -859,6 +859,7 @@ config PCI depends on SYS_SUPPORTS_PCI select PCI_DOMAINS select GENERIC_PCI_IOMAP + select NO_GENERIC_PCI_IOPORT_MAP help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 8f18dd090a66..1e7b0e2e764d 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -356,8 +356,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, #ifndef CONFIG_GENERIC_IOMAP -static void __iomem *ioport_map_pci(struct pci_dev *dev, - unsigned long port, unsigned int nr) +void __iomem *__pci_ioport_map(struct pci_dev *dev, + unsigned long port, unsigned int nr) { struct pci_channel *chan = dev->sysdata; From 62aa2b537c6f5957afd98e29f96897419ed5ebab Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 31 Jan 2012 13:31:54 -0800 Subject: [PATCH 243/380] Linux 3.3-rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 71e6ed21dd15..e3b23e864a53 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 3 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Saber-toothed Squirrel # *DOCUMENTATION* From 7df898b1a70b13c3a8892625f4ead929d9554293 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 31 Jan 2012 09:16:59 +1000 Subject: [PATCH 244/380] drm/nouveau/disp: check that panel power gpio is enabled at init time Reported-by: Yuriy Khomchik Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.h | 5 +++-- drivers/gpu/drm/nouveau/nouveau_display.c | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 1e382ad5a2b8..a37c31e358aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -54,9 +54,10 @@ struct bit_entry { int bit_table(struct drm_device *, u8 id, struct bit_entry *); enum dcb_gpio_tag { - DCB_GPIO_TVDAC0 = 0xc, + DCB_GPIO_PANEL_POWER = 0x01, + DCB_GPIO_TVDAC0 = 0x0c, DCB_GPIO_TVDAC1 = 0x2d, - DCB_GPIO_PWM_FAN = 0x9, + DCB_GPIO_PWM_FAN = 0x09, DCB_GPIO_FAN_SENSE = 0x3d, DCB_GPIO_UNUSED = 0xff }; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 3cb52bc52b21..795a9e3c990a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -219,6 +219,16 @@ nouveau_display_init(struct drm_device *dev) if (ret) return ret; + /* power on internal panel if it's not already. the init tables of + * some vbios default this to off for some reason, causing the + * panel to not work after resume + */ + if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) { + nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true); + msleep(300); + } + + /* enable polling for external displays */ drm_kms_helper_poll_enable(dev); /* enable hotplug interrupts */ From ce2e7895faba8fabaa917f52293126e5f4174fa9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Feb 2012 15:08:59 +1000 Subject: [PATCH 245/380] drm/nouveau/mxm: pretend to succeed, even if we can't shadow the MXM-SIS There's at least one known case where our shadowing code is buggy, and we fail init. Until we can be confident we're doing all this correctly, lets succeed and risk crazy bios tables rather than failing for perfectly valid configs too. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_mxm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c index 8bccddf4eff0..e5a64f0f4cb7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mxm.c +++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c @@ -656,7 +656,16 @@ nouveau_mxm_init(struct drm_device *dev) if (mxm_shadow(dev, mxm[0])) { MXM_MSG(dev, "failed to locate valid SIS\n"); +#if 0 + /* we should, perhaps, fall back to some kind of limited + * mode here if the x86 vbios hasn't already done the + * work for us (so we prevent loading with completely + * whacked vbios tables). + */ return -EINVAL; +#else + return 0; +#endif } MXM_MSG(dev, "MXMS Version %d.%d\n", From 1eb8a619b43c1e99179ebadbc9c614ed37358f2d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 7 Jan 2012 16:48:52 +1000 Subject: [PATCH 246/380] drm/nouveau: fix typo on mxmdcb option Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index e4a7cfe7898d..81d7962e7252 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -124,7 +124,7 @@ MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n"); int nouveau_ctxfw; module_param_named(ctxfw, nouveau_ctxfw, int, 0400); -MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n"); +MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS\n"); int nouveau_mxmdcb = 1; module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400); From 525895ba388c949aa906f26e3ec5cb1ab041f56b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 10 Jan 2012 10:18:28 +1000 Subject: [PATCH 247/380] drm/nouveau/gem: fix fence_sync race / oops Due to a race it was possible for a fence to be destroyed while another thread was trying to synchronise with it. If this happened in the fallback non-semaphore path, it lead to the following oops due to fence->channel being NULL. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] nouveau_fence_update+0xe/0xe0 [nouveau] *pde = a649c067 SMP Modules linked in: fuse nouveau(O) ttm(O) drm_kms_helper(O) drm(O) mxm_wmi video wmi netconsole configfs lockd bnep bluetooth rfkill ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack ip6table_filter ip6_tables snd_hda_codec_realtek snd_hda_intel snd_hda_cobinfmt_misc uinput ata_generic pata_acpi pata_aet2c_algo_bit i2c_core [last unloaded: wmi] Pid: 2255, comm: gnome-shell Tainted: G O 3.2.0-0.rc5.git0.1.fc17.i686 #1 System manufacturer System Product Name/M2A-VM EIP: 0060:[] EFLAGS: 00010296 CPU: 1 EIP is at nouveau_fence_update+0xe/0xe0 [nouveau] EAX: 00000000 EBX: ddfc6dd0 ECX: dd111580 EDX: 00000000 ESI: 00003e80 EDI: dd111580 EBP: dd121d00 ESP: dd121ce8 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Process gnome-shell (pid: 2255, ti=dd120000 task=dd111580 task.ti=dd120000) Stack: 7dc86c76 00000000 00003e80 ddfc6dd0 00003e80 dd111580 dd121d0c fa96371f 00000000 dd121d3c fa963773 dd111580 01000246 000ec53d 00000000 ddfc6dd0 00001f40 00000000 ddfc6dd0 00000010 dc7df840 dd121d6c fa9639a0 00000000 Call Trace: [] __nouveau_fence_signalled+0x1f/0x30 [nouveau] [] __nouveau_fence_wait+0x43/0xd0 [nouveau] [] nouveau_fence_sync+0x1a0/0x1c0 [nouveau] [] validate_list+0x176/0x300 [nouveau] [] ? ttm_bo_mem_put+0x30/0x30 [ttm] [] nouveau_gem_ioctl_pushbuf+0x48a/0xfd0 [nouveau] [] ? die+0x31/0x80 [] drm_ioctl+0x388/0x490 [drm] [] ? die+0x31/0x80 [] ? nouveau_gem_ioctl_new+0x150/0x150 [nouveau] [] ? file_has_perm+0xcb/0xe0 [] ? drm_copy_field+0x80/0x80 [drm] [] do_vfs_ioctl+0x86/0x5b0 [] ? die+0x31/0x80 [] ? selinux_file_ioctl+0x62/0x130 [] ? fget_light+0x30/0x340 [] sys_ioctl+0x6f/0x80 [] syscall_call+0x7/0xb [] ? die+0x31/0x80 [] ? die+0x31/0x80 Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org --- drivers/gpu/drm/nouveau/nouveau_gem.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 5f0bc57fdaab..7ce3fde40743 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -379,6 +379,25 @@ retry: return 0; } +static int +validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo) +{ + struct nouveau_fence *fence = NULL; + int ret = 0; + + spin_lock(&nvbo->bo.bdev->fence_lock); + if (nvbo->bo.sync_obj) + fence = nouveau_fence_ref(nvbo->bo.sync_obj); + spin_unlock(&nvbo->bo.bdev->fence_lock); + + if (fence) { + ret = nouveau_fence_sync(fence, chan); + nouveau_fence_unref(&fence); + } + + return ret; +} + static int validate_list(struct nouveau_channel *chan, struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr) @@ -393,7 +412,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, list_for_each_entry(nvbo, list, entry) { struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; - ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); + ret = validate_sync(chan, nvbo); if (unlikely(ret)) { NV_ERROR(dev, "fail pre-validate sync\n"); return ret; @@ -416,7 +435,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, return ret; } - ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); + ret = validate_sync(chan, nvbo); if (unlikely(ret)) { NV_ERROR(dev, "fail post-validate sync\n"); return ret; From a9d993882008a1ae2c953064f0c2ca7e604b1333 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 Jan 2012 10:20:47 +0300 Subject: [PATCH 248/380] drm/nv50/pm: signedness bug in nv50_pm_clocks_pre() calc_mclk() returns zero on success and negative on failure but clk is a u32. v2: Martin Peres: - clk should be an int, not a u32 Signed-off-by: Martin Peres Signed-off-by: Dan Carpenter Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 03937212e9d8..ec5481dfcd82 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -495,9 +495,9 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_pm_state *info; struct pll_lims pll; - int ret = -EINVAL; + int clk, ret = -EINVAL; int N, M, P1, P2; - u32 clk, out; + u32 out; if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) From f70eecde3bca92630d3886496e73316ff353f185 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Tue, 31 Jan 2012 13:04:41 -0800 Subject: [PATCH 249/380] ALSA: hda - Fix calling cs_automic twice for Cirrus codecs. If cs_automic is called twice (like it is during init) while the mic is present, it will over-write the last_input with the new one, causing it to switch back to the automic input when the mic is unplugged. This leaves the driver in a state (cur_input, last_input, and automix_idx the same) where the internal mic can not be selected until it is rebooted without the mic attached. Check that the mic hasn't already been switched to before setting last_input. Signed-off-by: Dylan Reid Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_cirrus.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 0e99357e822c..bc5a993d1146 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -988,8 +988,10 @@ static void cs_automic(struct hda_codec *codec) change_cur_input(codec, !spec->automic_idx, 0); } else { if (present) { - spec->last_input = spec->cur_input; - spec->cur_input = spec->automic_idx; + if (spec->cur_input != spec->automic_idx) { + spec->last_input = spec->cur_input; + spec->cur_input = spec->automic_idx; + } } else { spec->cur_input = spec->last_input; } From 50e92b3c971129c96a5fffb51dd42691e2ee4004 Mon Sep 17 00:00:00 2001 From: Takuya Yoshikawa Date: Wed, 4 Jan 2012 15:06:43 +0900 Subject: [PATCH 250/380] KVM: Fix __set_bit() race in mark_page_dirty() during dirty logging It is possible that the __set_bit() in mark_page_dirty() is called simultaneously on the same region of memory, which may result in only one bit being set, because some callers do not take mmu_lock before mark_page_dirty(). This problem is hard to produce because when we reach mark_page_dirty() beginning from, e.g., tdp_page_fault(), mmu_lock is being held during __direct_map(): making kvm-unit-tests' dirty log api test write to two pages concurrently was not useful for this reason. So we have confirmed that there can actually be race condition by checking if some callers really reach there without holding mmu_lock using spin_is_locked(): probably they were from kvm_write_guest_page(). To fix this race, this patch changes the bit operation to the atomic version: note that nr_dirty_pages also suffers from the race but we do not need exactly correct numbers for now. Signed-off-by: Takuya Yoshikawa Signed-off-by: Marcelo Tosatti --- virt/kvm/kvm_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 7287bf5d1c9e..a91f980077d8 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1543,7 +1543,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot, if (memslot && memslot->dirty_bitmap) { unsigned long rel_gfn = gfn - memslot->base_gfn; - if (!__test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap)) + if (!test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap)) memslot->nr_dirty_pages++; } } From bdb42f5afebe208eae90406959383856ae2caf2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= Date: Thu, 12 Jan 2012 16:43:03 +0100 Subject: [PATCH 251/380] KVM: x86: extend "struct x86_emulate_ops" with "get_cpuid" In order to be able to proceed checks on CPU-specific properties within the emulator, function "get_cpuid" is introduced. With "get_cpuid" it is possible to virtually call the guests "cpuid"-opcode without changing the VM's context. [mtosatti: cleanup/beautify code] Signed-off-by: Stephan Baerwolf Signed-off-by: Marcelo Tosatti --- arch/x86/include/asm/kvm_emulate.h | 3 +++ arch/x86/kvm/x86.c | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index ab4092e3214e..c8b28689eeeb 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -190,6 +190,9 @@ struct x86_emulate_ops { int (*intercept)(struct x86_emulate_ctxt *ctxt, struct x86_instruction_info *info, enum x86_intercept_stage stage); + + bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, + u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); }; typedef u32 __attribute__((vector_size(16))) sse128_t; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 14d6cadc4ba6..8c890e2fa6b6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4180,6 +4180,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt, return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage); } +static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, + u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) +{ + struct kvm_cpuid_entry2 *cpuid = NULL; + + if (eax && ecx) + cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt), + *eax, *ecx); + + if (cpuid) { + *eax = cpuid->eax; + *ecx = cpuid->ecx; + if (ebx) + *ebx = cpuid->ebx; + if (edx) + *edx = cpuid->edx; + return true; + } + + return false; +} + static struct x86_emulate_ops emulate_ops = { .read_std = kvm_read_guest_virt_system, .write_std = kvm_write_guest_virt_system, @@ -4211,6 +4233,7 @@ static struct x86_emulate_ops emulate_ops = { .get_fpu = emulator_get_fpu, .put_fpu = emulator_put_fpu, .intercept = emulator_intercept, + .get_cpuid = emulator_get_cpuid, }; static void cache_all_regs(struct kvm_vcpu *vcpu) From c2226fc9e87ba3da060e47333657cd6616652b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= Date: Thu, 12 Jan 2012 16:43:04 +0100 Subject: [PATCH 252/380] KVM: x86: fix missing checks in syscall emulation On hosts without this patch, 32bit guests will crash (and 64bit guests may behave in a wrong way) for example by simply executing following nasm-demo-application: [bits 32] global _start SECTION .text _start: syscall (I tested it with winxp and linux - both always crashed) Disassembly of section .text: 00000000 <_start>: 0: 0f 05 syscall The reason seems a missing "invalid opcode"-trap (int6) for the syscall opcode "0f05", which is not available on Intel CPUs within non-longmodes, as also on some AMD CPUs within legacy-mode. (depending on CPU vendor, MSR_EFER and cpuid) Because previous mentioned OSs may not engage corresponding syscall target-registers (STAR, LSTAR, CSTAR), they remain NULL and (non trapping) syscalls are leading to multiple faults and finally crashs. Depending on the architecture (AMD or Intel) pretended by guests, various checks according to vendor's documentation are implemented to overcome the current issue and behave like the CPUs physical counterparts. [mtosatti: cleanup/beautify code] Signed-off-by: Stephan Baerwolf Signed-off-by: Marcelo Tosatti --- arch/x86/include/asm/kvm_emulate.h | 13 ++++++++ arch/x86/kvm/emulate.c | 51 ++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index c8b28689eeeb..7b9cfc4878af 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -301,6 +301,19 @@ struct x86_emulate_ctxt { #define X86EMUL_MODE_PROT (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \ X86EMUL_MODE_PROT64) +/* CPUID vendors */ +#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541 +#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163 +#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65 + +#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41 +#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574 +#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273 + +#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547 +#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e +#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69 + enum x86_intercept_stage { X86_ICTP_NONE = 0, /* Allow zero-init to not match anything */ X86_ICPT_PRE_EXCEPT, diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 05a562b85025..0982507b962a 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, ss->p = 1; } +static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) +{ + struct x86_emulate_ops *ops = ctxt->ops; + u32 eax, ebx, ecx, edx; + + /* + * syscall should always be enabled in longmode - so only become + * vendor specific (cpuid) if other modes are active... + */ + if (ctxt->mode == X86EMUL_MODE_PROT64) + return true; + + eax = 0x00000000; + ecx = 0x00000000; + if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) { + /* + * Intel ("GenuineIntel") + * remark: Intel CPUs only support "syscall" in 64bit + * longmode. Also an 64bit guest with a + * 32bit compat-app running will #UD !! While this + * behaviour can be fixed (by emulating) into AMD + * response - CPUs of AMD can't behave like Intel. + */ + if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx && + ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx && + edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx) + return false; + + /* AMD ("AuthenticAMD") */ + if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx && + ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx && + edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) + return true; + + /* AMD ("AMDisbetter!") */ + if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx && + ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx && + edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx) + return true; + } + + /* default: (not Intel, not AMD), apply Intel's stricter rules... */ + return false; +} + static int em_syscall(struct x86_emulate_ctxt *ctxt) { struct x86_emulate_ops *ops = ctxt->ops; @@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt) ctxt->mode == X86EMUL_MODE_VM86) return emulate_ud(ctxt); + if (!(em_syscall_is_enabled(ctxt))) + return emulate_ud(ctxt); + ops->get_msr(ctxt, MSR_EFER, &efer); setup_syscalls_segments(ctxt, &cs, &ss); + if (!(efer & EFER_SCE)) + return emulate_ud(ctxt); + ops->get_msr(ctxt, MSR_STAR, &msr_data); msr_data >>= 32; cs_sel = (u16)(msr_data & 0xfffc); From 5753785fa97742d2723ed8ebb29ae59cac912705 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Sun, 15 Jan 2012 14:17:22 +0200 Subject: [PATCH 253/380] KVM: do not #GP on perf MSR writes when vPMU is disabled Return to behaviour perf MSR had before introducing vPMU in case vPMU is disabled. Some guests access those registers unconditionally and do not expect it to fail. Signed-off-by: Gleb Natapov Signed-off-by: Marcelo Tosatti --- arch/x86/kvm/x86.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 8c890e2fa6b6..9cbfc0698118 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1495,6 +1495,8 @@ static void record_steal_time(struct kvm_vcpu *vcpu) int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) { + bool pr = false; + switch (msr) { case MSR_EFER: return set_efer(vcpu, data); @@ -1635,6 +1637,18 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) pr_unimpl(vcpu, "unimplemented perfctr wrmsr: " "0x%x data 0x%llx\n", msr, data); break; + case MSR_P6_PERFCTR0: + case MSR_P6_PERFCTR1: + pr = true; + case MSR_P6_EVNTSEL0: + case MSR_P6_EVNTSEL1: + if (kvm_pmu_msr(vcpu, msr)) + return kvm_pmu_set_msr(vcpu, msr, data); + + if (pr || data != 0) + pr_unimpl(vcpu, "disabled perfctr wrmsr: " + "0x%x data 0x%llx\n", msr, data); + break; case MSR_K7_CLK_CTL: /* * Ignore all writes to this no longer documented MSR. @@ -1835,6 +1849,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) case MSR_FAM10H_MMIO_CONF_BASE: data = 0; break; + case MSR_P6_PERFCTR0: + case MSR_P6_PERFCTR1: + case MSR_P6_EVNTSEL0: + case MSR_P6_EVNTSEL1: + if (kvm_pmu_msr(vcpu, msr)) + return kvm_pmu_get_msr(vcpu, msr, pdata); + data = 0; + break; case MSR_IA32_UCODE_REV: data = 0x100000000ULL; break; From 2b6712b19531e22455e7fa18371c5ba9eec76699 Mon Sep 17 00:00:00 2001 From: Susan Gao Date: Mon, 30 Jan 2012 13:57:04 -0800 Subject: [PATCH 254/380] ASoC: wm8962: Fix word length configuration Signed-off-by: Susan Gao Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8962.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index bda3da887d7e..29c4b02c4790 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3159,13 +3159,13 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream, case SNDRV_PCM_FORMAT_S16_LE: break; case SNDRV_PCM_FORMAT_S20_3LE: - aif0 |= 0x40; + aif0 |= 0x4; break; case SNDRV_PCM_FORMAT_S24_LE: - aif0 |= 0x80; + aif0 |= 0x8; break; case SNDRV_PCM_FORMAT_S32_LE: - aif0 |= 0xc0; + aif0 |= 0xc; break; default: return -EINVAL; From 44bed4838dc191988fd1d03deccc3a845705d2de Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 31 Jan 2012 09:49:04 +0800 Subject: [PATCH 255/380] ASoC: cs42l73: Fix Output [X|A|V]SP_SCLK Sourcing Mode setting for master mode For master mode, set Output [X|A|V]SP_SCLK Sourcing Mode to MCLK Mode. Signed-off-by: Axel Lin Acked-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l73.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 9d38db8f1919..78979b3e0e95 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1113,7 +1113,7 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream, priv->config[id].mmcc &= 0xC0; priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc; priv->config[id].spc &= 0xFC; - priv->config[id].spc &= MCK_SCLK_64FS; + priv->config[id].spc |= MCK_SCLK_MCLK; } else { /* CS42L73 Slave */ priv->config[id].spc &= 0xFC; From 54c2a89f60fd71b924d0f848ac892442951401a6 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Wed, 1 Feb 2012 12:05:41 +0100 Subject: [PATCH 256/380] ALSA: HDA: Fix duplicated output to more than one codec This typo caused the wrong codec's nid to be checked for wcaps type. As a result, sometimes speakers would duplicate the output sent to HDMI output. Cc: stable@kernel.org BugLink: https://bugs.launchpad.net/bugs/924320 Signed-off-by: David Henningsson Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4df72c0e8c37..c2c65f63bf06 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1447,7 +1447,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, for (i = 0; i < c->cvt_setups.used; i++) { p = snd_array_elem(&c->cvt_setups, i); if (!p->active && p->stream_tag == stream_tag && - get_wcaps_type(get_wcaps(codec, p->nid)) == type) + get_wcaps_type(get_wcaps(c, p->nid)) == type) p->dirty = 1; } } From c70c471c585a3fc1a10c792d5121b3803c83dde0 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:17 +0200 Subject: [PATCH 257/380] lib/mpi: added missing NULL check Added missing NULL check after mpi_alloc(). Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/mpi/mpicoder.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 716802b774ea..6116fc4990da 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -79,7 +79,8 @@ MPI do_encode_md(const void *sha_buffer, unsigned nbits) } a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB); - mpi_set_buffer(a, frame, nframe, 0); + if (a) + mpi_set_buffer(a, frame, nframe, 0); kfree(frame); return a; From 3cccd1543ab623a5065335bf08350e06ffc788ab Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:16 +0200 Subject: [PATCH 258/380] lib/mpi: replaced MPI_NULL with normal NULL MPI_NULL is replaced with normal NULL. Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- include/linux/mpi.h | 2 -- lib/mpi/mpicoder.c | 8 ++++---- lib/mpi/mpiutil.c | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/linux/mpi.h b/include/linux/mpi.h index 06f88994ccaa..d02cca6cc8ce 100644 --- a/include/linux/mpi.h +++ b/include/linux/mpi.h @@ -57,8 +57,6 @@ struct gcry_mpi { typedef struct gcry_mpi *MPI; -#define MPI_NULL NULL - #define mpi_get_nlimbs(a) ((a)->nlimbs) #define mpi_is_neg(a) ((a)->sign) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 6116fc4990da..d7684aa7f65c 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -34,7 +34,7 @@ MPI do_encode_md(const void *sha_buffer, unsigned nbits) uint8_t *frame, *fr_pt; int i = 0, n; size_t asnlen = DIM(asn); - MPI a = MPI_NULL; + MPI a = NULL; if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe) pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n", @@ -48,7 +48,7 @@ MPI do_encode_md(const void *sha_buffer, unsigned nbits) */ frame = kmalloc(nframe, GFP_KERNEL); if (!frame) - return MPI_NULL; + return NULL; n = 0; frame[n++] = 0; frame[n++] = 1; /* block type */ @@ -92,7 +92,7 @@ MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) int i, j; unsigned nbits, nbytes, nlimbs, nread = 0; mpi_limb_t a; - MPI val = MPI_NULL; + MPI val = NULL; if (*ret_nread < 2) goto leave; @@ -109,7 +109,7 @@ MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; val = mpi_alloc(nlimbs); if (!val) - return MPI_NULL; + return NULL; i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; i %= BYTES_PER_MPI_LIMB; val->nbits = nbits; diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c index eefc55d6b7f5..6bfc41f62b8f 100644 --- a/lib/mpi/mpiutil.c +++ b/lib/mpi/mpiutil.c @@ -135,7 +135,7 @@ int mpi_copy(MPI *copied, const MPI a) size_t i; MPI b; - *copied = MPI_NULL; + *copied = NULL; if (a) { b = mpi_alloc(a->nlimbs); From e87c5e35a92e045de75fb6ae9846a38bdd0f92bd Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:21 +0200 Subject: [PATCH 259/380] lib/mpi: return error code on dividing by zero Definitely better to return error code than to divide by zero. Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/mpi/mpi-pow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c index b04a3cf80080..67f3e79af914 100644 --- a/lib/mpi/mpi-pow.c +++ b/lib/mpi/mpi-pow.c @@ -59,7 +59,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) ep = exp->d; if (!msize) - msize = 1 / msize; /* provoke a signal */ + return -EINVAL; if (!esize) { /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 From e2fe85c236736c866481de288f636ab06ef49787 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:22 +0200 Subject: [PATCH 260/380] lib/mpi: checks for zero divisor length Divisor length should not be 0. Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/mpi/mpi-div.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c index c3087d1390ce..8a45717bd001 100644 --- a/lib/mpi/mpi-div.c +++ b/lib/mpi/mpi-div.c @@ -149,6 +149,9 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den) mpi_ptr_t marker[5]; int markidx = 0; + if (!dsize) + return -EINVAL; + memset(marker, 0, sizeof(marker)); /* Ensure space is enough for quotient and remainder. From bc95eeadf5c6fd9e9840898a83a93718a0114b6d Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:23 +0200 Subject: [PATCH 261/380] lib/mpi: removed unused functions do_encode_md() and mpi_get_keyid() are not parts of mpi library. They were used early versions of gnupg and in digsig project, but they are not used neither here nor there anymore. Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/mpi/mpicoder.c | 88 ---------------------------------------------- 1 file changed, 88 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index d7684aa7f65c..f26b41fcb48c 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -20,72 +20,8 @@ #include "mpi-internal.h" -#define DIM(v) (sizeof(v)/sizeof((v)[0])) #define MAX_EXTERN_MPI_BITS 16384 -static uint8_t asn[15] = /* Object ID is 1.3.14.3.2.26 */ -{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, - 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 -}; - -MPI do_encode_md(const void *sha_buffer, unsigned nbits) -{ - int nframe = (nbits + 7) / 8; - uint8_t *frame, *fr_pt; - int i = 0, n; - size_t asnlen = DIM(asn); - MPI a = NULL; - - if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe) - pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n", - (int)(SHA1_DIGEST_LENGTH * 8), (int)nbits); - - /* We encode the MD in this way: - * - * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) - * - * PAD consists of FF bytes. - */ - frame = kmalloc(nframe, GFP_KERNEL); - if (!frame) - return NULL; - n = 0; - frame[n++] = 0; - frame[n++] = 1; /* block type */ - i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3; - - if (i <= 1) { - pr_info("MPI: message digest encoding failed\n"); - kfree(frame); - return a; - } - - memset(frame + n, 0xff, i); - n += i; - frame[n++] = 0; - memcpy(frame + n, &asn, asnlen); - n += asnlen; - memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH); - n += SHA1_DIGEST_LENGTH; - - i = nframe; - fr_pt = frame; - - if (n != nframe) { - printk - ("MPI: message digest encoding failed, frame length is wrong\n"); - kfree(frame); - return a; - } - - a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB); - if (a) - mpi_set_buffer(a, frame, nframe, 0); - kfree(frame); - - return a; -} - MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) { const uint8_t *buffer = xbuffer; @@ -212,30 +148,6 @@ int mpi_fromstr(MPI val, const char *str) } EXPORT_SYMBOL_GPL(mpi_fromstr); -/**************** - * Special function to get the low 8 bytes from an mpi. - * This can be used as a keyid; KEYID is an 2 element array. - * Return the low 4 bytes. - */ -u32 mpi_get_keyid(const MPI a, u32 *keyid) -{ -#if BYTES_PER_MPI_LIMB == 4 - if (keyid) { - keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0; - keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0; - } - return a->nlimbs >= 1 ? a->d[0] : 0; -#elif BYTES_PER_MPI_LIMB == 8 - if (keyid) { - keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0; - keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0; - } - return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0; -#else -#error Make this function work with other LIMB sizes -#endif -} - /**************** * Return an allocated buffer with the MPI (msb first). * NBYTES receives the length of this buffer. Caller must free the From f58a08152ce4198a2a1da162b97ecf8264c24866 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:25 +0200 Subject: [PATCH 262/380] lib/digsig: additional sanity checks against badly formated key payload Added sanity checks for possible wrongly formatted key payload data: - minimum key payload size - zero modulus length - corrected upper key payload boundary. Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/digsig.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/digsig.c b/lib/digsig.c index fd2402f67f89..5d840ac64fb1 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -105,6 +105,10 @@ static int digsig_verify_rsa(struct key *key, down_read(&key->sem); ukp = key->payload.data; + + if (ukp->datalen < sizeof(*pkh)) + goto err1; + pkh = (struct pubkey_hdr *)ukp->data; if (pkh->version != 1) @@ -117,7 +121,7 @@ static int digsig_verify_rsa(struct key *key, goto err1; datap = pkh->mpi; - endp = datap + ukp->datalen; + endp = ukp->data + ukp->datalen; for (i = 0; i < pkh->nmpi; i++) { unsigned int remaining = endp - datap; @@ -128,7 +132,8 @@ static int digsig_verify_rsa(struct key *key, mblen = mpi_get_nbits(pkey[0]); mlen = (mblen + 7)/8; - err = -ENOMEM; + if (mlen == 0) + goto err; out1 = kzalloc(mlen, GFP_KERNEL); if (!out1) From b35e286a640f31d619a637332972498b51f3fd90 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:26 +0200 Subject: [PATCH 263/380] lib/digsig: pkcs_1_v1_5_decode_emsa cleanup Removed useless 'is_valid' variable in pkcs_1_v1_5_decode_emsa(), which was inhereted from original code. Client now uses return value to check for an error. Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/digsig.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/lib/digsig.c b/lib/digsig.c index 5d840ac64fb1..b67e82c024b3 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -34,14 +34,9 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg, unsigned long msglen, unsigned long modulus_bitlen, unsigned char *out, - unsigned long *outlen, - int *is_valid) + unsigned long *outlen) { unsigned long modulus_len, ps_len, i; - int result; - - /* default to invalid packet */ - *is_valid = 0; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); @@ -50,39 +45,30 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg, return -EINVAL; /* separate encoded message */ - if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) { - result = -EINVAL; - goto bail; - } + if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) + return -EINVAL; for (i = 2; i < modulus_len - 1; i++) if (msg[i] != 0xFF) break; /* separator check */ - if (msg[i] != 0) { + if (msg[i] != 0) /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ - result = -EINVAL; - goto bail; - } + return -EINVAL; ps_len = i - 2; if (*outlen < (msglen - (2 + ps_len + 1))) { *outlen = msglen - (2 + ps_len + 1); - result = -EOVERFLOW; - goto bail; + return -EOVERFLOW; } *outlen = (msglen - (2 + ps_len + 1)); memcpy(out, &msg[2 + ps_len + 1], *outlen); - /* valid packet */ - *is_valid = 1; - result = 0; -bail: - return result; + return 0; } /* @@ -96,7 +82,7 @@ static int digsig_verify_rsa(struct key *key, unsigned long len; unsigned long mlen, mblen; unsigned nret, l; - int valid, head, i; + int head, i; unsigned char *out1 = NULL, *out2 = NULL; MPI in = NULL, res = NULL, pkey[2]; uint8_t *p, *datap, *endp; @@ -172,10 +158,9 @@ static int digsig_verify_rsa(struct key *key, memset(out1, 0, head); memcpy(out1 + head, p, l); - err = -EINVAL; - pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len, &valid); + err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len); - if (valid && len == hlen) + if (!err && len == hlen) err = memcmp(out2, h, hlen); err: From 4877e056192245b387aae004ab38f7f3899dd57c Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:19 +0200 Subject: [PATCH 264/380] lib/mpi: check for possible zero length Buggy client might pass zero nlimbs which is meaningless. Added check for zero length. Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/mpi/mpiutil.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c index 6bfc41f62b8f..26e4ed31e256 100644 --- a/lib/mpi/mpiutil.c +++ b/lib/mpi/mpiutil.c @@ -58,6 +58,9 @@ mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs) { size_t len = nlimbs * sizeof(mpi_limb_t); + if (!len) + return NULL; + return kmalloc(len, GFP_KERNEL); } From a6d68ecc56ed182644c81ef6917ce1f5404db7dd Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:20 +0200 Subject: [PATCH 265/380] lib/mpi: added comment on divide by 0 case Comment explains that existing clients do not call this function with dsize == 0, which means that 1/0 should not happen. Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/mpi/mpih-div.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/mpi/mpih-div.c b/lib/mpi/mpih-div.c index 87ede162dfab..cde1aaec18da 100644 --- a/lib/mpi/mpih-div.c +++ b/lib/mpi/mpih-div.c @@ -217,6 +217,10 @@ mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs, case 0: /* We are asked to divide by zero, so go ahead and do it! (To make the compiler not remove this statement, return the value.) */ + /* + * existing clients of this function have been modified + * not to call it with dsize == 0, so this should not happen + */ return 1 / dsize; case 1: From 43b2c0aeaab2237996a72f9b9d7952ba82d56913 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:18 +0200 Subject: [PATCH 266/380] lib/mpi: added missing NULL check Added missing NULL check after mpi_alloc_limb_space(). Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/mpi/mpi-div.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c index 8a45717bd001..f68cbbb4d4a4 100644 --- a/lib/mpi/mpi-div.c +++ b/lib/mpi/mpi-div.c @@ -210,6 +210,8 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den) * numerator would be gradually overwritten by the quotient limbs. */ if (qp == np) { /* Copy NP object to temporary space. */ np = marker[markidx++] = mpi_alloc_limb_space(nsize); + if (!np) + goto nomem; MPN_COPY(np, qp, nsize); } } else /* Put quotient at top of remainder. */ From 86f8bedc9e1a8ddb4f1d9ff1f0c1229cc0797d6d Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 26 Jan 2012 19:13:24 +0200 Subject: [PATCH 267/380] lib/digsig: checks for NULL return value mpi_read_from_buffer() return value must not be NULL. Signed-off-by: Dmitry Kasatkin Reviewed-by: Tetsuo Handa Signed-off-by: James Morris --- lib/digsig.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/digsig.c b/lib/digsig.c index b67e82c024b3..286d558033e2 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -109,9 +109,13 @@ static int digsig_verify_rsa(struct key *key, datap = pkh->mpi; endp = ukp->data + ukp->datalen; + err = -ENOMEM; + for (i = 0; i < pkh->nmpi; i++) { unsigned int remaining = endp - datap; pkey[i] = mpi_read_from_buffer(datap, &remaining); + if (!pkey[i]) + goto err; datap += remaining; } @@ -168,8 +172,8 @@ err: mpi_free(res); kfree(out1); kfree(out2); - mpi_free(pkey[0]); - mpi_free(pkey[1]); + while (--i >= 0) + mpi_free(pkey[i]); err1: up_read(&key->sem); From 86698c20f71d488b32c49ed4687fb3cf8a88a5ca Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Tue, 31 Jan 2012 19:06:25 -0600 Subject: [PATCH 268/380] drm/radeon/kms: disable output polling when suspended Polling the outputs when the device is suspended can result in erroneous status updates. Disable output polling during suspend to prevent this from happening. Signed-off-by: Seth Forshee Reviewed-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index cec51a5b69dd..49f7cb7e226b 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -883,6 +883,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; + drm_kms_helper_poll_disable(dev); + /* turn off display hw */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); @@ -972,6 +974,8 @@ int radeon_resume_kms(struct drm_device *dev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); } + + drm_kms_helper_poll_enable(dev); return 0; } From 1b61925061660009f5b8047f93c5297e04541273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 1 Feb 2012 12:09:55 +0100 Subject: [PATCH 269/380] drm/radeon: Set DESKTOP_HEIGHT register to the framebuffer (not mode) height. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The value of this register is transferred to the V_COUNTER register at the beginning of vertical blank. V_COUNTER is the reference for VLINE waits and goes from VIEWPORT_Y_START to VIEWPORT_Y_START+VIEWPORT_HEIGHT during scanout, so if VIEWPORT_Y_START is not 0, V_COUNTER actually went backwards at the beginning of vertical blank, and VLINE waits excluding the whole scanout area could never finish (possibly only if VIEWPORT_Y_START is larger than the length of vertical blank in scanlines). Setting DESKTOP_HEIGHT to the framebuffer height should prevent this for any kind of VLINE wait. Fixes https://bugs.freedesktop.org/show_bug.cgi?id=45329 . CC: stable@vger.kernel.org Signed-off-by: Michel Dänzer Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 891935271d34..742f17f009a9 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1184,7 +1184,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, - crtc->mode.vdisplay); + target_fb->height); x &= ~3; y &= ~1; WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, @@ -1353,7 +1353,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, - crtc->mode.vdisplay); + target_fb->height); x &= ~3; y &= ~1; WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, From 3f7e363249ad5f4070025f6c09fd264f93f24eab Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 31 Jan 2012 09:55:21 +0100 Subject: [PATCH 270/380] drm/radeon/kms: Fix device tree linkage of DP i2c buses too Properly set the parent device of DP i2c buses before registering them too. Signed-off-by: Jean Delvare Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_i2c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index e2a393ff0c44..98a8ad680109 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -958,6 +958,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, i2c->rec = *rec; i2c->adapter.owner = THIS_MODULE; i2c->adapter.class = I2C_CLASS_DDC; + i2c->adapter.dev.parent = &dev->pdev->dev; i2c->dev = dev; snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "Radeon aux bus %s", name); From e9c8d7a03e69093e4c33c5056a45c1233a42e8a4 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 18 Jan 2012 10:14:25 +0100 Subject: [PATCH 271/380] dma: sh_dma: not all SH DMAC implementations support MEMCPY Add a flag to allow platforms to specify, whether a DMAC instance supports the MEMCPY operation. To avoid regressions, preserve the current default. Signed-off-by: Guennadi Liakhovetski Acked-by: Paul Mundt Signed-off-by: Vinod Koul --- drivers/dma/shdma.c | 3 ++- include/linux/sh_dma.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 54043cd831c8..812fd76e9c18 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -1262,7 +1262,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev) INIT_LIST_HEAD(&shdev->common.channels); - dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask); + if (!pdata->slave_only) + dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask); if (pdata->slave && pdata->slave_num) dma_cap_set(DMA_SLAVE, shdev->common.cap_mask); diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index 8cd7fe59cf1a..425450b980b8 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -70,6 +70,7 @@ struct sh_dmae_pdata { unsigned int needs_tend_set:1; unsigned int no_dmars:1; unsigned int chclr_present:1; + unsigned int slave_only:1; }; /* DMA register */ From c8ddf036d99e7fab943b7587c75a905e789ea7e7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 18 Jan 2012 10:14:29 +0100 Subject: [PATCH 272/380] ARM: mach-shmobile: both USB DMAC instances on sh7372 are slave-only Signed-off-by: Guennadi Liakhovetski Acked-by: Paul Mundt Signed-off-by: Vinod Koul --- arch/arm/mach-shmobile/setup-sh7372.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 6fcf304d3cdf..a83cf51fc099 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -662,6 +662,7 @@ static struct sh_dmae_pdata usb_dma0_platform_data = { .dmaor_is_32bit = 1, .needs_tend_set = 1, .no_dmars = 1, + .slave_only = 1, }; static struct resource sh7372_usb_dmae0_resources[] = { @@ -723,6 +724,7 @@ static struct sh_dmae_pdata usb_dma1_platform_data = { .dmaor_is_32bit = 1, .needs_tend_set = 1, .no_dmars = 1, + .slave_only = 1, }; static struct resource sh7372_usb_dmae1_resources[] = { From 42f578741bc59dc871bef03ff0f72dd197388409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Wed, 1 Feb 2012 09:12:23 -0800 Subject: [PATCH 273/380] Input: evdev - fix variable initialisation Commit 509f87c5f564 (evdev - do not block waiting for an event if fd is nonblock) created a code path were it was possible to use retval uninitialized. This could lead to the xorg evdev input driver getting corrupt data and refusing to work with log messages like AUO-Pixcir touchscreen: Read error: Success sg060_keys: Read error: Success AUO-Pixcir touchscreen: Read error: Success sg060_keys: Read error: Success (for drivers auo-pixcir-ts and gpio-keys). Signed-off-by: Heiko Stuebner Acked-by: Dima Zavin Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 76457d50bc34..afc166fcc3d9 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -386,7 +386,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; struct input_event event; - int retval; + int retval = 0; if (count < input_event_size()) return -EINVAL; From b18db3d91234c03ad080d317878c7c77672ba326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Wed, 1 Feb 2012 09:12:24 -0800 Subject: [PATCH 274/380] Input: gpio_keys - fix struct device declared inside parameter list A struct device parameter is used in the enable and disable callbacks to distinguish between different gpio_keys devices. Platforms that don't use these callbacks may not include struct device at all, as seen on arch/arm/mach-s3c2410/mach-n30.c Signed-off-by: Heiko Stuebner Signed-off-by: Dmitry Torokhov --- include/linux/gpio_keys.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h index b5ca4b2c08ec..004ff33ab38e 100644 --- a/include/linux/gpio_keys.h +++ b/include/linux/gpio_keys.h @@ -1,6 +1,8 @@ #ifndef _GPIO_KEYS_H #define _GPIO_KEYS_H +struct device; + struct gpio_keys_button { /* Configuration parameters */ unsigned int code; /* input event code (KEY_*, SW_*) */ From 4936f97cbb99c19680ea6a3cc0148ebe51f0eb68 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Wed, 1 Feb 2012 09:12:23 -0800 Subject: [PATCH 275/380] Input: twl4030_keypad - fix comment (trivial) And trivial whitespace fixes. Signed-off-by: Felipe Contreras Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/twl4030_keypad.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index a588578037eb..67bec14e8b96 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -34,7 +34,6 @@ #include #include - /* * The TWL4030 family chips include a keypad controller that supports * up to an 8x8 switch matrix. The controller can issue system wakeup @@ -302,7 +301,7 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0) return -EIO; - /* Set timeout period to 100 ms */ + /* Set timeout period to 200 ms */ i = KEYP_PERIOD_US(200000, PTV_PRESCALER); if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0) return -EIO; @@ -466,4 +465,3 @@ MODULE_AUTHOR("Texas Instruments"); MODULE_DESCRIPTION("TWL4030 Keypad Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:twl4030_keypad"); - From d04df0232d6b5172dc1958df1829abd0214c8969 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Wed, 1 Feb 2012 09:12:24 -0800 Subject: [PATCH 276/380] Input: document device properties Add a section which defines the input device properties and provides guidelines on how to use them. Signed-off-by: Henrik Rydberg Reviewed-by: Chase Douglas Reviewed-by: Jussi Pakkanen Signed-off-by: Dmitry Torokhov --- Documentation/input/event-codes.txt | 72 +++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt index 23fcb05175be..53305bd08182 100644 --- a/Documentation/input/event-codes.txt +++ b/Documentation/input/event-codes.txt @@ -17,11 +17,11 @@ reports supported by a device are also provided by sysfs in class/input/event*/device/capabilities/, and the properties of a device are provided in class/input/event*/device/properties. -Types: -========== -Types are groupings of codes under a logical input construct. Each type has a -set of applicable codes to be used in generating events. See the Codes section -for details on valid codes for each type. +Event types: +=========== +Event types are groupings of codes under a logical input construct. Each +type has a set of applicable codes to be used in generating events. See the +Codes section for details on valid codes for each type. * EV_SYN: - Used as markers to separate events. Events may be separated in time or in @@ -63,9 +63,9 @@ for details on valid codes for each type. * EV_FF_STATUS: - Used to receive force feedback device status. -Codes: -========== -Codes define the precise type of event. +Event codes: +=========== +Event codes define the precise type of event. EV_SYN: ---------- @@ -220,6 +220,56 @@ EV_PWR: EV_PWR events are a special type of event used specifically for power mangement. Its usage is not well defined. To be addressed later. +Device properties: +================= +Normally, userspace sets up an input device based on the data it emits, +i.e., the event types. In the case of two devices emitting the same event +types, additional information can be provided in the form of device +properties. + +INPUT_PROP_DIRECT + INPUT_PROP_POINTER: +-------------------------------------- +The INPUT_PROP_DIRECT property indicates that device coordinates should be +directly mapped to screen coordinates (not taking into account trivial +transformations, such as scaling, flipping and rotating). Non-direct input +devices require non-trivial transformation, such as absolute to relative +transformation for touchpads. Typical direct input devices: touchscreens, +drawing tablets; non-direct devices: touchpads, mice. + +The INPUT_PROP_POINTER property indicates that the device is not transposed +on the screen and thus requires use of an on-screen pointer to trace user's +movements. Typical pointer devices: touchpads, tablets, mice; non-pointer +device: touchscreen. + +If neither INPUT_PROP_DIRECT or INPUT_PROP_POINTER are set, the property is +considered undefined and the device type should be deduced in the +traditional way, using emitted event types. + +INPUT_PROP_BUTTONPAD: +-------------------- +For touchpads where the button is placed beneath the surface, such that +pressing down on the pad causes a button click, this property should be +set. Common in clickpad notebooks and macbooks from 2009 and onwards. + +Originally, the buttonpad property was coded into the bcm5974 driver +version field under the name integrated button. For backwards +compatibility, both methods need to be checked in userspace. + +INPUT_PROP_SEMI_MT: +------------------ +Some touchpads, most common between 2008 and 2011, can detect the presence +of multiple contacts without resolving the individual positions; only the +number of contacts and a rectangular shape is known. For such +touchpads, the semi-mt property should be set. + +Depending on the device, the rectangle may enclose all touches, like a +bounding box, or just some of them, for instance the two most recent +touches. The diversity makes the rectangle of limited use, but some +gestures can normally be extracted from it. + +If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT +device. + Guidelines: ========== The guidelines below ensure proper single-touch and multi-finger functionality. @@ -240,6 +290,8 @@ used to report when a touch is active on the screen. BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch contact. BTN_TOOL_ events should be reported where possible. +For new hardware, INPUT_PROP_DIRECT should be set. + Trackpads: ---------- Legacy trackpads that only provide relative position information must report @@ -250,6 +302,8 @@ location of the touch. BTN_TOUCH should be used to report when a touch is active on the trackpad. Where multi-finger support is available, BTN_TOOL_ should be used to report the number of touches active on the trackpad. +For new hardware, INPUT_PROP_POINTER should be set. + Tablets: ---------- BTN_TOOL_ events must be reported when a stylus or other tool is active on @@ -260,3 +314,5 @@ button may be used for buttons on the tablet except BTN_{MOUSE,LEFT}. BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use meaningful buttons, like BTN_FORWARD, unless the button is labeled for that purpose on the device. + +For new hardware, both INPUT_PROP_DIRECT and INPUT_PROP_POINTER should be set. From 7a0a27d2ce38aee19a31fee8c12095f586eed393 Mon Sep 17 00:00:00 2001 From: Che-Liang Chiou Date: Wed, 1 Feb 2012 09:25:35 -0800 Subject: [PATCH 277/380] Input: serio_raw - return proper result when serio_raw_read fails serio_raw_read now returns (sometimes partially) successful number of bytes transferred to the caller, and only returns error code to the caller on completely failed transfers. Signed-off-by: Che-Liang Chiou Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio_raw.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 8250299fd64f..4494233d331a 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -164,7 +164,8 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, struct serio_raw_client *client = file->private_data; struct serio_raw *serio_raw = client->serio_raw; char uninitialized_var(c); - ssize_t retval = 0; + ssize_t read = 0; + int retval; if (serio_raw->dead) return -ENODEV; @@ -180,13 +181,15 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, if (serio_raw->dead) return -ENODEV; - while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) { - if (put_user(c, buffer++)) - return -EFAULT; - retval++; + while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { + if (put_user(c, buffer++)) { + retval = -EFAULT; + break; + } + read++; } - return retval; + return read ?: retval; } static ssize_t serio_raw_write(struct file *file, const char __user *buffer, From 7d731019218e49a9811f6d0adec4b1cfcb752bed Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 1 Feb 2012 11:10:24 -0800 Subject: [PATCH 278/380] mtd: fix merge conflict resolution breakage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes merge conflict resolution breakage introduced by merge d3712b9dfcf4 ("Merge tag 'for-linus' of git://github.com/prasad-joshi/logfs_upstream"). The commit changed 'mtd_can_have_bb()' function and made it always return zero, which is incorrect. Instead, we need it to return whether the underlying flash device can have bad eraseblocks or not. UBI needs this information because it affects how it handles the underlying flash. E.g., if the underlying flash is NOR, it cannot have bad blocks and any write or erase error is fatal, and all we can do is to switch to R/O mode. We do not need to reserve a pool of good eraseblocks for bad eraseblocks handling, and so on. This patch also removes 'mtd_can_have_bb()' invocations from Logfs to ensure correct Logfs behavior. I've tested that with this patch UBI works on top of NOR and NAND flashes emulated by mtdram and nandsim correspondingly. This patch is based on patch from Linus Torvalds. Signed-off-by: Artem Bityutskiy Acked-by: Jörn Engel Acked-by: Prasad Joshi Acked-by: Brian Norris Signed-off-by: Linus Torvalds --- fs/logfs/dev_mtd.c | 6 ------ include/linux/mtd/mtd.h | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c index e97404d611e0..9c501449450d 100644 --- a/fs/logfs/dev_mtd.c +++ b/fs/logfs/dev_mtd.c @@ -152,9 +152,6 @@ static struct page *logfs_mtd_find_first_sb(struct super_block *sb, u64 *ofs) filler_t *filler = logfs_mtd_readpage; struct mtd_info *mtd = super->s_mtd; - if (!mtd_can_have_bb(mtd)) - return NULL; - *ofs = 0; while (mtd_block_isbad(mtd, *ofs)) { *ofs += mtd->erasesize; @@ -172,9 +169,6 @@ static struct page *logfs_mtd_find_last_sb(struct super_block *sb, u64 *ofs) filler_t *filler = logfs_mtd_readpage; struct mtd_info *mtd = super->s_mtd; - if (!mtd_can_have_bb(mtd)) - return NULL; - *ofs = mtd->size - mtd->erasesize; while (mtd_block_isbad(mtd, *ofs)) { *ofs -= mtd->erasesize; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 221295208fd0..887ebe318c75 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -489,7 +489,7 @@ static inline int mtd_has_oob(const struct mtd_info *mtd) static inline int mtd_can_have_bb(const struct mtd_info *mtd) { - return 0; + return !!mtd->block_isbad; } /* Kernel-side ioctl definitions */ From 879a5a001b62a020e074d460b3a7c0fd993f9832 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Tue, 31 Jan 2012 20:02:00 -0800 Subject: [PATCH 279/380] MAINTAINERS: Greg's suse email address is dead My email address has changed, the suse.de one is now dead, so update all of my MAINTAINER entries with the correct one so that patches don't get lost. Also change the status of some of my entries as I'm supposed to be doing this stuff now for real. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- MAINTAINERS | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a1fce9a3ab20..252972b6c4a0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -159,7 +159,7 @@ S: Maintained F: drivers/net/ethernet/realtek/r8169.c 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER -M: Greg Kroah-Hartman +M: Greg Kroah-Hartman L: linux-serial@vger.kernel.org W: http://serial.sourceforge.net S: Maintained @@ -1783,9 +1783,9 @@ X: net/wireless/wext* CHAR and MISC DRIVERS M: Arnd Bergmann -M: Greg Kroah-Hartman +M: Greg Kroah-Hartman T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git -S: Maintained +S: Supported F: drivers/char/* F: drivers/misc/* @@ -2320,7 +2320,7 @@ F: lib/lru_cache.c F: Documentation/blockdev/drbd/ DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS -M: Greg Kroah-Hartman +M: Greg Kroah-Hartman T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git S: Supported F: Documentation/kobject.txt @@ -6276,15 +6276,15 @@ S: Maintained F: arch/alpha/kernel/srm_env.c STABLE BRANCH -M: Greg Kroah-Hartman +M: Greg Kroah-Hartman L: stable@vger.kernel.org -S: Maintained +S: Supported STAGING SUBSYSTEM -M: Greg Kroah-Hartman +M: Greg Kroah-Hartman T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git L: devel@driverdev.osuosl.org -S: Maintained +S: Supported F: drivers/staging/ STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS @@ -6669,8 +6669,8 @@ S: Maintained K: ^Subject:.*(?i)trivial TTY LAYER -M: Greg Kroah-Hartman -S: Maintained +M: Greg Kroah-Hartman +S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git F: drivers/tty/ F: drivers/tty/serial/serial_core.c @@ -6958,7 +6958,7 @@ S: Maintained F: drivers/usb/serial/digi_acceleport.c USB SERIAL DRIVER -M: Greg Kroah-Hartman +M: Greg Kroah-Hartman L: linux-usb@vger.kernel.org S: Supported F: Documentation/usb/usb-serial.txt @@ -6973,9 +6973,8 @@ S: Maintained F: drivers/usb/serial/empeg.c USB SERIAL KEYSPAN DRIVER -M: Greg Kroah-Hartman +M: Greg Kroah-Hartman L: linux-usb@vger.kernel.org -W: http://www.kroah.com/linux/ S: Maintained F: drivers/usb/serial/*keyspan* @@ -7003,7 +7002,7 @@ F: Documentation/video4linux/sn9c102.txt F: drivers/media/video/sn9c102/ USB SUBSYSTEM -M: Greg Kroah-Hartman +M: Greg Kroah-Hartman L: linux-usb@vger.kernel.org W: http://www.linux-usb.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git @@ -7090,7 +7089,7 @@ F: fs/hppfs/ USERSPACE I/O (UIO) M: "Hans J. Koch" -M: Greg Kroah-Hartman +M: Greg Kroah-Hartman S: Maintained F: Documentation/DocBook/uio-howto.tmpl F: drivers/uio/ From fe9161db2e6053da21e4649d77bbefaf3030b11d Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Wed, 1 Feb 2012 22:16:36 +0100 Subject: [PATCH 280/380] PM / Hibernate: Thaw kernel threads in SNAPSHOT_CREATE_IMAGE ioctl path In the SNAPSHOT_CREATE_IMAGE ioctl, if the call to hibernation_snapshot() fails, the frozen tasks are not thawed. And in the case of success, if we happen to exit due to a successful freezer test, all tasks (including those of userspace) are thawed, whereas actually we should have thawed only the kernel threads at that point. Fix both these issues. Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki Cc: stable@vger.kernel.org --- kernel/power/user.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/power/user.c b/kernel/power/user.c index e5a21a857302..3e100075b13c 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -249,13 +249,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, } pm_restore_gfp_mask(); error = hibernation_snapshot(data->platform_support); - if (!error) { + if (error) { + thaw_kernel_threads(); + } else { error = put_user(in_suspend, (int __user *)arg); if (!error && !freezer_test_done) data->ready = 1; if (freezer_test_done) { freezer_test_done = false; - thaw_processes(); + thaw_kernel_threads(); } } break; From 71879d3cb3dd8f2dfdefb252775c1b3ea04a3dd4 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 31 Jan 2012 17:14:38 +0100 Subject: [PATCH 281/380] proc: mem_release() should check mm != NULL mem_release() can hit mm == NULL, add the necessary check. Cc: stable@kernel.org Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds --- fs/proc/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 9cde9edf9c4d..c3617ea7830b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -822,8 +822,8 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig) static int mem_release(struct inode *inode, struct file *file) { struct mm_struct *mm = file->private_data; - - mmput(mm); + if (mm) + mmput(mm); return 0; } From 572d34b946bae070debd42db1143034d9687e13f Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 31 Jan 2012 17:14:54 +0100 Subject: [PATCH 282/380] proc: unify mem_read() and mem_write() No functional changes, cleanup and preparation. mem_read() and mem_write() are very similar. Move this code into the new common helper, mem_rw(), which takes the additional "int write" argument. Cc: stable@kernel.org Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds --- fs/proc/base.c | 90 ++++++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 58 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index c3617ea7830b..be1909041685 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -718,57 +718,13 @@ static int mem_open(struct inode* inode, struct file* file) return 0; } -static ssize_t mem_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) +static ssize_t mem_rw(struct file *file, char __user *buf, + size_t count, loff_t *ppos, int write) { - int ret; - char *page; - unsigned long src = *ppos; struct mm_struct *mm = file->private_data; - - if (!mm) - return 0; - - page = (char *)__get_free_page(GFP_TEMPORARY); - if (!page) - return -ENOMEM; - - ret = 0; - - while (count > 0) { - int this_len, retval; - - this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; - retval = access_remote_vm(mm, src, page, this_len, 0); - if (!retval) { - if (!ret) - ret = -EIO; - break; - } - - if (copy_to_user(buf, page, retval)) { - ret = -EFAULT; - break; - } - - ret += retval; - src += retval; - buf += retval; - count -= retval; - } - *ppos = src; - - free_page((unsigned long) page); - return ret; -} - -static ssize_t mem_write(struct file * file, const char __user *buf, - size_t count, loff_t *ppos) -{ - int copied; + unsigned long addr = *ppos; + ssize_t copied; char *page; - unsigned long dst = *ppos; - struct mm_struct *mm = file->private_data; if (!mm) return 0; @@ -779,30 +735,48 @@ static ssize_t mem_write(struct file * file, const char __user *buf, copied = 0; while (count > 0) { - int this_len, retval; + int this_len = min_t(int, count, PAGE_SIZE); - this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; - if (copy_from_user(page, buf, this_len)) { + if (write && copy_from_user(page, buf, this_len)) { copied = -EFAULT; break; } - retval = access_remote_vm(mm, dst, page, this_len, 1); - if (!retval) { + + this_len = access_remote_vm(mm, addr, page, this_len, write); + if (!this_len) { if (!copied) copied = -EIO; break; } - copied += retval; - buf += retval; - dst += retval; - count -= retval; + + if (!write && copy_to_user(buf, page, this_len)) { + copied = -EFAULT; + break; + } + + buf += this_len; + addr += this_len; + copied += this_len; + count -= this_len; } - *ppos = dst; + *ppos = addr; free_page((unsigned long) page); return copied; } +static ssize_t mem_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + return mem_rw(file, buf, count, ppos, 0); +} + +static ssize_t mem_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + return mem_rw(file, (char __user*)buf, count, ppos, 1); +} + loff_t mem_lseek(struct file *file, loff_t offset, int orig) { switch (orig) { From 6d08f2c7139790c268820a2e590795cb8333181a Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 31 Jan 2012 17:15:11 +0100 Subject: [PATCH 283/380] proc: make sure mem_open() doesn't pin the target's memory Once /proc/pid/mem is opened, the memory can't be released until mem_release() even if its owner exits. Change mem_open() to do atomic_inc(mm_count) + mmput(), this only pins mm_struct. Change mem_rw() to do atomic_inc_not_zero(mm_count) before access_remote_vm(), this verifies that this mm is still alive. I am not sure what should mem_rw() return if atomic_inc_not_zero() fails. With this patch it returns zero to match the "mm == NULL" case, may be it should return -EINVAL like it did before e268337d. Perhaps it makes sense to add the additional fatal_signal_pending() check into the main loop, to ensure we do not hold this memory if the target task was oom-killed. Cc: stable@kernel.org Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds --- fs/proc/base.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index be1909041685..d9512bd03e6c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -711,6 +711,13 @@ static int mem_open(struct inode* inode, struct file* file) if (IS_ERR(mm)) return PTR_ERR(mm); + if (mm) { + /* ensure this mm_struct can't be freed */ + atomic_inc(&mm->mm_count); + /* but do not pin its memory */ + mmput(mm); + } + /* OK to pass negative loff_t, we can catch out-of-range */ file->f_mode |= FMODE_UNSIGNED_OFFSET; file->private_data = mm; @@ -734,6 +741,9 @@ static ssize_t mem_rw(struct file *file, char __user *buf, return -ENOMEM; copied = 0; + if (!atomic_inc_not_zero(&mm->mm_users)) + goto free; + while (count > 0) { int this_len = min_t(int, count, PAGE_SIZE); @@ -761,6 +771,8 @@ static ssize_t mem_rw(struct file *file, char __user *buf, } *ppos = addr; + mmput(mm); +free: free_page((unsigned long) page); return copied; } @@ -797,7 +809,7 @@ static int mem_release(struct inode *inode, struct file *file) { struct mm_struct *mm = file->private_data; if (mm) - mmput(mm); + mmdrop(mm); return 0; } From c6df4b17c8539f737a6a2d7b797eac41e8e34cdc Mon Sep 17 00:00:00 2001 From: David Miller Date: Thu, 2 Feb 2012 00:17:54 +0200 Subject: [PATCH 284/380] lib: Fix multiple definitions of clz_tab Both sparc 32-bit's software divide assembler and MPILIB provide clz_tab[] with identical contents. Break it out into a seperate object file and select it when SPARC32 or MPILIB is set. Reported-by: Al Viro Signed-off-by: David S. Miller Signed-off-by: James Morris --- arch/sparc/Kconfig | 1 + arch/sparc/lib/divdi3.S | 16 +--------------- lib/Kconfig | 4 ++++ lib/Makefile | 2 ++ lib/clz_tab.c | 18 ++++++++++++++++++ lib/mpi/mpi-bit.c | 19 ------------------- 6 files changed, 26 insertions(+), 34 deletions(-) create mode 100644 lib/clz_tab.c diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 96657992a72e..ca5580e4d813 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -33,6 +33,7 @@ config SPARC config SPARC32 def_bool !64BIT select GENERIC_ATOMIC64 + select CLZ_TAB config SPARC64 def_bool 64BIT diff --git a/arch/sparc/lib/divdi3.S b/arch/sparc/lib/divdi3.S index 681b3683da9e..d74bc0925f2d 100644 --- a/arch/sparc/lib/divdi3.S +++ b/arch/sparc/lib/divdi3.S @@ -17,23 +17,9 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - .data - .align 8 - .globl __clz_tab -__clz_tab: - .byte 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 - .byte 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 - .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 - .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 - .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - .size __clz_tab,256 - .global .udiv - .text .align 4 + .global .udiv .globl __divdi3 __divdi3: save %sp,-104,%sp diff --git a/lib/Kconfig b/lib/Kconfig index 169eb7c598e5..d69d321a0997 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -279,6 +279,9 @@ config AVERAGE If unsure, say N. +config CLZ_TAB + bool + config CORDIC tristate "CORDIC algorithm" help @@ -287,6 +290,7 @@ config CORDIC config MPILIB tristate + select CLZ_TAB help Multiprecision maths library from GnuPG. It is used to implement RSA digital signature verification, diff --git a/lib/Makefile b/lib/Makefile index d71aae1b01b3..18515f0267c4 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -121,6 +121,8 @@ obj-$(CONFIG_DQL) += dynamic_queue_limits.o obj-$(CONFIG_MPILIB) += mpi/ obj-$(CONFIG_SIGNATURE) += digsig.o +obj-$(CONFIG_CLZ_TAB) += clz_tab.o + hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/clz_tab.c b/lib/clz_tab.c new file mode 100644 index 000000000000..7287b4a991a7 --- /dev/null +++ b/lib/clz_tab.c @@ -0,0 +1,18 @@ +const unsigned char __clz_tab[] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, +}; diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c index 854c9c6da025..2f526627e4f5 100644 --- a/lib/mpi/mpi-bit.c +++ b/lib/mpi/mpi-bit.c @@ -21,25 +21,6 @@ #include "mpi-internal.h" #include "longlong.h" -const unsigned char __clz_tab[] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, -}; - #define A_LIMB_1 ((mpi_limb_t) 1) /**************** From a99e7e5f36c55e561a64280f5099078c31839076 Mon Sep 17 00:00:00 2001 From: David Miller Date: Thu, 2 Feb 2012 00:17:55 +0200 Subject: [PATCH 285/380] lib: Fix 32-bit sparc udiv_qrnnd() definition in mpilib's longlong.h This copy of longlong.h is extremely dated and results in compile errors on sparc32 when MPILIB is enabled, copy over the more uptodate implementation from arch/sparc/math/sfp-util_32.h Reported-by: Al Viro Signed-off-by: David S. Miller Signed-off-by: James Morris --- lib/mpi/longlong.h | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index b87487b40a8b..29f98624ef93 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h @@ -1200,18 +1200,40 @@ do { \ "r" ((USItype)(v)) \ : "%g1", "%g2" __AND_CLOBBER_CC) #define UMUL_TIME 39 /* 39 instructions */ -#endif -#ifndef udiv_qrnnd -#ifndef LONGLONG_STANDALONE +/* It's quite necessary to add this much assembler for the sparc. + The default udiv_qrnnd (in C) is more than 10 times slower! */ #define udiv_qrnnd(q, r, n1, n0, d) \ -do { USItype __r; \ - (q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \ - (r) = __r; \ -} while (0) - extern USItype __udiv_qrnnd(); -#define UDIV_TIME 140 -#endif /* LONGLONG_STANDALONE */ -#endif /* udiv_qrnnd */ + __asm__ ("! Inlined udiv_qrnnd\n\t" \ + "mov 32,%%g1\n\t" \ + "subcc %1,%2,%%g0\n\t" \ + "1: bcs 5f\n\t" \ + "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \ + "sub %1,%2,%1 ! this kills msb of n\n\t" \ + "addx %1,%1,%1 ! so this can't give carry\n\t" \ + "subcc %%g1,1,%%g1\n\t" \ + "2: bne 1b\n\t" \ + "subcc %1,%2,%%g0\n\t" \ + "bcs 3f\n\t" \ + "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \ + "b 3f\n\t" \ + "sub %1,%2,%1 ! this kills msb of n\n\t" \ + "4: sub %1,%2,%1\n\t" \ + "5: addxcc %1,%1,%1\n\t" \ + "bcc 2b\n\t" \ + "subcc %%g1,1,%%g1\n\t" \ + "! Got carry from n. Subtract next step to cancel this carry.\n\t" \ + "bne 4b\n\t" \ + "addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n\t" \ + "sub %1,%2,%1\n\t" \ + "3: xnor %0,0,%0\n\t" \ + "! End of inline udiv_qrnnd\n" \ + : "=&r" ((USItype)(q)), \ + "=&r" ((USItype)(r)) \ + : "r" ((USItype)(d)), \ + "1" ((USItype)(n1)), \ + "0" ((USItype)(n0)) : "%g1", "cc") +#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ +#endif #endif /* __sparc__ */ /*************************************** From 43b6cec27e1e50a1de3eff47e66e502f3fe7e66e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 1 Feb 2012 23:46:58 +0000 Subject: [PATCH 286/380] ASoC: wm_hubs: Correct line input to line output 2 paths The second line output mixer has the controls for the line input bypasses in the opposite order. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm_hubs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index c1a3f8c39691..8a68cea4a3ee 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -586,8 +586,8 @@ SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), }; static const struct snd_kcontrol_new line2_mix[] = { -SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 1, 1, 0), +SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0), +SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0), SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), }; From 876cf5e7b9e4bae014b0fa2cc18b21bce6d99073 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Wed, 1 Feb 2012 18:32:32 +0530 Subject: [PATCH 287/380] gpio: samsung: adapt to changes in gpio specifier translator function declaration Commit 15c9a0acc3f7 (of: create of_phandle_args to simplify return of phandle parsing data) modifies the parameter list of of_xlate function pointer declaration in gpio_chip. Adapt the gpio specifier translate function for this change. Reported-by: Tushar Behera Signed-off-by: Thomas Abraham Tested-by: Karol Lewandowski Signed-off-by: Grant Likely --- drivers/gpio/gpio-samsung.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index a7661773c052..0a79a1167a25 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -2387,27 +2387,30 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { }; #if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) -static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np, - const void *gpio_spec, u32 *flags) +static int exynos4_gpio_xlate(struct gpio_chip *gc, + const struct of_phandle_args *gpiospec, u32 *flags) { - const __be32 *gpio = gpio_spec; - const u32 n = be32_to_cpup(gpio); - unsigned int pin = gc->base + be32_to_cpu(gpio[0]); + unsigned int pin; if (WARN_ON(gc->of_gpio_n_cells < 4)) return -EINVAL; - if (n > gc->ngpio) + if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) return -EINVAL; - if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1])))) + if (gpiospec->args[0] > gc->ngpio) + return -EINVAL; + + pin = gc->base + gpiospec->args[0]; + + if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1]))) pr_warn("gpio_xlate: failed to set pin function\n"); - if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2]))) + if (s3c_gpio_setpull(pin, gpiospec->args[2])) pr_warn("gpio_xlate: failed to set pin pull up/down\n"); - if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3]))) + if (s5p_gpio_set_drvstr(pin, gpiospec->args[3])) pr_warn("gpio_xlate: failed to set pin drive strength\n"); - return n; + return gpiospec->args[0]; } static const struct of_device_id exynos4_gpio_dt_match[] __initdata = { From 13405059e8148259a0d5b66f42e93d641a63e66a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 1 Feb 2012 18:15:49 -0800 Subject: [PATCH 288/380] docbook: fix fatal errors in device-drivers docbook and add DMA Management section Fix 2 fatal errors in the device-drivers docbook. Also add some missing files from drivers/base/; since several of these are DMA-related, add a section for DMA Management. docproc: drivers/base/sys.c: No such file or directory docproc: drivers/tty/serial/8250.c: No such file or directory Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/DocBook/device-drivers.tmpl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index 2f7fd4360848..9c27e5125dd2 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -102,9 +102,12 @@ X!Iinclude/linux/kobject.h !Iinclude/linux/device.h Device Drivers Base +!Idrivers/base/init.c !Edrivers/base/driver.c !Edrivers/base/core.c +!Edrivers/base/syscore.c !Edrivers/base/class.c +!Idrivers/base/node.c !Edrivers/base/firmware_class.c !Edrivers/base/transport_class.c -!Edrivers/base/sys.c +!Edrivers/base/dd.c !Iinclude/linux/platform_device.h !Edrivers/base/platform.c !Edrivers/base/bus.c + + Device Drivers DMA Management +!Edrivers/base/dma-buf.c +!Edrivers/base/dma-coherent.c +!Edrivers/base/dma-mapping.c Device Drivers Power Management !Edrivers/base/power/main.c @@ -219,7 +227,7 @@ X!Isound/sound_firmware.c 16x50 UART Driver !Edrivers/tty/serial/serial_core.c -!Edrivers/tty/serial/8250.c +!Edrivers/tty/serial/8250/8250.c From da46d7dd530c5af7cff049145f0c088f5e75bdc6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 1 Feb 2012 19:04:02 -0800 Subject: [PATCH 289/380] staging: fix go7007-usb license Add MODULE_LICENSE() as per the license in the comment at the top of the file for this source module to fix build warning: WARNING: modpost: missing MODULE_LICENSE() in drivers/staging/media/go7007/go7007-usb.o see include/linux/module.h for more information Signed-off-by: Randy Dunlap Cc: Ross Cohen Signed-off-by: Linus Torvalds --- drivers/staging/media/go7007/go7007-usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 70e006b50f29..5443e25086e9 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c @@ -1279,3 +1279,4 @@ static struct usb_driver go7007_usb_driver = { }; module_usb_driver(go7007_usb_driver); +MODULE_LICENSE("GPL v2"); From d166370ad86b33b1111af3a0cdd7de94e03789a6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 1 Feb 2012 10:51:53 +0800 Subject: [PATCH 290/380] gpio: Add missing spin_lock_init in gpio-pch driver This bug was introduced by commit d568a681 "gpio-pch: add spinlock in suspend/resume processing" which adds a spinlock to struct pch_gpio but never init the spinlock. Reported-by: Tomoya MORINAGA Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Grant Likely --- drivers/gpio/gpio-pch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 68fa55e86eb1..e8729cc2ba2b 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -392,6 +392,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, chip->reg = chip->base; pci_set_drvdata(pdev, chip); mutex_init(&chip->lock); + spin_lock_init(&chip->spinlock); pch_gpio_setup(chip); ret = gpiochip_add(&chip->gpio); if (ret) { From 7e3a70fb7bccada029c188c89bfbf3c0a63c1500 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 1 Feb 2012 10:50:05 +0800 Subject: [PATCH 291/380] gpio: Add missing spin_lock_init in gpio-ml-ioh driver This bug was introduced by commit 54be5663 "gpio-ml-ioh: Support interrupt function" which adds a spinlock to struct ioh_gpio but never init the spinlock. Signed-off-by: Axel Lin Signed-off-by: Grant Likely --- drivers/gpio/gpio-ml-ioh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 03d6dd5dcb77..f0febe5b8221 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -448,6 +448,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev, chip->reg = chip->base; chip->ch = i; mutex_init(&chip->lock); + spin_lock_init(&chip->spinlock); ioh_gpio_setup(chip, num_ports[i]); ret = gpiochip_add(&chip->gpio); if (ret) { From 94ac27a54be6a14948f0a9b3f542b4ff1faac232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= Date: Tue, 24 Jan 2012 14:22:01 +0100 Subject: [PATCH 292/380] i.MX SDMA: Fix burstsize settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 6584cb88 (ARM i.MX dma: Fix burstsize settings) fixed the mxcmmc driver but forgot to fix the SDMA driver to handle the correct burtsize. This make the SD card access works again with DMA on i.MX31 boards. Signed-off-by: Philippe Rétornaz Tested-by: Sascha Hauer Acked-by: Sascha Hauer Signed-off-by: Vinod Koul --- drivers/dma/imx-sdma.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index a8af379680c1..8bc5acf36ee5 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1102,11 +1102,13 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, case DMA_SLAVE_CONFIG: if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { sdmac->per_address = dmaengine_cfg->src_addr; - sdmac->watermark_level = dmaengine_cfg->src_maxburst; + sdmac->watermark_level = dmaengine_cfg->src_maxburst * + dmaengine_cfg->src_addr_width; sdmac->word_size = dmaengine_cfg->src_addr_width; } else { sdmac->per_address = dmaengine_cfg->dst_addr; - sdmac->watermark_level = dmaengine_cfg->dst_maxburst; + sdmac->watermark_level = dmaengine_cfg->dst_maxburst * + dmaengine_cfg->dst_addr_width; sdmac->word_size = dmaengine_cfg->dst_addr_width; } sdmac->direction = dmaengine_cfg->direction; From ba18311dff7933ccb9c41bbbb1ad3d70840069b5 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 12 Jan 2012 17:42:22 +0800 Subject: [PATCH 293/380] HID: usbhid: fix dead lock between open and disconect There is no reason to hold hiddev->existancelock before calling usb_deregister_dev, so move it out of the lock. The patch fixes the lockdep warning below. [ 5733.386271] ====================================================== [ 5733.386274] [ INFO: possible circular locking dependency detected ] [ 5733.386278] 3.2.0-custom-next-20120111+ #1 Not tainted [ 5733.386281] ------------------------------------------------------- [ 5733.386284] khubd/186 is trying to acquire lock: [ 5733.386288] (minor_rwsem){++++.+}, at: [] usb_deregister_dev+0x37/0x9e [usbcore] [ 5733.386311] [ 5733.386312] but task is already holding lock: [ 5733.386315] (&hiddev->existancelock){+.+...}, at: [] hiddev_disconnect+0x26/0x87 [usbhid] [ 5733.386328] [ 5733.386329] which lock already depends on the new lock. [ 5733.386330] [ 5733.386333] [ 5733.386334] the existing dependency chain (in reverse order) is: [ 5733.386336] [ 5733.386337] -> #1 (&hiddev->existancelock){+.+...}: [ 5733.386346] [] lock_acquire+0xcb/0x10e [ 5733.386357] [] __mutex_lock_common+0x60/0x465 [ 5733.386366] [] mutex_lock_nested+0x36/0x3b [ 5733.386371] [] hiddev_open+0x113/0x193 [usbhid] [ 5733.386378] [] usb_open+0x66/0xc2 [usbcore] [ 5733.386390] [] chrdev_open+0x12b/0x154 [ 5733.386402] [] __dentry_open.isra.16+0x20b/0x355 [ 5733.386408] [] nameidata_to_filp+0x43/0x4a [ 5733.386413] [] do_last+0x536/0x570 [ 5733.386419] [] path_openat+0xce/0x301 [ 5733.386423] [] do_filp_open+0x33/0x81 [ 5733.386427] [] do_sys_open+0x6a/0xfc [ 5733.386431] [] sys_open+0x1c/0x1e [ 5733.386434] [] system_call_fastpath+0x16/0x1b [ 5733.386441] [ 5733.386441] -> #0 (minor_rwsem){++++.+}: [ 5733.386448] [] __lock_acquire+0xa80/0xd74 [ 5733.386454] [] lock_acquire+0xcb/0x10e [ 5733.386458] [] down_write+0x44/0x77 [ 5733.386464] [] usb_deregister_dev+0x37/0x9e [usbcore] [ 5733.386475] [] hiddev_disconnect+0x3c/0x87 [usbhid] [ 5733.386483] [] hid_disconnect+0x3f/0x54 [ 5733.386491] [] hid_device_remove+0x4e/0x7a [ 5733.386496] [] __device_release_driver+0x81/0xcd [ 5733.386502] [] device_release_driver+0x20/0x2d [ 5733.386507] [] bus_remove_device+0x114/0x128 [ 5733.386512] [] device_del+0x131/0x183 [ 5733.386519] [] hid_destroy_device+0x1e/0x3d [ 5733.386525] [] usbhid_disconnect+0x36/0x42 [usbhid] [ 5733.386530] [] usb_unbind_interface+0x57/0x11f [usbcore] [ 5733.386542] [] __device_release_driver+0x81/0xcd [ 5733.386547] [] device_release_driver+0x20/0x2d [ 5733.386552] [] bus_remove_device+0x114/0x128 [ 5733.386557] [] device_del+0x131/0x183 [ 5733.386562] [] usb_disable_device+0xa8/0x1d8 [usbcore] [ 5733.386573] [] usb_disconnect+0xab/0x11f [usbcore] [ 5733.386583] [] hub_thread+0x73b/0x1157 [usbcore] [ 5733.386593] [] kthread+0x95/0x9d [ 5733.386601] [] kernel_thread_helper+0x4/0x10 [ 5733.386607] [ 5733.386608] other info that might help us debug this: [ 5733.386609] [ 5733.386612] Possible unsafe locking scenario: [ 5733.386613] [ 5733.386615] CPU0 CPU1 [ 5733.386618] ---- ---- [ 5733.386620] lock(&hiddev->existancelock); [ 5733.386625] lock(minor_rwsem); [ 5733.386630] lock(&hiddev->existancelock); [ 5733.386635] lock(minor_rwsem); [ 5733.386639] [ 5733.386640] *** DEADLOCK *** [ 5733.386641] [ 5733.386644] 6 locks held by khubd/186: [ 5733.386646] #0: (&__lockdep_no_validate__){......}, at: [] hub_thread+0x14a/0x1157 [usbcore] [ 5733.386661] #1: (&__lockdep_no_validate__){......}, at: [] usb_disconnect+0x50/0x11f [usbcore] [ 5733.386677] #2: (hcd->bandwidth_mutex){+.+.+.}, at: [] usb_disconnect+0xa1/0x11f [usbcore] [ 5733.386693] #3: (&__lockdep_no_validate__){......}, at: [] device_release_driver+0x18/0x2d [ 5733.386704] #4: (&__lockdep_no_validate__){......}, at: [] device_release_driver+0x18/0x2d [ 5733.386714] #5: (&hiddev->existancelock){+.+...}, at: [] hiddev_disconnect+0x26/0x87 [usbhid] [ 5733.386727] [ 5733.386727] stack backtrace: [ 5733.386731] Pid: 186, comm: khubd Not tainted 3.2.0-custom-next-20120111+ #1 [ 5733.386734] Call Trace: [ 5733.386741] [] ? up+0x34/0x3b [ 5733.386747] [] print_circular_bug+0x1f8/0x209 [ 5733.386752] [] __lock_acquire+0xa80/0xd74 [ 5733.386756] [] ? trace_hardirqs_on_caller+0x15d/0x1a3 [ 5733.386763] [] ? vprintk+0x3f4/0x419 [ 5733.386774] [] ? usb_deregister_dev+0x37/0x9e [usbcore] [ 5733.386779] [] lock_acquire+0xcb/0x10e [ 5733.386789] [] ? usb_deregister_dev+0x37/0x9e [usbcore] [ 5733.386797] [] down_write+0x44/0x77 [ 5733.386807] [] ? usb_deregister_dev+0x37/0x9e [usbcore] [ 5733.386818] [] usb_deregister_dev+0x37/0x9e [usbcore] [ 5733.386825] [] hiddev_disconnect+0x3c/0x87 [usbhid] [ 5733.386830] [] hid_disconnect+0x3f/0x54 [ 5733.386834] [] hid_device_remove+0x4e/0x7a [ 5733.386839] [] __device_release_driver+0x81/0xcd [ 5733.386844] [] device_release_driver+0x20/0x2d [ 5733.386848] [] bus_remove_device+0x114/0x128 [ 5733.386854] [] device_del+0x131/0x183 [ 5733.386859] [] hid_destroy_device+0x1e/0x3d [ 5733.386865] [] usbhid_disconnect+0x36/0x42 [usbhid] [ 5733.386876] [] usb_unbind_interface+0x57/0x11f [usbcore] [ 5733.386882] [] __device_release_driver+0x81/0xcd [ 5733.386886] [] device_release_driver+0x20/0x2d [ 5733.386890] [] bus_remove_device+0x114/0x128 [ 5733.386895] [] device_del+0x131/0x183 [ 5733.386905] [] usb_disable_device+0xa8/0x1d8 [usbcore] [ 5733.386916] [] usb_disconnect+0xab/0x11f [usbcore] [ 5733.386921] [] ? __mutex_unlock_slowpath+0x130/0x141 [ 5733.386929] [] hub_thread+0x73b/0x1157 [usbcore] [ 5733.386935] [] ? finish_task_switch+0x78/0x150 [ 5733.386941] [] ? __init_waitqueue_head+0x4c/0x4c [ 5733.386950] [] ? usb_remote_wakeup+0x56/0x56 [usbcore] [ 5733.386955] [] kthread+0x95/0x9d [ 5733.386961] [] kernel_thread_helper+0x4/0x10 [ 5733.386966] [] ? retint_restore_args+0x13/0x13 [ 5733.386970] [] ? __init_kthread_worker+0x55/0x55 [ 5733.386974] [] ? gs_change+0x13/0x13 Signed-off-by: Ming Lei Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 7c297d305d5d..b1ec0e2aeb57 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -922,11 +922,11 @@ void hiddev_disconnect(struct hid_device *hid) struct hiddev *hiddev = hid->hiddev; struct usbhid_device *usbhid = hid->driver_data; + usb_deregister_dev(usbhid->intf, &hiddev_class); + mutex_lock(&hiddev->existancelock); hiddev->exist = 0; - usb_deregister_dev(usbhid->intf, &hiddev_class); - if (hiddev->open) { mutex_unlock(&hiddev->existancelock); usbhid_close(hiddev->hid); From 054d867e032daf55c3343fc6d36c5c5f1e7954db Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 24 Jan 2012 12:25:50 +0100 Subject: [PATCH 294/380] ALSA: hda - Check power-state before changing in patch_via.c Instead of always writing AC_VERB_SET_POWER_STATE, check the current power-state and don't write again if the value is already set. This may reduce the click noise upon the dynamic power-state change (e.g. in analog-input mixer). Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 256 ++++++++++++++++---------------------- 1 file changed, 107 insertions(+), 149 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 03e63fed9caf..fb1f0ffc556b 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -687,6 +687,15 @@ static void via_auto_init_analog_input(struct hda_codec *codec) } } +static void update_power_state(struct hda_codec *codec, hda_nid_t nid, + unsigned int parm) +{ + if (snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_POWER_STATE, 0) == parm) + return; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); +} + static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, unsigned int *affected_parm) { @@ -709,7 +718,7 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, } else parm = AC_PWRST_D3; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, nid, parm); } static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol, @@ -2295,10 +2304,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol, if (mux) { /* switch to D0 beofre change index */ - if (snd_hda_codec_read(codec, mux, 0, - AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0) - snd_hda_codec_write(codec, mux, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, mux, AC_PWRST_D0); snd_hda_codec_write(codec, mux, 0, AC_VERB_SET_CONNECT_SEL, spec->inputs[cur].mux_idx); @@ -2922,9 +2928,9 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec) if (imux_is_smixer) parm = AC_PWRST_D0; /* SW0 (17h), AIW 0/1 (13h/14h) */ - snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x17, parm); + update_power_state(codec, 0x13, parm); + update_power_state(codec, 0x14, parm); /* outputs */ /* PW0 (19h), SW1 (18h), AOW1 (11h) */ @@ -2932,8 +2938,8 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec) set_pin_power_state(codec, 0x19, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x1b, &parm); - snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x11, parm); /* PW6 (22h), SW2 (26h), AOW2 (24h) */ if (is_8ch) { @@ -2941,20 +2947,16 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec) set_pin_power_state(codec, 0x22, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x1a, &parm); - snd_hda_codec_write(codec, 0x26, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x24, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x26, parm); + update_power_state(codec, 0x24, parm); } else if (codec->vendor_id == 0x11064397) { /* PW7(23h), SW2(27h), AOW2(25h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x23, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x1a, &parm); - snd_hda_codec_write(codec, 0x27, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x25, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x27, parm); + update_power_state(codec, 0x25, parm); } /* PW 3/4/7 (1ch/1dh/23h) */ @@ -2966,17 +2968,13 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec) set_pin_power_state(codec, 0x23, &parm); /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */ - snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, - imux_is_smixer ? AC_PWRST_D0 : parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x10, parm); if (is_8ch) { - snd_hda_codec_write(codec, 0x25, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x27, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x25, parm); + update_power_state(codec, 0x27, parm); } else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode) - snd_hda_codec_write(codec, 0x25, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x25, parm); } static int patch_vt1708S(struct hda_codec *codec); @@ -3149,10 +3147,10 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec) if (imux_is_smixer) parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */ /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */ - snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x13, parm); + update_power_state(codec, 0x12, parm); + update_power_state(codec, 0x1f, parm); + update_power_state(codec, 0x20, parm); /* outputs */ /* PW 3/4 (16h/17h) */ @@ -3160,10 +3158,9 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec) set_pin_power_state(codec, 0x17, &parm); set_pin_power_state(codec, 0x16, &parm); /* MW0 (1ah), AOW 0/1 (10h/1dh) */ - snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, - imux_is_smixer ? AC_PWRST_D0 : parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x10, parm); + update_power_state(codec, 0x1d, parm); } static int patch_vt1702(struct hda_codec *codec) @@ -3228,52 +3225,48 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec) if (imux_is_smixer) parm = AC_PWRST_D0; /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */ - snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1e, parm); + update_power_state(codec, 0x1f, parm); + update_power_state(codec, 0x10, parm); + update_power_state(codec, 0x11, parm); /* outputs */ /* PW3 (27h), MW2 (1ah), AOW3 (bh) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x27, &parm); - snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1a, parm); + update_power_state(codec, 0xb, parm); /* PW2 (26h), AOW2 (ah) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x26, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x2b, &parm); - snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0xa, parm); /* PW0 (24h), AOW0 (8h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x24, &parm); if (!spec->hp_independent_mode) /* check for redirected HP */ set_pin_power_state(codec, 0x28, &parm); - snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x8, parm); /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */ - snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE, - imux_is_smixer ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm); /* PW1 (25h), AOW1 (9h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x25, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x2a, &parm); - snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x9, parm); if (spec->hp_independent_mode) { /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm); - snd_hda_codec_write(codec, 0x1b, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x34, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0xc, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1b, parm); + update_power_state(codec, 0x34, parm); + update_power_state(codec, 0xc, parm); } } @@ -3433,8 +3426,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) if (imux_is_smixer) parm = AC_PWRST_D0; /* SW0 (17h), AIW0(13h) */ - snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x17, parm); + update_power_state(codec, 0x13, parm); parm = AC_PWRST_D3; set_pin_power_state(codec, 0x1e, &parm); @@ -3442,12 +3435,11 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) if (spec->dmic_enabled) set_pin_power_state(codec, 0x22, &parm); else - snd_hda_codec_write(codec, 0x22, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + update_power_state(codec, 0x22, AC_PWRST_D3); /* SW2(26h), AIW1(14h) */ - snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x26, parm); + update_power_state(codec, 0x14, parm); /* outputs */ /* PW0 (19h), SW1 (18h), AOW1 (11h) */ @@ -3456,8 +3448,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) /* Smart 5.1 PW2(1bh) */ if (spec->smart51_enabled) set_pin_power_state(codec, 0x1b, &parm); - snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x11, parm); /* PW7 (23h), SW3 (27h), AOW3 (25h) */ parm = AC_PWRST_D3; @@ -3465,12 +3457,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) /* Smart 5.1 PW1(1ah) */ if (spec->smart51_enabled) set_pin_power_state(codec, 0x1a, &parm); - snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x27, parm); /* Smart 5.1 PW5(1eh) */ if (spec->smart51_enabled) set_pin_power_state(codec, 0x1e, &parm); - snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x25, parm); /* Mono out */ /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/ @@ -3486,9 +3478,9 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) mono_out = 1; } parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3; - snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x28, parm); + update_power_state(codec, 0x29, parm); + update_power_state(codec, 0x2a, parm); /* PW 3/4 (1ch/1dh) */ parm = AC_PWRST_D3; @@ -3496,15 +3488,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) set_pin_power_state(codec, 0x1d, &parm); /* HP Independent Mode, power on AOW3 */ if (spec->hp_independent_mode) - snd_hda_codec_write(codec, 0x25, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x25, parm); /* force to D0 for internal Speaker */ /* MW0 (16h), AOW0 (10h) */ - snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, - imux_is_smixer ? AC_PWRST_D0 : parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, - mono_out ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm); } static int patch_vt1716S(struct hda_codec *codec) @@ -3580,54 +3569,45 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) set_pin_power_state(codec, 0x2b, &parm); parm = AC_PWRST_D0; /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */ - snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1e, parm); + update_power_state(codec, 0x1f, parm); + update_power_state(codec, 0x10, parm); + update_power_state(codec, 0x11, parm); /* outputs */ /* AOW0 (8h)*/ - snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x8, parm); if (spec->codec_type == VT1802) { /* PW4 (28h), MW4 (18h), MUX4(38h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm); - snd_hda_codec_write(codec, 0x18, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x38, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x38, parm); } else { /* PW4 (26h), MW4 (1ch), MUX4(37h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x26, &parm); - snd_hda_codec_write(codec, 0x1c, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x37, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1c, parm); + update_power_state(codec, 0x37, parm); } if (spec->codec_type == VT1802) { /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x25, &parm); - snd_hda_codec_write(codec, 0x15, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x35, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x15, parm); + update_power_state(codec, 0x35, parm); } else { /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x25, &parm); - snd_hda_codec_write(codec, 0x19, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x35, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x19, parm); + update_power_state(codec, 0x35, parm); } if (spec->hp_independent_mode) - snd_hda_codec_write(codec, 0x9, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x9, AC_PWRST_D0); /* Class-D */ /* PW0 (24h), MW0(18h/14h), MUX0(34h) */ @@ -3637,12 +3617,10 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) set_pin_power_state(codec, 0x24, &parm); parm = present ? AC_PWRST_D3 : AC_PWRST_D0; if (spec->codec_type == VT1802) - snd_hda_codec_write(codec, 0x14, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x14, parm); else - snd_hda_codec_write(codec, 0x18, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x34, parm); /* Mono Out */ present = snd_hda_jack_detect(codec, 0x26); @@ -3650,28 +3628,20 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) parm = present ? AC_PWRST_D3 : AC_PWRST_D0; if (spec->codec_type == VT1802) { /* PW15 (33h), MW8(1ch), MUX8(3ch) */ - snd_hda_codec_write(codec, 0x33, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1c, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x3c, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x33, parm); + update_power_state(codec, 0x1c, parm); + update_power_state(codec, 0x3c, parm); } else { /* PW15 (31h), MW8(17h), MUX8(3bh) */ - snd_hda_codec_write(codec, 0x31, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x17, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x3b, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x31, parm); + update_power_state(codec, 0x17, parm); + update_power_state(codec, 0x3b, parm); } /* MW9 (21h) */ if (imux_is_smixer || !is_aa_path_mute(codec)) - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x21, AC_PWRST_D0); else - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + update_power_state(codec, 0x21, AC_PWRST_D3); } /* patch for vt2002P */ @@ -3731,30 +3701,28 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec) set_pin_power_state(codec, 0x2b, &parm); parm = AC_PWRST_D0; /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */ - snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1e, parm); + update_power_state(codec, 0x1f, parm); + update_power_state(codec, 0x10, parm); + update_power_state(codec, 0x11, parm); /* outputs */ /* AOW0 (8h)*/ - snd_hda_codec_write(codec, 0x8, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x8, AC_PWRST_D0); /* PW4 (28h), MW4 (18h), MUX4(38h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm); - snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x38, parm); /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x25, &parm); - snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x15, parm); + update_power_state(codec, 0x35, parm); if (spec->hp_independent_mode) - snd_hda_codec_write(codec, 0x9, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x9, AC_PWRST_D0); /* Internal Speaker */ /* PW0 (24h), MW0(14h), MUX0(34h) */ @@ -3763,15 +3731,11 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec) parm = AC_PWRST_D3; set_pin_power_state(codec, 0x24, &parm); if (present) { - snd_hda_codec_write(codec, 0x14, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - snd_hda_codec_write(codec, 0x34, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + update_power_state(codec, 0x14, AC_PWRST_D3); + update_power_state(codec, 0x34, AC_PWRST_D3); } else { - snd_hda_codec_write(codec, 0x14, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); - snd_hda_codec_write(codec, 0x34, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x14, AC_PWRST_D0); + update_power_state(codec, 0x34, AC_PWRST_D0); } @@ -3782,26 +3746,20 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec) parm = AC_PWRST_D3; set_pin_power_state(codec, 0x31, &parm); if (present) { - snd_hda_codec_write(codec, 0x1c, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - snd_hda_codec_write(codec, 0x3c, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - snd_hda_codec_write(codec, 0x3e, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + update_power_state(codec, 0x1c, AC_PWRST_D3); + update_power_state(codec, 0x3c, AC_PWRST_D3); + update_power_state(codec, 0x3e, AC_PWRST_D3); } else { - snd_hda_codec_write(codec, 0x1c, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); - snd_hda_codec_write(codec, 0x3c, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); - snd_hda_codec_write(codec, 0x3e, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x1c, AC_PWRST_D0); + update_power_state(codec, 0x3c, AC_PWRST_D0); + update_power_state(codec, 0x3e, AC_PWRST_D0); } /* PW15 (33h), MW15 (1dh), MUX15(3dh) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x33, &parm); - snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1d, parm); + update_power_state(codec, 0x3d, parm); } From 924339239fd5ba3e505f9420d41f0939196f3530 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 24 Jan 2012 13:58:36 +0100 Subject: [PATCH 295/380] ALSA: hda - Fix the logic to detect VIA analog low-current mode The analog low-current mode must be enabled when the no stream is running but the current detection checks it in a wrong way. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=741128 Cc: [v3.1+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index fb1f0ffc556b..de43cd92b0a5 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1051,7 +1051,7 @@ static void analog_low_current_mode(struct hda_codec *codec) bool enable; unsigned int verb, parm; - enable = is_aa_path_mute(codec) && (spec->opened_streams != 0); + enable = is_aa_path_mute(codec) && !spec->opened_streams; /* decide low current mode's verb & parameter */ switch (spec->codec_type) { From e9d010c2e8f03952e67a6fd8aed0f0dc92084ccc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 1 Feb 2012 10:33:23 +0100 Subject: [PATCH 296/380] ALSA: hda - Allow analog low-current mode when dynamic power-control is on VIA codecs have several different power-saving features, and one of them is the analog low-current mode. But it turned out that the ALC mode causes pop-noises at each on/off time on some machines. As a quick workaround, disable the ALC when another power-saving feature, the dynamic pin power-control, is turned off, too, since the dynamic power-control is already exposed as a mixer enum element so that user can turn it on/off freely. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=741128 Cc: [v3.1+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index de43cd92b0a5..79166fb8b074 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -199,6 +199,9 @@ struct via_spec { unsigned int no_pin_power_ctl; enum VIA_HDA_CODEC codec_type; + /* analog low-power control */ + bool alc_mode; + /* smart51 setup */ unsigned int smart51_nums; hda_nid_t smart51_pins[2]; @@ -758,6 +761,7 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol, return 0; spec->no_pin_power_ctl = val; set_widgets_power_state(codec); + analog_low_current_mode(codec); return 1; } @@ -1045,13 +1049,19 @@ static bool is_aa_path_mute(struct hda_codec *codec) } /* enter/exit analog low-current mode */ -static void analog_low_current_mode(struct hda_codec *codec) +static void __analog_low_current_mode(struct hda_codec *codec, bool force) { struct via_spec *spec = codec->spec; bool enable; unsigned int verb, parm; - enable = is_aa_path_mute(codec) && !spec->opened_streams; + if (spec->no_pin_power_ctl) + enable = false; + else + enable = is_aa_path_mute(codec) && !spec->opened_streams; + if (enable == spec->alc_mode && !force) + return; + spec->alc_mode = enable; /* decide low current mode's verb & parameter */ switch (spec->codec_type) { @@ -1083,6 +1093,11 @@ static void analog_low_current_mode(struct hda_codec *codec) snd_hda_codec_write(codec, codec->afg, 0, verb, parm); } +static void analog_low_current_mode(struct hda_codec *codec) +{ + return __analog_low_current_mode(codec, false); +} + /* * generic initialization of ADC, input mixers and output mixers */ @@ -1508,10 +1523,6 @@ static int via_build_controls(struct hda_codec *codec) return err; } - /* init power states */ - set_widgets_power_state(codec); - analog_low_current_mode(codec); - via_free_kctls(codec); /* no longer needed */ err = snd_hda_jack_add_kctls(codec, &spec->autocfg); @@ -2782,6 +2793,10 @@ static int via_init(struct hda_codec *codec) for (i = 0; i < spec->num_iverbs; i++) snd_hda_sequence_write(codec, spec->init_verbs[i]); + /* init power states */ + set_widgets_power_state(codec); + __analog_low_current_mode(codec, true); + via_auto_init_multi_out(codec); via_auto_init_hp_out(codec); via_auto_init_speaker_out(codec); From b5bcc189401c815988b7dd37611fc56f40c9139d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 2 Feb 2012 10:30:17 +0100 Subject: [PATCH 297/380] ALSA: hda - Disable dynamic-power control for VIA as default Since the dynamic pin power-control and the analog low-current mode may lead to pop-noise, it's safer to set it off as default. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=741128 Cc: [v3.1+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 79166fb8b074..284e311040fe 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1470,6 +1470,7 @@ static int via_build_controls(struct hda_codec *codec) struct snd_kcontrol *kctl; int err, i; + spec->no_pin_power_ctl = 1; if (spec->set_widgets_power_state) if (!via_clone_control(spec, &via_pin_power_ctl_enum)) return -ENOMEM; From c1c454b8691cc95aa83f19273ed7845914c70e83 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 18 Jan 2012 08:57:14 -0800 Subject: [PATCH 298/380] HID: hyperv: Properly disconnect the input device When we unload the mouse driver, properly disconnect the input device. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Reported-by: Fuzhou Chen Cc: stable Signed-off-by: Jiri Kosina --- drivers/hid/hid-hyperv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index 0c33ae9cf0f0..406632472c1b 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -548,6 +548,7 @@ static int mousevsc_remove(struct hv_device *dev) struct mousevsc_dev *input_dev = hv_get_drvdata(dev); vmbus_close(dev->channel); + hid_hw_stop(input_dev->hid_device); hid_destroy_device(input_dev->hid_device); mousevsc_free_device(input_dev); From de47a9cd62771e3e78954d855d2304fbad4c5a44 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 2 Feb 2012 15:25:16 +0000 Subject: [PATCH 299/380] drm/radeon: fix use after free in ATRM bios reading code. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=45503 Reported-and-Debugged-by: mlambda@gmail.com Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 13ac63ba6075..98724fcb0088 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -59,8 +59,9 @@ static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, obj = (union acpi_object *)buffer.pointer; memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); + len = obj->buffer.length; kfree(buffer.pointer); - return obj->buffer.length; + return len; } bool radeon_atrm_supported(struct pci_dev *pdev) From 304a48400d9718f74ec35ae46f30868a5f4c4516 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 2 Feb 2012 10:18:00 -0500 Subject: [PATCH 300/380] drm/radeon/kms: fix TRAVIS panel setup Different versions of the DP to LVDS bridge chip need different panel mode settings depending on the chip version used. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=41569 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_dp.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index a71557ce01dc..552b436451fd 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -564,9 +564,21 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, ENCODER_OBJECT_ID_NUTMEG) panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == - ENCODER_OBJECT_ID_TRAVIS) - panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; - else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + ENCODER_OBJECT_ID_TRAVIS) { + u8 id[6]; + int i; + for (i = 0; i < 6; i++) + id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i); + if (id[0] == 0x73 && + id[1] == 0x69 && + id[2] == 0x76 && + id[3] == 0x61 && + id[4] == 0x72 && + id[5] == 0x54) + panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; + else + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; From 52b53a0bf8026a322cfa6cfec6a10dd31fef8752 Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Thu, 2 Feb 2012 10:26:24 -0500 Subject: [PATCH 301/380] drm/radeon/kms/blit: fix blit copy for very large buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Evergreen and NI blit copy was broken if the buffer maps to a rectangle whose one dimension is 16384 (max dimension allowed by these chips). In the mainline kernel, the problem is exposed only when buffers are very large (1G), but it's still a problem. The problem could be exposed for smaller buffers if anyone modifies the algorithm for rectangle construction in r600_blit_create_rect() (the reason why someone would modify that algorithm is to tune the performance of buffer moves). The root cause was in i2f() function which only operated on range between 0 and 16383. Fix this by extending the range of i2f() function to 0 to 32767. While at it improve the function so that the range can be easily extended in the future (if it becomes necessary), cleanup lines over 80 characters, and replace in-line comments with one strategic comment that explains the crux of the function. Credits to michel@daenzer.net for pointing out the root cause of the bug. v2: Fix I2F_MAX_INPUT constant definition goof and warn only once if input argument is out of range. Edit the comment a little bit to avoid some linguistic confusion and make it look better in general. Signed-off-by: Ilija Hadzic Reviewed-by: Alex Deucher Reviewed-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_blit_kms.c | 35 ++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index d996f4381130..accc032c103f 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -468,27 +468,42 @@ set_default_state(struct radeon_device *rdev) radeon_ring_write(ring, sq_stack_resource_mgmt_2); } +#define I2F_MAX_BITS 15 +#define I2F_MAX_INPUT ((1 << I2F_MAX_BITS) - 1) +#define I2F_SHIFT (24 - I2F_MAX_BITS) + +/* + * Converts unsigned integer into 32-bit IEEE floating point representation. + * Conversion is not universal and only works for the range from 0 + * to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between + * 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary, + * I2F_MAX_BITS can be increased, but that will add to the loop iterations + * and slow us down. Conversion is done by shifting the input and counting + * down until the first 1 reaches bit position 23. The resulting counter + * and the shifted input are, respectively, the exponent and the fraction. + * The sign is always zero. + */ static uint32_t i2f(uint32_t input) { u32 result, i, exponent, fraction; - if ((input & 0x3fff) == 0) - result = 0; /* 0 is a special case */ + WARN_ON_ONCE(input > I2F_MAX_INPUT); + + if ((input & I2F_MAX_INPUT) == 0) + result = 0; else { - exponent = 140; /* exponent biased by 127; */ - fraction = (input & 0x3fff) << 10; /* cheat and only - handle numbers below 2^^15 */ - for (i = 0; i < 14; i++) { + exponent = 126 + I2F_MAX_BITS; + fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT; + + for (i = 0; i < I2F_MAX_BITS; i++) { if (fraction & 0x800000) break; else { - fraction = fraction << 1; /* keep - shifting left until top bit = 1 */ + fraction = fraction << 1; exponent = exponent - 1; } } - result = exponent << 23 | (fraction & 0x7fffff); /* mask - off top bit; assumed 1 */ + result = exponent << 23 | (fraction & 0x7fffff); } return result; } From 97f1040982d7935716e9a45a26ccd5cc8fe92f8c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 29 Jan 2012 14:55:21 +0000 Subject: [PATCH 302/380] Revert "ARM: 7304/1: ioremap: fix boundary check when reusing static mapping" This reverts commit 3c424f359898aff48c3d5bed608ac706f8a528c3. Joachim Eastwood reports: | "ARM: 7304/1: ioremap: fix boundary check when reusing static mapping" | Commit: 3c424f359898aff48c3d5bed608ac706f8a528c3 in Linus master | | Breaks booting on my custom AT91RM9200 board. | There isn't any error messages or anything that indicates what goes | wrong it just stops after; Uncompressing Linux... done, booting the | kernel. | | Reverting it makes my board boot again. and further debugging reveals: ioremap: pfn=fffff phys=fffff000 offset=400 size=1000 ioremap: area c3ffdfc0: phys_addr=200000 pfn=200 size=4000 ioremap: found: addr fef74000 => fed73000 => fed73400 Clearly, an area for pfn 0x200, 16K can't ever satisfy a request for pfn 0xfffff. This happens because the changed if statement becomes: if (0x00200 > 0xfffff || 0xfffff000 + 0x400 + 0x1000-1 > 0x00200000 + 0x4000-1) and therefore: if (0x00200 > 0xfffff || 0x000003ff > 0x00203fff) The if condition fails, and so we _believe_ that the SRAM mapping fits our request. Clearly that's totally bogus. Moreover, the original premise of the 'fix' patch was wrong: | The condition checking boundaries of the requested and existing | mappings didn't take in-page offset into consideration though, | which lead to obscure and hard to debug problems when requested | mapping crossed end of the static one. as the code immediately above this loop does: size = PAGE_ALIGN(offset + size); so 'size' already contains the requested offset into the page. So, revert the broken 'fix'. Acked-by: Nicolas Pitre --- arch/arm/mm/ioremap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index ba159370fa5f..80632e8d7538 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -225,8 +225,7 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype)) continue; if (__phys_to_pfn(area->phys_addr) > pfn || - __pfn_to_phys(pfn) + offset + size-1 > - area->phys_addr + area->size-1) + __pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1) continue; /* we can drop the lock here as we know *area is static */ read_unlock(&vmlist_lock); From 2af276dfb1722e97b190bd2e646b079a2aa674db Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 30 Jan 2012 20:21:42 +0100 Subject: [PATCH 303/380] ARM: 7306/1: vfp: flush thread hwstate before restoring context from sigframe Following execution of a signal handler, we currently restore the VFP context from the ucontext in the signal frame. This involves copying from the user stack into the current thread's vfp_hard_struct and then flushing the new data out to the hardware registers. This is problematic when using a preemptible kernel because we could be context switched whilst updating the vfp_hard_struct. If the current thread has made use of VFP since the last context switch, the VFP notifier will copy from the hardware registers into the vfp_hard_struct, overwriting any data that had been partially copied by the signal code. Disabling preemption across copy_from_user calls is a terrible idea, so instead we move the VFP thread flush *before* we update the vfp_hard_struct. Since the flushing is performed lazily, this has the effect of disabling VFP and clearing the CPU's VFP state pointer, therefore preventing the thread from being updated with stale data on the next context switch. Cc: stable Tested-by: Peter Maydell Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/signal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 0340224cf73c..9e617bd4a146 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -227,6 +227,8 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame) if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) return -EINVAL; + vfp_flush_hwstate(thread); + /* * Copy the floating point registers. There can be unused * registers see asm/hwcap.h for details. @@ -251,9 +253,6 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame) __get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err); __get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err); - if (!err) - vfp_flush_hwstate(thread); - return err ? -EFAULT : 0; } From 247f4993a5974e6759606c4d380748eecfd273ff Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Mon, 30 Jan 2012 20:22:28 +0100 Subject: [PATCH 304/380] ARM: 7307/1: vfp: fix ptrace regset modification race In a preemptible kernel, vfp_set() can be preempted, causing the hardware VFP context to be switched while the thread vfp state is being read and modified. This leads to a race condition which can cause the thread vfp state to become corrupted if lazy VFP context save occurs due to preemption in between the time thread->vfpstate is read and the time the modified state is written back. This may occur if preemption occurs during the execution of a ptrace() call which modifies the VFP register state of a thread. Such instances should be very rare in most realistic scenarios -- none has been reported, so far as I am aware. Only uniprocessor systems should be affected, since VFP context save is not currently lazy in SMP kernels. The problem was introduced by my earlier patch migrating to use regsets to implement ptrace. This patch does a vfp_sync_hwstate() before reading thread->vfpstate, to make sure that the thread's VFP state is not live in the hardware registers while the registers are modified. Thanks to Will Deacon for spotting this. Cc: stable Signed-off-by: Dave Martin Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/ptrace.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index e1d5e1929fbd..d001be4e0ce1 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -699,10 +699,13 @@ static int vfp_set(struct task_struct *target, { int ret; struct thread_info *thread = task_thread_info(target); - struct vfp_hard_struct new_vfp = thread->vfpstate.hard; + struct vfp_hard_struct new_vfp; const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); + vfp_sync_hwstate(thread); + new_vfp = thread->vfpstate.hard; + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &new_vfp.fpregs, user_fpregs_offset, @@ -723,7 +726,6 @@ static int vfp_set(struct task_struct *target, if (ret) return ret; - vfp_sync_hwstate(thread); thread->vfpstate.hard = new_vfp; vfp_flush_hwstate(thread); From 8130b9d7b9d858aa04ce67805e8951e3cb6e9b2f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 30 Jan 2012 20:23:29 +0100 Subject: [PATCH 305/380] ARM: 7308/1: vfp: flush thread hwstate before copying ptrace registers If we are context switched whilst copying into a thread's vfp_hard_struct then the partial copy may be corrupted by the VFP context switching code (see "ARM: vfp: flush thread hwstate before restoring context from sigframe"). This patch updates the ptrace VFP set code so that the thread state is flushed before the copy, therefore disabling VFP and preventing corruption from occurring. Cc: stable Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index d001be4e0ce1..e33870ff0ac0 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -726,8 +726,8 @@ static int vfp_set(struct task_struct *target, if (ret) return ret; - thread->vfpstate.hard = new_vfp; vfp_flush_hwstate(thread); + thread->vfpstate.hard = new_vfp; return 0; } From 91756acb58b17aee68d055fc15b1e2550ff00801 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 25 Jan 2012 19:36:28 +0100 Subject: [PATCH 306/380] ARM: 7303/1: perf: add empty NODE event definitions for Cortex-A5 and Cortex-A15 Commit 89d6c0b5 ("perf, arch: Add generic NODE cache events") added empty NODE event definitions for the ARM PMU implementations. This was merged along with Cortex-A5 and Cortex-A15 PMU support, so they missed out on the original patch. This patch adds the empty definitions to Cortex-A5 and Cortex-A15. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/perf_event_v7.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 460bbbb6b885..6933244c68f9 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -469,6 +469,20 @@ static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, }, + [C(NODE)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, }; /* @@ -579,6 +593,20 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, }, + [C(NODE)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, }; /* From 6d3ec1ae6cdcda185bd9452b2daed5145e2493a5 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 25 Jan 2012 11:54:22 +0100 Subject: [PATCH 307/380] ARM: 7302/1: Add TLB flushing for both entries in a PMD Linux uses two PMD entries for a PTE with the classic page table format, covering 2MB range. However, the __pte_free_tlb() function only adds a single TLB flush corresponding to 1MB range covering 'addr'. On Cortex-A15, level 1 entries can be cached by the TLB independently of the level 2 entries and without additional flushing a PMD entry would be left pointing at the wrong PTE. The patch limits the TLB flushing range to two 4KB pages around the 1MB boundary within PMD. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/tlb.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 5d3ed7e38561..314d4664eae7 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h @@ -198,7 +198,15 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr) { pgtable_page_dtor(pte); - tlb_add_flush(tlb, addr); + + /* + * With the classic ARM MMU, a pte page has two corresponding pmd + * entries, each covering 1MB. + */ + addr &= PMD_MASK; + tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); + tlb_add_flush(tlb, addr + SZ_1M); + tlb_remove_page(tlb, pte); } From 114fc47492e23d93653e4a16664833e98d62a563 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 11 Jan 2012 17:41:01 -0800 Subject: [PATCH 308/380] ceph: change "ceph.layout" xattr to be "ceph.file.layout" The virtual extended attribute named "ceph.layout" is meaningful only for regular files. Change its name to be "ceph.file.layout" to more directly reflect that in the ceph xattr namespace. Preserve the old "ceph.layout" name for the time being (until we decide it's safe to get rid of it entirely). Add a missing initializer for "readonly" in the terminating entry. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- fs/ceph/xattr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index a5e36e4488a7..9e6734e38c12 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -111,8 +111,10 @@ static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val, } static struct ceph_vxattr_cb ceph_file_vxattrs[] = { + { true, "ceph.file.layout", ceph_vxattrcb_layout}, + /* The following extended attribute name is deprecated */ { true, "ceph.layout", ceph_vxattrcb_layout}, - { NULL, NULL } + { true, NULL, NULL } }; static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode) From ab434b60ab07f8c44246b6fb0cddee436687a09a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 13 Jan 2012 22:22:03 -0800 Subject: [PATCH 309/380] ceph: initialize client debugfs outside of monc->mutex Initializing debufs under monc->mutex introduces a lock dependency for sb->s_type->i_mutex_key, which (combined with several other dependencies) leads to an annoying lockdep warning. There's no particular reason to do the debugfs setup under this lock, so move it out. It used to be the case that our first monmap could come from the OSD; that is no longer the case with recent servers, so we will reliably set up the client entry during the initial authentication. We don't have to worry about racing with debugfs teardown by ceph_debugfs_client_cleanup() because ceph_destroy_client() calls ceph_msgr_flush() first, which will wait for the message dispatch work to complete (and the debugfs init to complete). Fixes: #1940 Signed-off-by: Sage Weil --- net/ceph/ceph_common.c | 2 -- net/ceph/mon_client.c | 13 ++++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 97f70e50ad3b..761ad9d6cc3b 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -85,8 +85,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) } else { pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); memcpy(&client->fsid, fsid, sizeof(*fsid)); - ceph_debugfs_client_init(client); - client->have_fsid = true; } return 0; } diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 0b62deae42bd..1845cde26227 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -8,8 +8,8 @@ #include #include +#include #include - #include /* @@ -340,8 +340,19 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, client->monc.monmap = monmap; kfree(old); + if (!client->have_fsid) { + client->have_fsid = true; + mutex_unlock(&monc->mutex); + /* + * do debugfs initialization without mutex to avoid + * creating a locking dependency + */ + ceph_debugfs_client_init(client); + goto out_unlocked; + } out: mutex_unlock(&monc->mutex); +out_unlocked: wake_up_all(&client->auth_wq); } From 32852a81bccd9e3d1953b894966393d1b546576d Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Sat, 14 Jan 2012 22:20:59 -0500 Subject: [PATCH 310/380] ceph: fix length validation in parse_reply_info() "len" is read from network and thus needs validation. Otherwise, given a bogus "len" value, p+len could be an out-of-bounds pointer, which is used in further parsing. Signed-off-by: Xi Wang Signed-off-by: Sage Weil --- fs/ceph/mds_client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 6203d805eb45..be1415fcaac8 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -262,6 +262,7 @@ static int parse_reply_info(struct ceph_msg *msg, /* trace */ ceph_decode_32_safe(&p, end, len, bad); if (len > 0) { + ceph_decode_need(&p, end, len, bad); err = parse_reply_info_trace(&p, p+len, info, features); if (err < 0) goto out_bad; @@ -270,6 +271,7 @@ static int parse_reply_info(struct ceph_msg *msg, /* extra */ ceph_decode_32_safe(&p, end, len, bad); if (len > 0) { + ceph_decode_need(&p, end, len, bad); err = parse_reply_info_extra(&p, p+len, info, features); if (err < 0) goto out_bad; From d8fb02abdc39f92a1066313e2b17047876afa8f9 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Thu, 12 Jan 2012 17:48:10 -0800 Subject: [PATCH 311/380] ceph: create a new session lock to avoid lock inversion Lockdep was reporting a possible circular lock dependency in dentry_lease_is_valid(). That function needs to sample the session's s_cap_gen and and s_cap_ttl fields coherently, but needs to do so while holding a dentry lock. The s_cap_lock field was being used to protect the two fields, but that can't be taken while holding a lock on a dentry within the session. In most cases, the s_cap_gen and s_cap_ttl fields only get operated on separately. But in three cases they need to be updated together. Implement a new lock to protect the spots updating both fields atomically is required. Signed-off-by: Alex Elder Reviewed-by: Sage Weil --- fs/ceph/caps.c | 4 ++-- fs/ceph/dir.c | 4 ++-- fs/ceph/mds_client.c | 8 +++++--- fs/ceph/mds_client.h | 7 +++++-- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 8b53193e4f7c..90d789df9ce0 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -641,10 +641,10 @@ static int __cap_is_valid(struct ceph_cap *cap) unsigned long ttl; u32 gen; - spin_lock(&cap->session->s_cap_lock); + spin_lock(&cap->session->s_gen_ttl_lock); gen = cap->session->s_cap_gen; ttl = cap->session->s_cap_ttl; - spin_unlock(&cap->session->s_cap_lock); + spin_unlock(&cap->session->s_gen_ttl_lock); if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) { dout("__cap_is_valid %p cap %p issued %s " diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 98954003a8d3..63c52f33361b 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -975,10 +975,10 @@ static int dentry_lease_is_valid(struct dentry *dentry) di = ceph_dentry(dentry); if (di && di->lease_session) { s = di->lease_session; - spin_lock(&s->s_cap_lock); + spin_lock(&s->s_gen_ttl_lock); gen = s->s_cap_gen; ttl = s->s_cap_ttl; - spin_unlock(&s->s_cap_lock); + spin_unlock(&s->s_gen_ttl_lock); if (di->lease_gen == gen && time_before(jiffies, dentry->d_time) && diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index be1415fcaac8..a4fdf9397a90 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -400,9 +400,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; s->s_con.peer_name.num = cpu_to_le64(mds); - spin_lock_init(&s->s_cap_lock); + spin_lock_init(&s->s_gen_ttl_lock); s->s_cap_gen = 0; s->s_cap_ttl = 0; + + spin_lock_init(&s->s_cap_lock); s->s_renew_requested = 0; s->s_renew_seq = 0; INIT_LIST_HEAD(&s->s_caps); @@ -2328,10 +2330,10 @@ static void handle_session(struct ceph_mds_session *session, case CEPH_SESSION_STALE: pr_info("mds%d caps went stale, renewing\n", session->s_mds); - spin_lock(&session->s_cap_lock); + spin_lock(&session->s_gen_ttl_lock); session->s_cap_gen++; session->s_cap_ttl = 0; - spin_unlock(&session->s_cap_lock); + spin_unlock(&session->s_gen_ttl_lock); send_renew_caps(mdsc, session); break; diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index a50ca0e39475..8c7c04ebb595 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -117,10 +117,13 @@ struct ceph_mds_session { void *s_authorizer_buf, *s_authorizer_reply_buf; size_t s_authorizer_buf_len, s_authorizer_reply_buf_len; - /* protected by s_cap_lock */ - spinlock_t s_cap_lock; + /* protected by s_gen_ttl_lock */ + spinlock_t s_gen_ttl_lock; u32 s_cap_gen; /* inc each time we get mds stale msg */ unsigned long s_cap_ttl; /* when session caps expire */ + + /* protected by s_cap_lock */ + spinlock_t s_cap_lock; struct list_head s_caps; /* all caps issued by this session */ int s_nr_caps, s_trim_caps; int s_num_cap_releases; From 97bb59a03dd6767fcc00be09b0c6d9e5294eeea6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 24 Jan 2012 10:08:36 -0600 Subject: [PATCH 312/380] rbd: fix a memory leak in rbd_get_client() If an existing rbd client is found to be suitable for use in rbd_get_client(), the rbd_options structure is not being freed as it should. Fix that. Signed-off-by: Alex Elder Signed-off-by: Sage Weil --- drivers/block/rbd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 148ab944378d..7d8f8ddb3359 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -380,6 +380,7 @@ static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr, rbdc = __rbd_client_find(opt); if (rbdc) { ceph_destroy_options(opt); + kfree(rbd_opts); /* using an existing client */ kref_get(&rbdc->kref); From 8cdb878dcb359fd1137e9abdee9322f5e9bcfdf8 Mon Sep 17 00:00:00 2001 From: Christopher Yeoh Date: Thu, 2 Feb 2012 11:34:09 +1030 Subject: [PATCH 313/380] Fix race in process_vm_rw_core This fixes the race in process_vm_core found by Oleg (see http://article.gmane.org/gmane.linux.kernel/1235667/ for details). This has been updated since I last sent it as the creation of the new mm_access() function did almost exactly the same thing as parts of the previous version of this patch did. In order to use mm_access() even when /proc isn't enabled, we move it to kernel/fork.c where other related process mm access functions already are. Signed-off-by: Chris Yeoh Signed-off-by: Linus Torvalds --- fs/proc/base.c | 20 -------------------- include/linux/sched.h | 6 ++++++ kernel/fork.c | 20 ++++++++++++++++++++ mm/process_vm_access.c | 23 +++++++++-------------- 4 files changed, 35 insertions(+), 34 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index d9512bd03e6c..d4548dd49b02 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -198,26 +198,6 @@ static int proc_root_link(struct dentry *dentry, struct path *path) return result; } -static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) -{ - struct mm_struct *mm; - int err; - - err = mutex_lock_killable(&task->signal->cred_guard_mutex); - if (err) - return ERR_PTR(err); - - mm = get_task_mm(task); - if (mm && mm != current->mm && - !ptrace_may_access(task, mode)) { - mmput(mm); - mm = ERR_PTR(-EACCES); - } - mutex_unlock(&task->signal->cred_guard_mutex); - - return mm; -} - struct mm_struct *mm_for_maps(struct task_struct *task) { return mm_access(task, PTRACE_MODE_READ); diff --git a/include/linux/sched.h b/include/linux/sched.h index 2234985a5e65..7d379a6bfd88 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2259,6 +2259,12 @@ static inline void mmdrop(struct mm_struct * mm) extern void mmput(struct mm_struct *); /* Grab a reference to a task's mm, if it is not already going away */ extern struct mm_struct *get_task_mm(struct task_struct *task); +/* + * Grab a reference to a task's mm, if it is not already going away + * and ptrace_may_access with the mode parameter passed to it + * succeeds. + */ +extern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode); /* Remove the current tasks stale references to the old mm_struct */ extern void mm_release(struct task_struct *, struct mm_struct *); /* Allocate a new mm structure and copy contents from tsk->mm */ diff --git a/kernel/fork.c b/kernel/fork.c index 051f090d40c1..1b2ef3c23ae4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -647,6 +647,26 @@ struct mm_struct *get_task_mm(struct task_struct *task) } EXPORT_SYMBOL_GPL(get_task_mm); +struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) +{ + struct mm_struct *mm; + int err; + + err = mutex_lock_killable(&task->signal->cred_guard_mutex); + if (err) + return ERR_PTR(err); + + mm = get_task_mm(task); + if (mm && mm != current->mm && + !ptrace_may_access(task, mode)) { + mmput(mm); + mm = ERR_PTR(-EACCES); + } + mutex_unlock(&task->signal->cred_guard_mutex); + + return mm; +} + /* Please note the differences between mmput and mm_release. * mmput is called whenever we stop holding onto a mm_struct, * error success whatever. diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index e920aa3ce104..c20ff48994c2 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c @@ -298,22 +298,17 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec, goto free_proc_pages; } - task_lock(task); - if (__ptrace_may_access(task, PTRACE_MODE_ATTACH)) { - task_unlock(task); - rc = -EPERM; + mm = mm_access(task, PTRACE_MODE_ATTACH); + if (!mm || IS_ERR(mm)) { + rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH; + /* + * Explicitly map EACCES to EPERM as EPERM is a more a + * appropriate error code for process_vw_readv/writev + */ + if (rc == -EACCES) + rc = -EPERM; goto put_task_struct; } - mm = task->mm; - - if (!mm || (task->flags & PF_KTHREAD)) { - task_unlock(task); - rc = -EINVAL; - goto put_task_struct; - } - - atomic_inc(&mm->mm_users); - task_unlock(task); for (i = 0; i < riovcnt && iov_l_curr_idx < liovcnt; i++) { rc = process_vm_rw_single_vec( From 486d8b9f88cd0871a716e2f16873e811ee6c1ece Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 2 Feb 2012 12:55:58 -0800 Subject: [PATCH 314/380] IB/srpt: Use DEFINE_SPINLOCK()/LIST_HEAD() Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srpt/ib_srpt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index cd5d05e22a77..284cb5092ee4 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -69,8 +69,8 @@ MODULE_LICENSE("Dual BSD/GPL"); */ static u64 srpt_service_guid; -static spinlock_t srpt_dev_lock; /* Protects srpt_dev_list. */ -static struct list_head srpt_dev_list; /* List of srpt_device structures. */ +static DEFINE_SPINLOCK(srpt_dev_lock); /* Protects srpt_dev_list. */ +static LIST_HEAD(srpt_dev_list); /* List of srpt_device structures. */ static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE; module_param(srp_max_req_size, int, 0444); @@ -4010,9 +4010,6 @@ static int __init srpt_init_module(void) goto out; } - spin_lock_init(&srpt_dev_lock); - INIT_LIST_HEAD(&srpt_dev_list); - ret = -ENODEV; srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt"); if (!srpt_target) { From f225066b64eaffe3a51ee488fb750c82fbcd971c Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 2 Feb 2012 12:55:58 -0800 Subject: [PATCH 315/380] IB/srpt: Use ARRAY_SIZE() instead of open-coding Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srpt/ib_srpt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 284cb5092ee4..38ef61dbee0a 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -3264,8 +3264,7 @@ static void srpt_add_one(struct ib_device *device) for (i = 0; i < sdev->srq_size; ++i) srpt_post_recv(sdev, sdev->ioctx_ring[i]); - WARN_ON(sdev->device->phys_port_cnt - > sizeof(sdev->port)/sizeof(sdev->port[0])); + WARN_ON(sdev->device->phys_port_cnt > ARRAY_SIZE(sdev->port)); for (i = 1; i <= sdev->device->phys_port_cnt; i++) { sport = &sdev->port[i - 1]; From ebfded8c4b34caea450709ce467e67483fa4d8df Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 2 Feb 2012 12:55:59 -0800 Subject: [PATCH 316/380] IB/srpt: Remove unneeded include Signed-off-by: Jesper Juhl Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srpt/ib_srpt.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index b4b4bbcd7f16..61e52b830816 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h @@ -35,7 +35,6 @@ #ifndef IB_SRPT_H #define IB_SRPT_H -#include #include #include #include From d23a4b3fd6ef70b80411b39b8c8bc548a219ce70 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sun, 29 Jan 2012 13:57:43 -0600 Subject: [PATCH 317/380] rbd: fix safety of rbd_put_client() The rbd_client structure uses a kref to arrange for cleaning up and freeing an instance when its last reference is dropped. The cleanup routine is rbd_client_release(), and one of the things it does is delete the rbd_client from rbd_client_list. It acquires node_lock to do so, but the way it is done is still not safe. The problem is that when attempting to reuse an existing rbd_client, the structure found might already be in the process of getting destroyed and cleaned up. Here's the scenario, with "CLIENT" representing an existing rbd_client that's involved in the race: Thread on CPU A | Thread on CPU B --------------- | --------------- rbd_put_client(CLIENT) | rbd_get_client() kref_put() | (acquires node_lock) kref->refcount becomes 0 | __rbd_client_find() returns CLIENT calls rbd_client_release() | kref_get(&CLIENT->kref); | (releases node_lock) (acquires node_lock) | deletes CLIENT from list | ...and starts using CLIENT... (releases node_lock) | and frees CLIENT | <-- but CLIENT gets freed here Fix this by having rbd_put_client() acquire node_lock. The result could still be improved, but at least it avoids this problem. Signed-off-by: Alex Elder Signed-off-by: Sage Weil --- drivers/block/rbd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 7d8f8ddb3359..7f40cb4553c9 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -407,15 +407,15 @@ done_err: /* * Destroy ceph client + * + * Caller must hold node_lock. */ static void rbd_client_release(struct kref *kref) { struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref); dout("rbd_release_client %p\n", rbdc); - spin_lock(&node_lock); list_del(&rbdc->node); - spin_unlock(&node_lock); ceph_destroy_client(rbdc->client); kfree(rbdc->rbd_opts); @@ -428,7 +428,9 @@ static void rbd_client_release(struct kref *kref) */ static void rbd_put_client(struct rbd_device *rbd_dev) { + spin_lock(&node_lock); kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); + spin_unlock(&node_lock); rbd_dev->rbd_client = NULL; rbd_dev->client = NULL; } From de47a4176c532ef5961b8a46a2d541a3517412d3 Mon Sep 17 00:00:00 2001 From: Shirish Pargaonkar Date: Thu, 2 Feb 2012 15:28:28 -0600 Subject: [PATCH 318/380] cifs: Fix oops in session setup code for null user mounts For null user mounts, do not invoke string length function during session setup. Cc: Acked-by: Jeff Layton Signed-off-by: Shirish Pargaonkar Signed-off-by: Steve French --- fs/cifs/sess.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index eb767412177d..551d0c2b9736 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -246,16 +246,15 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, /* copy user */ /* BB what about null user mounts - check that we do this BB */ /* copy user */ - if (ses->user_name != NULL) + if (ses->user_name != NULL) { strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE); + bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE); + } /* else null user mount */ - - bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE); *bcc_ptr = 0; bcc_ptr++; /* account for null termination */ /* copy domain */ - if (ses->domainName != NULL) { strncpy(bcc_ptr, ses->domainName, 256); bcc_ptr += strnlen(ses->domainName, 256); From ff05f603c3238010769787f3ba54c48c290ed3e5 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 2 Feb 2012 15:29:08 -0800 Subject: [PATCH 319/380] include/linux/lp8727.h: Remove executable bit Signed-off-by: Josh Triplett Signed-off-by: Linus Torvalds --- include/linux/lp8727.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 include/linux/lp8727.h diff --git a/include/linux/lp8727.h b/include/linux/lp8727.h old mode 100755 new mode 100644 From 82b982c9a697e7be0745523a53334fe38a4582c8 Mon Sep 17 00:00:00 2001 From: Igor Murzov Date: Fri, 3 Feb 2012 00:19:07 -0800 Subject: [PATCH 320/380] Input: i8042 - add Lenovo Ideapad U455 to 'reset' blacklist From 2d5a38a56453421e82428155f4b00303f3fb19b2 Mon Sep 17 00:00:00 2001 From: Igor Murzov Date: Wed, 1 Feb 2012 03:11:53 +0400 Subject: [PATCH] Input: i8042 - add Lenovo Ideapad U455 to 'reset' blacklist Lenovo Ideapad U455 needs to be in the reset quirk list for its touchpad's proper function. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=40672 Signed-off-by: Igor Murzov Signed-off-by: Dmitry Torokhov --- 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 b4cfc6c8be89..5ec774d6c82b 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -512,6 +512,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"), }, }, + { + /* Lenovo Ideapad U455 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20046"), + }, + }, { } }; From b544d1e0e233f83a2e6d20ee96b54ea272d5d5ba Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Feb 2012 11:56:35 +0100 Subject: [PATCH 321/380] ALSA: hda/realtek - Add missing Bass and CLFE as vmaster slaves The recent changes in Realtek auto-parser added the new "Bass Speaker" and "CLFE" mixer elements which should be tracked as vmaster slaves, too. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42720 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a8e82be3d2fc..33b6077fcdb8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1855,6 +1855,8 @@ static const char * const alc_slave_vols[] = { "Speaker Playback Volume", "Mono Playback Volume", "Line-Out Playback Volume", + "CLFE Playback Volume", + "Bass Speaker Playback Volume", "PCM Playback Volume", NULL, }; @@ -1870,6 +1872,8 @@ static const char * const alc_slave_sws[] = { "Mono Playback Switch", "IEC958 Playback Switch", "Line-Out Playback Switch", + "CLFE Playback Switch", + "Bass Speaker Playback Switch", "PCM Playback Switch", NULL, }; From 5a97d0ae5b5d78727b87965cba84194a9f1e06ce Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 3 Feb 2012 11:08:05 +0100 Subject: [PATCH 322/380] ARM: 7314/1: kuser: consistently use usr_ret for returning from helpers __kuser_cmpxchg64 has a return path using bx lr to get back to the caller. This is actually ok since the code in question is predicated on CONFIG_CPU_32v6K, but for the sake of consistency using the usr_ret macro is probably better. Acked-by: Dave Martin Acked-by: Nicolas Pitre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 3a456c6c7005..be16a48007b4 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -790,7 +790,7 @@ __kuser_cmpxchg64: @ 0xffff0f60 smp_dmb arm rsbs r0, r3, #0 @ set returned val and C flag ldmfd sp!, {r4, r5, r6, r7} - bx lr + usr_ret lr #elif !defined(CONFIG_SMP) From 3af336376f77859da84bb1156ef29d5337b316a9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 4 Nov 2011 21:27:32 +0300 Subject: [PATCH 323/380] IB/srpt: Fix ERR_PTR() vs. NULL checking confusion transport_init_session() and target_fabric_configfs_init() don't return NULL pointers, they only return ERR_PTRs or valid pointers. Signed-off-by: Dan Carpenter Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srpt/ib_srpt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 38ef61dbee0a..c125614ac256 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -2595,7 +2595,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, } ch->sess = transport_init_session(); - if (!ch->sess) { + if (IS_ERR(ch->sess)) { rej->reason = __constant_cpu_to_be32( SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); pr_debug("Failed to create session\n"); @@ -4009,10 +4009,10 @@ static int __init srpt_init_module(void) goto out; } - ret = -ENODEV; srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt"); - if (!srpt_target) { + if (IS_ERR(srpt_target)) { printk(KERN_ERR "couldn't register\n"); + ret = PTR_ERR(srpt_target); goto out; } From f8447d6c213273b444c81eaa2449f55510229d4f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Sat, 14 Jan 2012 20:58:43 +0100 Subject: [PATCH 324/380] mfd: Store twl6040-codec mclk configuration Store the last used mclk configuration for the PLL. Signed-off-by: Peter Ujfalusi Signed-off-by: Samuel Ortiz --- drivers/mfd/twl6040-core.c | 3 +++ include/linux/mfd/twl6040.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index dda86293dc9f..c2088f4c4547 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; twl6040->sysclk = 19200000; + twl6040->mclk = 32768; } else { /* already powered-down */ if (!twl6040->power_count) { @@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) twl6040_power_down(twl6040); } twl6040->sysclk = 0; + twl6040->mclk = 0; } out: @@ -421,6 +423,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, } twl6040->sysclk = freq_out; + twl6040->mclk = freq_in; twl6040->pll = pll_id; pll_out: diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 2463c2619596..9bc9ac651dad 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -187,8 +187,10 @@ struct twl6040 { int rev; u8 vibra_ctrl_cache[2]; + /* PLL configuration */ int pll; unsigned int sysclk; + unsigned int mclk; unsigned int irq; unsigned int irq_base; From 2bd05db718cf452fe235c7c08083b2e60f787f3a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Sat, 14 Jan 2012 20:58:44 +0100 Subject: [PATCH 325/380] mfd: Avoid twl6040-codec PLL reconfiguration when not needed Do not reconfigure the PLL in case it has been configured already with the requested parameters. In case of different PLL configuration do only the needed changes. This can save considerable amount of time since we can avoid the defined protocol (with delays) for the PLL configuration. Signed-off-by: Peter Ujfalusi Signed-off-by: Samuel Ortiz --- drivers/mfd/twl6040-core.c | 125 ++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 51 deletions(-) diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index c2088f4c4547..b2d8e512d3cb 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -326,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL); lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL); + /* Force full reconfiguration when switching between PLL */ + if (pll_id != twl6040->pll) { + twl6040->sysclk = 0; + twl6040->mclk = 0; + } + switch (pll_id) { case TWL6040_SYSCLK_SEL_LPPLL: /* low-power PLL divider */ - switch (freq_out) { - case 17640000: - lppllctl |= TWL6040_LPLLFIN; - break; - case 19200000: - lppllctl &= ~TWL6040_LPLLFIN; - break; - default: - dev_err(twl6040->dev, - "freq_out %d not supported\n", freq_out); - ret = -EINVAL; - goto pll_out; + /* Change the sysclk configuration only if it has been canged */ + if (twl6040->sysclk != freq_out) { + switch (freq_out) { + case 17640000: + lppllctl |= TWL6040_LPLLFIN; + break; + case 19200000: + lppllctl &= ~TWL6040_LPLLFIN; + break; + default: + dev_err(twl6040->dev, + "freq_out %d not supported\n", + freq_out); + ret = -EINVAL; + goto pll_out; + } + twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, + lppllctl); } - twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); + + /* The PLL in use has not been change, we can exit */ + if (twl6040->pll == pll_id) + break; switch (freq_in) { case 32768: @@ -373,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } - hppllctl &= ~TWL6040_MCLK_MSK; + if (twl6040->mclk != freq_in) { + hppllctl &= ~TWL6040_MCLK_MSK; + + switch (freq_in) { + case 12000000: + /* PLL enabled, active mode */ + hppllctl |= TWL6040_MCLK_12000KHZ | + TWL6040_HPLLENA; + break; + case 19200000: + /* + * PLL disabled + * (enable PLL if MCLK jitter quality + * doesn't meet specification) + */ + hppllctl |= TWL6040_MCLK_19200KHZ; + break; + case 26000000: + /* PLL enabled, active mode */ + hppllctl |= TWL6040_MCLK_26000KHZ | + TWL6040_HPLLENA; + break; + case 38400000: + /* PLL enabled, active mode */ + hppllctl |= TWL6040_MCLK_38400KHZ | + TWL6040_HPLLENA; + break; + default: + dev_err(twl6040->dev, + "freq_in %d not supported\n", freq_in); + ret = -EINVAL; + goto pll_out; + } - switch (freq_in) { - case 12000000: - /* PLL enabled, active mode */ - hppllctl |= TWL6040_MCLK_12000KHZ | - TWL6040_HPLLENA; - break; - case 19200000: /* - * PLL disabled - * (enable PLL if MCLK jitter quality - * doesn't meet specification) + * enable clock slicer to ensure input waveform is + * square */ - hppllctl |= TWL6040_MCLK_19200KHZ; - break; - case 26000000: - /* PLL enabled, active mode */ - hppllctl |= TWL6040_MCLK_26000KHZ | - TWL6040_HPLLENA; - break; - case 38400000: - /* PLL enabled, active mode */ - hppllctl |= TWL6040_MCLK_38400KHZ | - TWL6040_HPLLENA; - break; - default: - dev_err(twl6040->dev, - "freq_in %d not supported\n", freq_in); - ret = -EINVAL; - goto pll_out; + hppllctl |= TWL6040_HPLLSQRENA; + + twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, + hppllctl); + usleep_range(500, 700); + lppllctl |= TWL6040_HPLLSEL; + twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, + lppllctl); + lppllctl &= ~TWL6040_LPLLENA; + twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, + lppllctl); } - - /* enable clock slicer to ensure input waveform is square */ - hppllctl |= TWL6040_HPLLSQRENA; - - twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl); - usleep_range(500, 700); - lppllctl |= TWL6040_HPLLSEL; - twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); - lppllctl &= ~TWL6040_LPLLENA; - twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); break; default: dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); From 20d16fef95fb2924228dce0078fdfec5429f84f2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 3 Feb 2012 15:37:11 -0800 Subject: [PATCH 326/380] MAINTAINERS: update partitions block F: patterns Commit 9be96f3fd101 ("move fs/partitions to block/") moved the files, update the patterns. Signed-off-by: Joe Perches Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 252972b6c4a0..8c2086f61959 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4136,7 +4136,7 @@ L: linux-ntfs-dev@lists.sourceforge.net W: http://www.linux-ntfs.org/content/view/19/37/ S: Maintained F: Documentation/ldm.txt -F: fs/partitions/ldm.* +F: block/partitions/ldm.* LogFS M: Joern Engel @@ -5633,7 +5633,7 @@ W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported F: arch/s390/ F: drivers/s390/ -F: fs/partitions/ibm.c +F: block/partitions/ibm.c F: Documentation/s390/ F: Documentation/DocBook/s390* From 0960e7d13f5d33e4a8201b6c546ce60a2c6faba4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 3 Feb 2012 15:37:12 -0800 Subject: [PATCH 327/380] MAINTAINERS: remove iMX5 section commit 784a90c0a7d8f5 ("ARM i.MX: Merge i.MX5 support into mach-imx") merged the files, remove the iMX5 section. Signed-off-by: Joe Perches Cc: Amit Kucheria Cc: Sascha Hauer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8c2086f61959..a9fd6ca540f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -789,12 +789,6 @@ F: arch/arm/mach-mx*/ F: arch/arm/mach-imx/ F: arch/arm/plat-mxc/ -ARM/FREESCALE IMX51 -M: Amit Kucheria -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained -F: arch/arm/mach-mx5/ - ARM/FREESCALE IMX6 M: Shawn Guo L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) From cdb7232b29229ecf1cc89764d75074eaee63ce32 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 3 Feb 2012 15:37:12 -0800 Subject: [PATCH 328/380] MAINTAINERS: remove staging sections Two commits moved files from staging to drivers/media/ commit d6ce55de3abcc ("[media] move cx25821 out of staging") commit be30497085080 ("[media] move tm6000 to drivers/media/video") Remove the sections. Signed-off-by: Joe Perches Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 5 ----- 1 file changed, 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a9fd6ca540f2..51767d58706a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6390,11 +6390,6 @@ M: Omar Ramirez Luna S: Odd Fixes F: drivers/staging/tidspbridge/ -STAGING - TRIDENT TVMASTER TMxxxx USB VIDEO CAPTURE DRIVERS -L: linux-media@vger.kernel.org -S: Odd Fixes -F: drivers/staging/tm6000/ - STAGING - USB ENE SM/MS CARD READER DRIVER M: Al Cho S: Odd Fixes From 070f420b35a2c078ca2bd2a0d31dd7b5001d411c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 3 Feb 2012 15:37:13 -0800 Subject: [PATCH 329/380] MAINTAINERS: update lguest F: patterns commit 07fe9977b623 ("lguest: move the lguest tool to the tools directory") moved the files, update the patterns. Sort F: patterns alphabetically too. Signed-off-by: Joe Perches Cc: Davidlohr Bueso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 51767d58706a..8591c03354ef 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3986,11 +3986,11 @@ M: Rusty Russell L: lguest@lists.ozlabs.org W: http://lguest.ozlabs.org/ S: Odd Fixes -F: Documentation/virtual/lguest/ +F: arch/x86/include/asm/lguest*.h F: arch/x86/lguest/ F: drivers/lguest/ F: include/linux/lguest*.h -F: arch/x86/include/asm/lguest*.h +F: tools/lguest/ LINUX FOR IBM pSERIES (RS/6000) M: Paul Mackerras From a1b58c237b73f10221b31e05b47a6565558207ef Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 3 Feb 2012 15:37:13 -0800 Subject: [PATCH 330/380] xtensa: fix memscan() Defining memscan() as memchr() is wrong, because the return values of memscan() and memchr() are different when the character is not found. So use the generic memscan() implementation to fix this. Signed-off-by: Akinobu Mita Cc: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/xtensa/include/asm/string.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h index 5fb8c27cbef5..405a8c49ff2c 100644 --- a/arch/xtensa/include/asm/string.h +++ b/arch/xtensa/include/asm/string.h @@ -118,7 +118,4 @@ extern void *memmove(void *__dest, __const__ void *__src, size_t __n); /* Don't build bcopy at all ... */ #define __HAVE_ARCH_BCOPY -#define __HAVE_ARCH_MEMSCAN -#define memscan memchr - #endif /* _XTENSA_STRING_H */ From 35512ecaef03250fe50ad81430dd467f01d9a96b Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Fri, 3 Feb 2012 15:37:13 -0800 Subject: [PATCH 331/380] mm: postpone migrated page mapping reset Postpone resetting page->mapping until the final remove_migration_ptes(). Otherwise the expression PageAnon(migration_entry_to_page(entry)) does not work. Signed-off-by: Konstantin Khlebnikov Cc: Hugh Dickins Cc: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/migrate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/migrate.c b/mm/migrate.c index 9871a56d82c3..df141f60289e 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -445,7 +445,6 @@ void migrate_page_copy(struct page *newpage, struct page *page) ClearPageSwapCache(page); ClearPagePrivate(page); set_page_private(page, 0); - page->mapping = NULL; /* * If any waiters have accumulated on the new page then @@ -667,6 +666,7 @@ static int move_to_new_page(struct page *newpage, struct page *page, } else { if (remap_swapcache) remove_migration_ptes(page, newpage); + page->mapping = NULL; } unlock_page(newpage); From 31e0017e6f6fb5cfdfaf932c1f98c9bef8d57688 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Fri, 3 Feb 2012 15:37:14 -0800 Subject: [PATCH 332/380] avr32: select generic atomic64_t support Enable use of the generic atomic64 implementation on AVR32 platforms. Without this the kernel fails to build as the architecture does not provide its version. Signed-off-by: Fabio Baltieri Acked-by: Hans-Christian Egtvedt Cc: Haavard Skinnemoen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/avr32/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 197e96f70405..3dea7231f637 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -8,6 +8,7 @@ config AVR32 select HAVE_KPROBES select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE + select GENERIC_ATOMIC64 select HARDIRQS_SW_RESEND select GENERIC_IRQ_SHOW select ARCH_HAVE_NMI_SAFE_CMPXCHG From 82b3f2a7171731cce62f25058d25afb91a14710c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 3 Feb 2012 15:37:14 -0800 Subject: [PATCH 333/380] mm/memcontrol.c: fix warning with CONFIG_NUMA=n mm/memcontrol.c: In function 'memcg_check_events': mm/memcontrol.c:779: warning: unused variable 'do_numainfo' Acked-by: Michal Hocko Cc: Li Zefan Cc: Hiroyuki KAMEZAWA Cc: Johannes Weiner Acked-by: "Kirill A. Shutemov" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 556859fec4ef..6728a7ae6f2d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -776,7 +776,8 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) /* threshold event is triggered in finer grain than soft limit */ if (unlikely(mem_cgroup_event_ratelimit(memcg, MEM_CGROUP_TARGET_THRESH))) { - bool do_softlimit, do_numainfo; + bool do_softlimit; + bool do_numainfo __maybe_unused; do_softlimit = mem_cgroup_event_ratelimit(memcg, MEM_CGROUP_TARGET_SOFTLIMIT); From 99f02ef1f18631eb0a4e0ea0a3d56878dbcb4b90 Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Fri, 3 Feb 2012 15:37:14 -0800 Subject: [PATCH 334/380] mm/filemap_xip.c: fix race condition in xip_file_fault() Fix a race condition that shows in conjunction with xip_file_fault() when two threads of the same user process fault on the same memory page. In this case, the race winner will install the page table entry and the unlucky loser will cause an oops: xip_file_fault calls vm_insert_pfn (via vm_insert_mixed) which drops out at this check: retval = -EBUSY; if (!pte_none(*pte)) goto out_unlock; The resulting -EBUSY return value will trigger a BUG_ON() in xip_file_fault. This fix simply considers the fault as fixed in this case, because the race winner has successfully installed the pte. [akpm@linux-foundation.org: use conventional (and consistent) comment layout] Reported-by: David Sadler Signed-off-by: Carsten Otte Reported-by: Louis Alex Eisner Cc: Hugh Dickins Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/filemap_xip.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index f91b2f687343..a4eb31132229 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c @@ -263,7 +263,12 @@ found: xip_pfn); if (err == -ENOMEM) return VM_FAULT_OOM; - BUG_ON(err); + /* + * err == -EBUSY is fine, we've raced against another thread + * that faulted-in the same page + */ + if (err != -EBUSY) + BUG_ON(err); return VM_FAULT_NOPAGE; } else { int err, ret = VM_FAULT_OOM; From 92618184cb92c5b39d4d8573572d576f9ccb3c28 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Fri, 3 Feb 2012 15:37:15 -0800 Subject: [PATCH 335/380] lkdtm: avoid calling lkdtm_do_action() with spinlock held lkdtm_do_action() may call sleeping functions like kmalloc(), so do not call it with spin lock held. Signed-off-by: WANG Cong Cc: Prarit Bhargava Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Reviewed-by: Dave Young Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/lkdtm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 150cd7061b80..28adefe70f96 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -354,6 +354,7 @@ static void lkdtm_do_action(enum ctype which) static void lkdtm_handler(void) { unsigned long flags; + bool do_it = false; spin_lock_irqsave(&count_lock, flags); count--; @@ -361,10 +362,13 @@ static void lkdtm_handler(void) cp_name_to_str(cpoint), cp_type_to_str(cptype), count); if (count == 0) { - lkdtm_do_action(cptype); + do_it = true; count = cpoint_count; } spin_unlock_irqrestore(&count_lock, flags); + + if (do_it) + lkdtm_do_action(cptype); } static int lkdtm_register_cpoint(enum cname which) From cbcb8346054073d000ecac324763372d6abd44ac Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 3 Feb 2012 15:37:15 -0800 Subject: [PATCH 336/380] drivers/tty/vt/vt_ioctl.c: fix KDFONTOP 32bit compatibility layer KDFONTOP(GET) currently fails with EIO when being run in a 32bit userland with a 64bit kernel if the font width is not 8. This is because of the setting of the KD_FONT_FLAG_OLD flag, which makes con_font_get return EIO in such case. This flag should *not* be set for KDFONTOP, since it's actually the whole point of this flag (see comment in con_font_set for instance). Signed-off-by: Samuel Thibault Reviewed-by: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Arthur Taylor Cc: Jiri Slaby Cc: Jiri Olsa Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/tty/vt/vt_ioctl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 5e096f43bcea..65447c5f91d7 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -1463,7 +1463,6 @@ compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop, if (!perm && op->op != KD_FONT_OP_GET) return -EPERM; op->data = compat_ptr(((struct compat_console_font_op *)op)->data); - op->flags |= KD_FONT_FLAG_OLD; i = con_font_op(vc, op); if (i) return i; From 55ca6140e9bb307efc97a9301a4f501de02a6fd6 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 3 Feb 2012 15:37:16 -0800 Subject: [PATCH 337/380] kprobes: fix a memory leak in function pre_handler_kretprobe() In function pre_handler_kretprobe(), the allocated kretprobe_instance object will get leaked if the entry_handler callback returns non-zero. This may cause all the preallocated kretprobe_instance objects exhausted. This issue can be reproduced by changing samples/kprobes/kretprobe_example.c to probe "mutex_unlock". And the fix is straightforward: just put the allocated kretprobe_instance object back onto the free_instances list. [akpm@linux-foundation.org: use raw_spin_lock/unlock] Signed-off-by: Jiang Liu Acked-by: Jim Keniston Acked-by: Ananth N Mavinakayanahalli Cc: Masami Hiramatsu Cc: Anil S Keshavamurthy Cc: "David S. Miller" Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/kprobes.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 29f5b65bee29..9788c0ec6f43 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1673,8 +1673,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, ri->rp = rp; ri->task = current; - if (rp->entry_handler && rp->entry_handler(ri, regs)) + if (rp->entry_handler && rp->entry_handler(ri, regs)) { + raw_spin_lock_irqsave(&rp->lock, flags); + hlist_add_head(&ri->hlist, &rp->free_instances); + raw_spin_unlock_irqrestore(&rp->lock, flags); return 0; + } arch_prepare_kretprobe(ri, regs); From 3deaa7190a8da38453c4fabd9dec7f66d17fff67 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 3 Feb 2012 15:37:17 -0800 Subject: [PATCH 338/380] readahead: fix pipeline break caused by block plug Herbert Poetzl reported a performance regression since 2.6.39. The test is a simple dd read, but with big block size. The reason is: T1: ra (A, A+128k), (A+128k, A+256k) T2: lock_page for page A, submit the 256k T3: hit page A+128K, ra (A+256k, A+384). the range isn't submitted because of plug and there isn't any lock_page till we hit page A+256k because all pages from A to A+256k is in memory T4: hit page A+256k, ra (A+384, A+ 512). Because of plug, the range isn't submitted again. T5: lock_page A+256k, so (A+256k, A+512k) will be submitted. The task is waitting for (A+256k, A+512k) finish. There is no request to disk in T3 and T4, so readahead pipeline breaks. We really don't need block plug for generic_file_aio_read() for buffered I/O. The readahead already has plug and has fine grained control when I/O should be submitted. Deleting plug for buffered I/O fixes the regression. One side effect is plug makes the request size 256k, the size is 128k without it. This is because default ra size is 128k and not a reason we need plug here. Vivek said: : We submit some readahead IO to device request queue but because of nested : plug, queue never gets unplugged. When read logic reaches a page which is : not in page cache, it waits for page to be read from the disk : (lock_page_killable()) and that time we flush the plug list. : : So effectively read ahead logic is kind of broken in parts because of : nested plugging. Removing top level plug (generic_file_aio_read()) for : buffered reads, will allow unplugging queue earlier for readahead. Signed-off-by: Shaohua Li Signed-off-by: Wu Fengguang Reported-by: Herbert Poetzl Tested-by: Eric Dumazet Cc: Christoph Hellwig Cc: Jens Axboe Cc: Vivek Goyal Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/filemap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index 97f49ed35bd2..b66275757c28 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long seg = 0; size_t count; loff_t *ppos = &iocb->ki_pos; - struct blk_plug plug; count = 0; retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); if (retval) return retval; - blk_start_plug(&plug); - /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ if (filp->f_flags & O_DIRECT) { loff_t size; @@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, retval = filemap_write_and_wait_range(mapping, pos, pos + iov_length(iov, nr_segs) - 1); if (!retval) { + struct blk_plug plug; + + blk_start_plug(&plug); retval = mapping->a_ops->direct_IO(READ, iocb, iov, pos, nr_segs); + blk_finish_plug(&plug); } if (retval > 0) { *ppos = pos + retval; @@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, break; } out: - blk_finish_plug(&plug); return retval; } EXPORT_SYMBOL(generic_file_aio_read); From 0bf380bc70ecba68cb4d74dc656cc2fa8c4d801a Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Fri, 3 Feb 2012 15:37:18 -0800 Subject: [PATCH 339/380] mm: compaction: check pfn_valid when entering a new MAX_ORDER_NR_PAGES block during isolation for migration When isolating for migration, migration starts at the start of a zone which is not necessarily pageblock aligned. Further, it stops isolating when COMPACT_CLUSTER_MAX pages are isolated so migrate_pfn is generally not aligned. This allows isolate_migratepages() to call pfn_to_page() on an invalid PFN which can result in a crash. This was originally reported against a 3.0-based kernel with the following trace in a crash dump. PID: 9902 TASK: d47aecd0 CPU: 0 COMMAND: "memcg_process_s" #0 [d72d3ad0] crash_kexec at c028cfdb #1 [d72d3b24] oops_end at c05c5322 #2 [d72d3b38] __bad_area_nosemaphore at c0227e60 #3 [d72d3bec] bad_area at c0227fb6 #4 [d72d3c00] do_page_fault at c05c72ec #5 [d72d3c80] error_code (via page_fault) at c05c47a4 EAX: 00000000 EBX: 000c0000 ECX: 00000001 EDX: 00000807 EBP: 000c0000 DS: 007b ESI: 00000001 ES: 007b EDI: f3000a80 GS: 6f50 CS: 0060 EIP: c030b15a ERR: ffffffff EFLAGS: 00010002 #6 [d72d3cb4] isolate_migratepages at c030b15a #7 [d72d3d14] zone_watermark_ok at c02d26cb #8 [d72d3d2c] compact_zone at c030b8de #9 [d72d3d68] compact_zone_order at c030bba1 #10 [d72d3db4] try_to_compact_pages at c030bc84 #11 [d72d3ddc] __alloc_pages_direct_compact at c02d61e7 #12 [d72d3e08] __alloc_pages_slowpath at c02d66c7 #13 [d72d3e78] __alloc_pages_nodemask at c02d6a97 #14 [d72d3eb8] alloc_pages_vma at c030a845 #15 [d72d3ed4] do_huge_pmd_anonymous_page at c03178eb #16 [d72d3f00] handle_mm_fault at c02f36c6 #17 [d72d3f30] do_page_fault at c05c70ed #18 [d72d3fb0] error_code (via page_fault) at c05c47a4 EAX: b71ff000 EBX: 00000001 ECX: 00001600 EDX: 00000431 DS: 007b ESI: 08048950 ES: 007b EDI: bfaa3788 SS: 007b ESP: bfaa36e0 EBP: bfaa3828 GS: 6f50 CS: 0073 EIP: 080487c8 ERR: ffffffff EFLAGS: 00010202 It was also reported by Herbert van den Bergh against 3.1-based kernel with the following snippet from the console log. BUG: unable to handle kernel paging request at 01c00008 IP: [] isolate_migratepages+0x119/0x390 *pdpt = 000000002f7ce001 *pde = 0000000000000000 It is expected that it also affects 3.2.x and current mainline. The problem is that pfn_valid is only called on the first PFN being checked and that PFN is not necessarily aligned. Lets say we have a case like this H = MAX_ORDER_NR_PAGES boundary | = pageblock boundary m = cc->migrate_pfn f = cc->free_pfn o = memory hole H------|------H------|----m-Hoooooo|ooooooH-f----|------H The migrate_pfn is just below a memory hole and the free scanner is beyond the hole. When isolate_migratepages started, it scans from migrate_pfn to migrate_pfn+pageblock_nr_pages which is now in a memory hole. It checks pfn_valid() on the first PFN but then scans into the hole where there are not necessarily valid struct pages. This patch ensures that isolate_migratepages calls pfn_valid when necessary. Reported-by: Herbert van den Bergh Tested-by: Herbert van den Bergh Signed-off-by: Mel Gorman Acked-by: Michal Nazarewicz Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mm/compaction.c b/mm/compaction.c index 71a58f67f481..bd939a574b84 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -313,6 +313,19 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, } else if (!locked) spin_lock_irq(&zone->lru_lock); + /* + * migrate_pfn does not necessarily start aligned to a + * pageblock. Ensure that pfn_valid is called when moving + * into a new MAX_ORDER_NR_PAGES range in case of large + * memory holes within the zone + */ + if ((low_pfn & (MAX_ORDER_NR_PAGES - 1)) == 0) { + if (!pfn_valid(low_pfn)) { + low_pfn += MAX_ORDER_NR_PAGES - 1; + continue; + } + } + if (!pfn_valid_within(low_pfn)) continue; nr_scanned++; From 500823195d0c9eec2a4637484f30cc93ec633d4a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 2 Feb 2012 13:54:25 +0200 Subject: [PATCH 340/380] Revert "mtd: atmel_nand: optimize read/write buffer functions" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit fb5427508abbd635e877fabdf55795488119c2d6. The reason is that it breaks 16 bits NAND flash as it was reported by Nikolaus Voss and confirmed by Eric Bénard. Nicolas Ferre alco confirmed: "After double checking with designers, I must admit that I misunderstood the way of optimizing accesses to SMC. 16 bit nand is not so common those days..." Reported-by: Nikolaus Voss Acked-by: Nicolas Ferre Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Cc: stable@kernel.org [3.1+] --- drivers/mtd/nand/atmel_nand.c | 45 +++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 4dd056e2e16a..35b4fb55dbd6 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -161,6 +161,37 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) !!host->board->rdy_pin_active_low; } +/* + * Minimal-overhead PIO for data access. + */ +static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_readsb(nand_chip->IO_ADDR_R, buf, len); +} + +static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); +} + +static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_writesb(nand_chip->IO_ADDR_W, buf, len); +} + +static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); +} + static void dma_complete_func(void *completion) { complete(completion); @@ -235,27 +266,33 @@ err_buf: static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *chip = mtd->priv; + struct atmel_nand_host *host = chip->priv; if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) return; - /* if no DMA operation possible, use PIO */ - memcpy_fromio(buf, chip->IO_ADDR_R, len); + if (host->board->bus_width_16) + atmel_read_buf16(mtd, buf, len); + else + atmel_read_buf8(mtd, buf, len); } static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { struct nand_chip *chip = mtd->priv; + struct atmel_nand_host *host = chip->priv; if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) return; - /* if no DMA operation possible, use PIO */ - memcpy_toio(chip->IO_ADDR_W, buf, len); + if (host->board->bus_width_16) + atmel_write_buf16(mtd, buf, len); + else + atmel_write_buf8(mtd, buf, len); } /* From 379e0be812ab8a2a351e784b0c987788f5123090 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Fri, 3 Feb 2012 22:22:41 +0100 Subject: [PATCH 341/380] PM / Freezer: Thaw only kernel threads if freezing of kernel threads fails If freezing of kernel threads fails, we are expected to automatically thaw tasks in the error recovery path. However, at times, we encounter situations in which we would like the automatic error recovery path to thaw only the kernel threads, because we want to be able to do some more cleanup before we thaw userspace. Something like: error = freeze_kernel_threads(); if (error) { /* Do some cleanup */ /* Only then thaw userspace tasks*/ thaw_processes(); } An example of such a situation is where we freeze/thaw filesystems during suspend/hibernation. There, if freezing of kernel threads fails, we would like to thaw the frozen filesystems before thawing the userspace tasks. So, modify freeze_kernel_threads() to thaw only kernel threads in case of freezing failure. And change suspend_freeze_processes() accordingly. (At the same time, let us also get rid of the rather cryptic usage of the conditional operator (:?) in that function.) [rjw: In fact, this patch fixes a regression introduced during the 3.3 merge window, because without it thaw_processes() may be called before swsusp_free() in some situations and that may lead to massive memory allocation failures.] Signed-off-by: Srivatsa S. Bhat Acked-by: Tejun Heo Acked-by: Nigel Cunningham Signed-off-by: Rafael J. Wysocki --- kernel/power/power.h | 24 ++++++++++++++++++++++-- kernel/power/process.c | 7 +++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/kernel/power/power.h b/kernel/power/power.h index 0c4defe6d3b8..21724eee5206 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -231,8 +231,28 @@ extern int pm_test_level; #ifdef CONFIG_SUSPEND_FREEZER static inline int suspend_freeze_processes(void) { - int error = freeze_processes(); - return error ? : freeze_kernel_threads(); + int error; + + error = freeze_processes(); + + /* + * freeze_processes() automatically thaws every task if freezing + * fails. So we need not do anything extra upon error. + */ + if (error) + goto Finish; + + error = freeze_kernel_threads(); + + /* + * freeze_kernel_threads() thaws only kernel threads upon freezing + * failure. So we have to thaw the userspace tasks ourselves. + */ + if (error) + thaw_processes(); + + Finish: + return error; } static inline void suspend_thaw_processes(void) diff --git a/kernel/power/process.c b/kernel/power/process.c index eeca00311f39..7e426459e60a 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -143,7 +143,10 @@ int freeze_processes(void) /** * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator. * - * On success, returns 0. On failure, -errno and system is fully thawed. + * On success, returns 0. On failure, -errno and only the kernel threads are + * thawed, so as to give a chance to the caller to do additional cleanups + * (if any) before thawing the userspace tasks. So, it is the responsibility + * of the caller to thaw the userspace tasks, when the time is right. */ int freeze_kernel_threads(void) { @@ -159,7 +162,7 @@ int freeze_kernel_threads(void) BUG_ON(in_atomic()); if (error) - thaw_processes(); + thaw_kernel_threads(); return error; } From d020283dc694c9ec31b410f522252f7a8397e67d Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Fri, 3 Feb 2012 22:22:25 +0100 Subject: [PATCH 342/380] PM / QoS: CPU C-state breakage with PM Qos change Looks like change "PM QoS: Move and rename the implementation files" merged during the 3.2 development cycle made PM QoS depend on CONFIG_PM which depends on (PM_SLEEP || PM_RUNTIME). That breaks CPU C-states with kernels not having these CONFIGs, causing CPUs to spend time in Polling loop idle instead of going into deep C-states, consuming way way more power. This is with either acpi idle or intel idle enabled. Either CONFIG_PM should be enabled with any pm_qos users or the !CONFIG_PM pm_qos_request() should return sane defaults not to break the existing users. Here's is the patch for the latter option. [rjw: Modified the changelog slightly.] Signed-off-by: Venkatesh Pallipadi Signed-off-by: Rafael J. Wysocki Cc: stable@vger.kernel.org --- include/linux/pm_qos.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index e5bbcbaa6f57..4d99e4e6ef83 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -110,7 +110,19 @@ static inline void pm_qos_remove_request(struct pm_qos_request *req) { return; } static inline int pm_qos_request(int pm_qos_class) - { return 0; } +{ + switch (pm_qos_class) { + case PM_QOS_CPU_DMA_LATENCY: + return PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; + case PM_QOS_NETWORK_LATENCY: + return PM_QOS_NETWORK_LAT_DEFAULT_VALUE; + case PM_QOS_NETWORK_THROUGHPUT: + return PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE; + default: + return PM_QOS_DEFAULT_VALUE; + } +} + static inline int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier) { return 0; } From 585c0fd8216e0c9f98e2434092af7ec0f999522d Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 27 Jan 2012 05:43:59 -0800 Subject: [PATCH 343/380] hwmon: (w83627ehf) Fix number of fans for NCT6776F NCT6776F can select fan input pins for fans 3 to 5 with a secondary set of chip register bits. Check that second set of bits in addition to the first set to detect if fans 3..5 are monitored. Signed-off-by: Guenter Roeck Cc: stable@vger.kernel.org # 3.0+ Acked-by: Jean Delvare --- drivers/hwmon/w83627ehf.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 2dfae7d7cc5b..4d383e7e051d 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -1920,9 +1920,26 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data, fan4min = 0; fan5pin = 0; } else if (sio_data->kind == nct6776) { - fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40); - fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01); - fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02); + bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80; + + superio_select(sio_data->sioreg, W83627EHF_LD_HWM); + regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE); + + if (regval & 0x80) + fan3pin = gpok; + else + fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40); + + if (regval & 0x40) + fan4pin = gpok; + else + fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01); + + if (regval & 0x20) + fan5pin = gpok; + else + fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02); + fan4min = fan4pin; } else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { fan3pin = 1; From b1a4874e0d03cb65a1bde950d8f5f2d8743f66ed Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 25 Jan 2012 17:20:59 +0100 Subject: [PATCH 344/380] spi: Add spi-s3c64xx driver dependency on ARCH_EXYNOS4 The spi-s3c64xx driver is also used on Exynos4 so update the dependency to enable build on those platforms. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park [grant.likely: relax depends to ARCH_EXYNOS instead of ARCH_EXYNOS4] Signed-off-by: Grant Likely --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3f9a47ec67dc..8293658e7cf9 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -299,7 +299,7 @@ config SPI_S3C24XX_FIQ config SPI_S3C64XX tristate "Samsung S3C64XX series type SPI" - depends on (ARCH_S3C64XX || ARCH_S5P64X0) + depends on (ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS) select S3C64XX_DMA if ARCH_S3C64XX help SPI driver for Samsung S3C64XX and newer SoCs. From c88db233251b026fda775428f0250c760553e216 Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Thu, 2 Feb 2012 14:20:30 +0100 Subject: [PATCH 345/380] spi-topcliff-pch: rename pch_spi_pcidev to pch_spi_pcidev_driver Rename static struct pci_driver pch_spi_pcidev to pch_spi_pcidev_driver to get rid of warnings from modpost checks. Signed-off-by: Danny Kukawka Signed-off-by: Grant Likely --- drivers/spi/spi-topcliff-pch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 2a6429d8c363..10182eb50068 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1720,7 +1720,7 @@ static int pch_spi_resume(struct pci_dev *pdev) #endif -static struct pci_driver pch_spi_pcidev = { +static struct pci_driver pch_spi_pcidev_driver = { .name = "pch_spi", .id_table = pch_spi_pcidev_id, .probe = pch_spi_probe, @@ -1736,7 +1736,7 @@ static int __init pch_spi_init(void) if (ret) return ret; - ret = pci_register_driver(&pch_spi_pcidev); + ret = pci_register_driver(&pch_spi_pcidev_driver); if (ret) return ret; @@ -1746,7 +1746,7 @@ module_init(pch_spi_init); static void __exit pch_spi_exit(void) { - pci_unregister_driver(&pch_spi_pcidev); + pci_unregister_driver(&pch_spi_pcidev_driver); platform_driver_unregister(&pch_spi_pd_driver); } module_exit(pch_spi_exit); From 226e01ef0da0b1a4c2c3922fb83ff3f9e4dfb508 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 5 Feb 2012 01:27:44 +0100 Subject: [PATCH 346/380] ALSA: emu8000: Remove duplicate linux/moduleparam.h include from emu8000_patch.c The header 'linux/moduleparam.h' is included twice in 'sound/isa/sb/emu8000_patch.c'. Once is enough. Signed-off-by: Jesper Juhl Signed-off-by: Takashi Iwai --- sound/isa/sb/emu8000_patch.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index e09f144177f5..c99c6078be33 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c @@ -22,7 +22,6 @@ #include "emu8000_local.h" #include #include -#include static int emu8000_reset_addr; module_param(emu8000_reset_addr, int, 0444); From eedec3d3854a390fc14008f265930f8c22b0373f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 6 Feb 2012 10:24:04 +0100 Subject: [PATCH 347/380] ALSA: hda/realtek - Fix a wrong condition sparse complains that "spec->multiout.dac_nids" is a pointer. sound/pci/hda/patch_realtek.c:2321:37: error: incompatible types for operation (>) sound/pci/hda/patch_realtek.c:2321:37: left side has type unsigned short const [usertype] *dac_nids sound/pci/hda/patch_realtek.c:2321:37: right side has type int It was meant to be num_dacs instead of dac_nids. Although the current code still works as expected (when num_dacs is zero, dac_nids should be NULL, too), better to fix now, of course. Reported-by: Dan Carpenter Cc: David Henningsson Signed-off-by: Takashi Iwai --- 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 33b6077fcdb8..485a83746e5a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2322,7 +2322,7 @@ static int alc_build_pcms(struct hda_codec *codec) "%s Analog", codec->chip_name); info->name = spec->stream_name_analog; - if (spec->multiout.dac_nids > 0) { + if (spec->multiout.num_dacs > 0) { p = spec->stream_analog_playback; if (!p) p = &alc_pcm_analog_playback; From db966f8abb9ba74f7d5a7230f51572f52c31c4e5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 6 Feb 2012 12:07:08 +0000 Subject: [PATCH 348/380] ASoC: wm8994: Enabling VMID should take a runtime PM reference We can enable VMID independently of the bias in some use cases so we need to ensure that the core device is powered up. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8994.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 8623950d55f8..81795ebcab17 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -770,6 +770,8 @@ static void vmid_reference(struct snd_soc_codec *codec) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + pm_runtime_get_sync(codec->dev); + wm8994->vmid_refcount++; dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n", @@ -837,6 +839,8 @@ static void vmid_dereference(struct snd_soc_codec *codec) WM8994_VMID_BUF_ENA | WM8994_VMID_RAMP_MASK, 0); } + + pm_runtime_put(codec->dev); } static int vmid_event(struct snd_soc_dapm_widget *w, From d7cb3dbd10c09081fafd05fcbef590ce04e402ff Mon Sep 17 00:00:00 2001 From: Przemo Firszt Date: Sun, 5 Feb 2012 22:35:24 +0000 Subject: [PATCH 349/380] HID: wacom: Fix invalid power_supply_powers calls power_supply_powers calls added in 35b4c01e2 ("power_supply: add "powers" links to self-powered HID devices") have to be called after power device is created. This patch also fixes the second call - it has to be "ac" instead of "battery" Signed-off-by: Przemo Firszt Signed-off-by: Chris Bagwell Signed-off-by: Jiri Kosina --- drivers/hid/hid-wacom.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index b47e58b52d9f..acab74cde727 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -531,7 +531,6 @@ static int wacom_probe(struct hid_device *hdev, wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; wdata->battery.use_for_apm = 0; - power_supply_powers(&wdata->battery, &hdev->dev); ret = power_supply_register(&hdev->dev, &wdata->battery); if (ret) { @@ -540,6 +539,8 @@ static int wacom_probe(struct hid_device *hdev, goto err_battery; } + power_supply_powers(&wdata->battery, &hdev->dev); + wdata->ac.properties = wacom_ac_props; wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props); wdata->ac.get_property = wacom_ac_get_property; @@ -547,14 +548,14 @@ static int wacom_probe(struct hid_device *hdev, wdata->ac.type = POWER_SUPPLY_TYPE_MAINS; wdata->ac.use_for_apm = 0; - power_supply_powers(&wdata->battery, &hdev->dev); - ret = power_supply_register(&hdev->dev, &wdata->ac); if (ret) { hid_warn(hdev, "can't create ac battery attribute, err: %d\n", ret); goto err_ac; } + + power_supply_powers(&wdata->ac, &hdev->dev); #endif return 0; From 715252d41912941efb791a7b7bad94d2614dc5c3 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 4 Feb 2012 23:49:40 +0100 Subject: [PATCH 350/380] IB/srpt: Don't return freed pointer from srpt_alloc_ioctx_ring() Signed-off-by: Jesper Juhl Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srpt/ib_srpt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index c125614ac256..2b73d43cd691 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -687,6 +687,7 @@ err: while (--i >= 0) srpt_free_ioctx(sdev, ring[i], dma_size, dir); kfree(ring); + ring = NULL; out: return ring; } From 96e02d1586782eadf051fa3d6bc4132d2447ac2c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Sat, 4 Feb 2012 10:47:10 +0100 Subject: [PATCH 351/380] exec: fix use-after-free bug in setup_new_exec() Setting the task name is done within setup_new_exec() by accessing bprm->filename. However this happens after flush_old_exec(). This may result in a use after free bug, flush_old_exec() may "complete" vfork_done, which will wake up the parent which in turn may free the passed in filename. To fix this add a new tcomm field in struct linux_binprm which contains the now early generated task name until it is used. Fixes this bug on s390: Unable to handle kernel pointer dereference at virtual kernel address 0000000039768000 Process kworker/u:3 (pid: 245, task: 000000003a3dc840, ksp: 0000000039453818) Krnl PSW : 0704000180000000 0000000000282e94 (setup_new_exec+0xa0/0x374) Call Trace: ([<0000000000282e2c>] setup_new_exec+0x38/0x374) [<00000000002dd12e>] load_elf_binary+0x402/0x1bf4 [<0000000000280a42>] search_binary_handler+0x38e/0x5bc [<0000000000282b6c>] do_execve_common+0x410/0x514 [<0000000000282cb6>] do_execve+0x46/0x58 [<00000000005bce58>] kernel_execve+0x28/0x70 [<000000000014ba2e>] ____call_usermodehelper+0x102/0x140 [<00000000005bc8da>] kernel_thread_starter+0x6/0xc [<00000000005bc8d4>] kernel_thread_starter+0x0/0xc Last Breaking-Event-Address: [<00000000002830f0>] setup_new_exec+0x2fc/0x374 Kernel panic - not syncing: Fatal exception: panic_on_oops Reported-by: Sebastian Ott Signed-off-by: Heiko Carstens Signed-off-by: Linus Torvalds --- fs/exec.c | 33 +++++++++++++++++---------------- include/linux/binfmts.h | 3 ++- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index aeb135c7ff5c..92ce83a11e90 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1071,6 +1071,21 @@ void set_task_comm(struct task_struct *tsk, char *buf) perf_event_comm(tsk); } +static void filename_to_taskname(char *tcomm, const char *fn, unsigned int len) +{ + int i, ch; + + /* Copies the binary name from after last slash */ + for (i = 0; (ch = *(fn++)) != '\0';) { + if (ch == '/') + i = 0; /* overwrite what we wrote */ + else + if (i < len - 1) + tcomm[i++] = ch; + } + tcomm[i] = '\0'; +} + int flush_old_exec(struct linux_binprm * bprm) { int retval; @@ -1085,6 +1100,7 @@ int flush_old_exec(struct linux_binprm * bprm) set_mm_exe_file(bprm->mm, bprm->file); + filename_to_taskname(bprm->tcomm, bprm->filename, sizeof(bprm->tcomm)); /* * Release all of the old mmap stuff */ @@ -1116,10 +1132,6 @@ EXPORT_SYMBOL(would_dump); void setup_new_exec(struct linux_binprm * bprm) { - int i, ch; - const char *name; - char tcomm[sizeof(current->comm)]; - arch_pick_mmap_layout(current->mm); /* This is the point of no return */ @@ -1130,18 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm) else set_dumpable(current->mm, suid_dumpable); - name = bprm->filename; - - /* Copies the binary name from after last slash */ - for (i=0; (ch = *(name++)) != '\0';) { - if (ch == '/') - i = 0; /* overwrite what we wrote */ - else - if (i < (sizeof(tcomm) - 1)) - tcomm[i++] = ch; - } - tcomm[i] = '\0'; - set_task_comm(current, tcomm); + set_task_comm(current, bprm->tcomm); /* 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 diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index fd88a3945aa1..0092102db2de 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -18,7 +18,7 @@ struct pt_regs; #define BINPRM_BUF_SIZE 128 #ifdef __KERNEL__ -#include +#include #define CORENAME_MAX_SIZE 128 @@ -58,6 +58,7 @@ struct linux_binprm { unsigned interp_flags; unsigned interp_data; unsigned long loader, exec; + char tcomm[TASK_COMM_LEN]; }; #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0 From f5fe184b08daf0c34b0de0d02c7033fe119dbf0a Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 6 Feb 2012 09:49:50 -0800 Subject: [PATCH 352/380] Documentation: add missing tainted bits to Documentation/sysctl/kernel.txt Two of the bits in the tainted flag are not documented. Signed-off-by: Larry Finger Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/sysctl/kernel.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 8c20fbd8b42d..6d78841fd416 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -601,6 +601,8 @@ can be ORed together: instead of using the one provided by the hardware. 512 - A kernel warning has occurred. 1024 - A module from drivers/staging was loaded. +2048 - The system is working around a severe firmware bug. +4096 - An out-of-tree module has been loaded. ============================================================== From 71ea4efe4fc3319ab577be00d1bbcb76d3ffaf63 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 6 Feb 2012 09:50:00 -0800 Subject: [PATCH 353/380] Documentation: update quilt tree location for Documentation patches Update quilt tree location for Documentation/ patches. Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8591c03354ef..55ca0bea142c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2281,7 +2281,7 @@ F: drivers/acpi/dock.c DOCUMENTATION M: Randy Dunlap L: linux-doc@vger.kernel.org -T: quilt http://userweb.kernel.org/~rdunlap/kernel-doc-patches/current/ +T: quilt http://xenotime.net/kernel-doc-patches/current/ S: Maintained F: Documentation/ From db91ff55bdf06736b849afc1b1fce5763bbb8d5d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 7 Feb 2012 12:01:51 +1100 Subject: [PATCH 354/380] md: two small fixes to handling interrupt resync. 1/ If a resync is aborted we should record how far we got (recovery_cp) the last request that we know has completed (->curr_resync_completed) rather than the last request that was submitted (->curr_resync). 2/ When a resync aborts we still want to update the metadata with any changes, so set MD_CHANGE_DEVS even if we 'skip'. Signed-off-by: NeilBrown --- drivers/md/md.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 33aa06f12b87..81d1c43dd97f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7333,7 +7333,8 @@ void md_do_sync(struct mddev *mddev) printk(KERN_INFO "md: checkpointing %s of %s.\n", desc, mdname(mddev)); - mddev->recovery_cp = mddev->curr_resync; + mddev->recovery_cp = + mddev->curr_resync_completed; } } else mddev->recovery_cp = MaxSector; @@ -7351,9 +7352,9 @@ void md_do_sync(struct mddev *mddev) rcu_read_unlock(); } } + skip: set_bit(MD_CHANGE_DEVS, &mddev->flags); - skip: if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { /* We completed so min/max setting can be forgotten if used. */ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) From 95fe1ee41e23fa271416da67483594dde74bc6ca Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 18 Jan 2012 14:04:29 +0100 Subject: [PATCH 355/380] target: accept REQUEST_SENSE with 18bytes WindowsXP+BOT issues a MODE_SENSE request with page 0x1c which is not suppoerted by target. Target rejects that command with TCM_INVALID_CDB_FIELD, so far so good. On BOT I can't send the SENSE response back, instead I can only reply that an error occured. The next thing happens is a REQUEST_SENSE request with 18 bytes length. Since the check here is more than 18 bytes I have to NACK that request as well. This is not really required: We check for some additional room, but we never use it. The additional length is set to 0xa so the total length is 0xa + 8 = 18 which is fine with my 18 bytes. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_cdb.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index a9bbf5a5cc27..f3d71fa88a28 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -1058,11 +1058,8 @@ int target_emulate_request_sense(struct se_task *task) */ buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; - /* - * Make sure request data length is enough for additional - * sense data. - */ - if (cmd->data_length <= 18) { + + if (cmd->data_length < 18) { buf[7] = 0x00; err = -EINVAL; goto end; @@ -1079,11 +1076,8 @@ int target_emulate_request_sense(struct se_task *task) */ buf[0] = 0x70; buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; - /* - * Make sure request data length is enough for additional - * sense data. - */ - if (cmd->data_length <= 18) { + + if (cmd->data_length < 18) { buf[7] = 0x00; err = -EINVAL; goto end; From 1edcdb497ef418122cd4f98e157660cf594b345a Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 19 Jan 2012 13:39:23 -0800 Subject: [PATCH 356/380] target: Change target_submit_cmd() to return void Retval not very useful, and may even be harmful. Once submitted, fabrics should expect a sense error if anything goes wrong. All fabrics checking of this retval are useless or broken: fc checks it just to emit more debug output. ib_srpt trickles retval up, then it is ignored. qla2xxx trickles it up, which then causes a bug because the abort goto in qla_target.c thinks cmd hasn't been sent to target. Just returning nothing is best. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 5 ++--- drivers/target/tcm_fc/tfc_cmd.c | 9 ++------- include/target/target_core_fabric.h | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index cf996d81cfcb..aace7ee141f3 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1657,7 +1657,7 @@ EXPORT_SYMBOL(transport_handle_cdb_direct); * This may only be called from process context, and also currently * assumes internal allocation of fabric payload buffer by target-core. **/ -int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, +void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, unsigned char *cdb, unsigned char *sense, u32 unpacked_lun, u32 data_length, int task_attr, int data_dir, int flags) { @@ -1706,12 +1706,11 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, * when fabric has filled the incoming buffer. */ transport_handle_cdb_direct(se_cmd); - return 0; + return; out_check_cond: transport_send_check_condition_and_sense(se_cmd, se_cmd->scsi_sense_reason, 0); - return 0; } EXPORT_SYMBOL(target_submit_cmd); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index addc18f727ea..9e7e26c74c79 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -540,7 +540,6 @@ static void ft_send_work(struct work_struct *work) int data_dir = 0; u32 data_len; int task_attr; - int ret; fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp)); if (!fcp) @@ -603,14 +602,10 @@ static void ft_send_work(struct work_struct *work) * Use a single se_cmd->cmd_kref as we expect to release se_cmd * directly from ft_check_stop_free callback in response path. */ - ret = target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb, + target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb, &cmd->ft_sense_buffer[0], cmd->lun, data_len, task_attr, data_dir, 0); - pr_debug("r_ctl %x alloc target_submit_cmd %d\n", fh->fh_r_ctl, ret); - if (ret < 0) { - ft_dump_cmd(cmd, __func__); - return; - } + pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl); return; err: diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 523e8bc104d4..d36fad317e78 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -114,7 +114,7 @@ void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *, struct se_session *, u32, int, int, unsigned char *); int transport_lookup_cmd_lun(struct se_cmd *, u32); int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *); -int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, +void target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, unsigned char *, u32, u32, int, int, int); int transport_handle_cdb_direct(struct se_cmd *); int transport_generic_handle_cdb_map(struct se_cmd *); From 735703cac08f34a197e1c6331ca9adc8a52d6046 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 20 Jan 2012 19:02:56 -0800 Subject: [PATCH 357/380] target: Fix target_submit_cmd() exception handling This patch fixes a bug in target_submit_cmd() where the failure path for transport_generic_allocate_tasks() made a direct call to transport_send_check_condition_and_sense() and not calling the final target_put_sess_cmd() release callback. For transport_generic_allocate_tasks() failures, use the proper call to transport_generic_request_failure() to handle kref_put() along with potential internal queue full response processing. It also makes transport_lookup_cmd_lun() failures in target_submit_cmd() use transport_send_check_condition_and_sense() and target_put_sess_cmd() directly to avoid se_cmd->se_dev reference in transport_generic_request_failure() handling. Finally it drops the out_check_cond: label and use direct reference for allocate task failures, and per-se_device queue_full handling is currently not supported for transport_lookup_cmd_lun() failure descriptors due to se_device dependency. Reported-by: Roland Dreier Cc: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index aace7ee141f3..799b5efcd382 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1690,15 +1690,21 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, /* * Locate se_lun pointer and attach it to struct se_cmd */ - if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) - goto out_check_cond; + if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) { + transport_send_check_condition_and_sense(se_cmd, + se_cmd->scsi_sense_reason, 0); + target_put_sess_cmd(se_sess, se_cmd); + return; + } /* * Sanitize CDBs via transport_generic_cmd_sequencer() and * allocate the necessary tasks to complete the received CDB+data */ rc = transport_generic_allocate_tasks(se_cmd, cdb); - if (rc != 0) - goto out_check_cond; + if (rc != 0) { + transport_generic_request_failure(se_cmd); + return; + } /* * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend * for immediate execution of READs, otherwise wait for @@ -1707,10 +1713,6 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, */ transport_handle_cdb_direct(se_cmd); return; - -out_check_cond: - transport_send_check_condition_and_sense(se_cmd, - se_cmd->scsi_sense_reason, 0); } EXPORT_SYMBOL(target_submit_cmd); From 7347b5ff7090b2b399b7921a266255cd55bbd78f Mon Sep 17 00:00:00 2001 From: Marco Sanvido Date: Fri, 20 Jan 2012 15:49:27 -0800 Subject: [PATCH 358/380] target: Fix iblock se_dev_attrib.unmap_granularity The block layer keeps q->limits.discard_granularity in bytes, but iblock (and the SCSI Block Limits VPD page) keep unmap_granularity in blocks. Report the correct value when exporting block devices by dividing to convert bytes to blocks. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_iblock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 628e877381d8..d43d5eb5ed20 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -181,7 +181,7 @@ static struct se_device *iblock_create_virtdevice( */ dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1; dev->se_sub_dev->se_dev_attrib.unmap_granularity = - q->limits.discard_granularity; + q->limits.discard_granularity >> 9; dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = q->limits.discard_alignment; From c3bc93da24c8f315d9ece741f6e6414a38879ec6 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 23 Jan 2012 11:39:49 +1100 Subject: [PATCH 359/380] iscsi_target: in_aton needs linux/inet.h Fixes this error after a recent nfs cleanup: drivers/target/iscsi/iscsi_target_configfs.c: In function 'lio_target_call_addnptotpg': drivers/target/iscsi/iscsi_target_configfs.c:214:3: error: implicit declaration of function 'in6_pton' [-Werror=implicit-function-declaration] drivers/target/iscsi/iscsi_target_configfs.c:239:3: error: implicit declaration of function 'in_aton' [-Werror=implicit-function-declaration] Signed-off-by: Stephen Rothwell Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 3468caab47a2..6b35b37988ed 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include From 3011684c0b0b77b0f88113ef1c15b18befc6734a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 27 Jan 2012 15:50:55 +0300 Subject: [PATCH 360/380] target: handle empty string writes in sysfs These are root only and we're not likely to hit the problem in practise, but it makes the static checkers happy. Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 0955bb8979fb..6e043eeb1db9 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -1704,13 +1704,15 @@ static ssize_t target_core_store_dev_alias( return -EINVAL; } - se_dev->su_dev_flags |= SDF_USING_ALIAS; read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN, "%s", page); - + if (!read_bytes) + return -EINVAL; if (se_dev->se_dev_alias[read_bytes - 1] == '\n') se_dev->se_dev_alias[read_bytes - 1] = '\0'; + se_dev->su_dev_flags |= SDF_USING_ALIAS; + pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n", config_item_name(&hba->hba_group.cg_item), config_item_name(&se_dev->se_dev_group.cg_item), @@ -1753,13 +1755,15 @@ static ssize_t target_core_store_dev_udev_path( return -EINVAL; } - se_dev->su_dev_flags |= SDF_USING_UDEV_PATH; read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN, "%s", page); - + if (!read_bytes) + return -EINVAL; if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n') se_dev->se_dev_udev_path[read_bytes - 1] = '\0'; + se_dev->su_dev_flags |= SDF_USING_UDEV_PATH; + pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n", config_item_name(&hba->hba_group.cg_item), config_item_name(&se_dev->se_dev_group.cg_item), From 5c55125f4794f4e77574fc09839cb47b0eb45b06 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 2 Feb 2012 16:51:24 -0500 Subject: [PATCH 361/380] iblock: fix handling of large requests Requesting to many bvecs upsets bio_alloc_bioset, so limit the number we ask for to the amount it can handle. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_iblock.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index d43d5eb5ed20..8572eae62da7 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -488,6 +488,13 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num) struct iblock_req *ib_req = IBLOCK_REQ(task); struct bio *bio; + /* + * Only allocate as many vector entries as the bio code allows us to, + * we'll loop later on until we have handled the whole request. + */ + if (sg_num > BIO_MAX_PAGES) + sg_num = BIO_MAX_PAGES; + bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set); if (!bio) { pr_err("Unable to allocate memory for bio\n"); From 9f9ef6d3c08319defc29e4cf6ef2868d15ed0cc3 Mon Sep 17 00:00:00 2001 From: Dax Kelson Date: Fri, 3 Feb 2012 23:40:25 -0700 Subject: [PATCH 362/380] iscsi: use IP_FREEBIND socket option Use IP_FREEBIND socket option so that iscsi portal configuration with explicit IP addresses can happen during boot, before network interfaces have been assigned IPs. This is especially important on systemd based Linux boxes where system boot happens asynchronously and non-trivial configuration must be done to get targetcli.service to start synchronously after the network is configured. Reference: http://lists.fedoraproject.org/pipermail/devel/2011-October/158025.html Signed-off-by: Dax Kelson Cc: "Nicholas A. Bellinger" Cc: "Andy Grover" Cc: "Lennart Poettering" Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_login.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index ec47a7c5966e..38cb7ce8469e 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -842,6 +842,14 @@ int iscsi_target_setup_login_socket( goto fail; } + ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND, + (char *)&opt, sizeof(opt)); + if (ret < 0) { + pr_err("kernel_setsockopt() for IP_FREEBIND" + " failed\n"); + goto fail; + } + ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len); if (ret < 0) { pr_err("kernel_bind() failed: %d\n", ret); From 67236c44741e250199ccd77f1115568e68cf8848 Mon Sep 17 00:00:00 2001 From: Martin Svec Date: Mon, 6 Feb 2012 22:13:25 -0800 Subject: [PATCH 363/380] target: Fix unsupported WRITE_SAME sense payload This patch fixes a bug in target-core where unsupported WRITE_SAME ops from a target_check_write_same_discard() failure was incorrectly returning CHECK_CONDITION w/ TCM_INVALID_CDB_FIELD sense data. This was causing some clients to not properly fall back, so go ahead and use the correct TCM_UNSUPPORTED_SCSI_OPCODE sense for this case. Reported-by: Martin Svec Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 799b5efcd382..58cea07b12fb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2697,7 +2697,7 @@ static int transport_generic_cmd_sequencer( cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (target_check_write_same_discard(&cdb[10], dev) < 0) - goto out_invalid_cdb_field; + goto out_unsupported_cdb; if (!passthrough) cmd->execute_task = target_emulate_write_same; break; @@ -2980,7 +2980,7 @@ static int transport_generic_cmd_sequencer( cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; if (target_check_write_same_discard(&cdb[1], dev) < 0) - goto out_invalid_cdb_field; + goto out_unsupported_cdb; if (!passthrough) cmd->execute_task = target_emulate_write_same; break; @@ -3003,7 +3003,7 @@ static int transport_generic_cmd_sequencer( * of byte 1 bit 3 UNMAP instead of original reserved field */ if (target_check_write_same_discard(&cdb[1], dev) < 0) - goto out_invalid_cdb_field; + goto out_unsupported_cdb; if (!passthrough) cmd->execute_task = target_emulate_write_same; break; From b97f6bfdd1af95681de5a9f652da644a6525e376 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 Feb 2012 11:00:53 +0100 Subject: [PATCH 364/380] ALSA: hda - Fix error handling in patch_ca0132.c In patch_ca0132.c, the error returned from chipio_write() isn't checked always. Also, the power-up/down sequence isn't tracked properly in some error paths. Reported-by: Dan Carpenter Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 35abe3c62908..21d91d580da8 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -728,18 +728,19 @@ static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol, err = chipio_read(codec, REG_CODEC_MUTE, &data); if (err < 0) - return err; + goto exit; /* *valp 0 is mute, 1 is unmute */ data = (data & 0x7f) | (*valp ? 0 : 0x80); - chipio_write(codec, REG_CODEC_MUTE, data); + err = chipio_write(codec, REG_CODEC_MUTE, data); if (err < 0) - return err; + goto exit; spec->curr_hp_switch = *valp; + exit: snd_hda_power_down(codec); - return 1; + return err < 0 ? err : 1; } static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol, @@ -770,18 +771,19 @@ static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol, err = chipio_read(codec, REG_CODEC_MUTE, &data); if (err < 0) - return err; + goto exit; /* *valp 0 is mute, 1 is unmute */ data = (data & 0xef) | (*valp ? 0 : 0x10); - chipio_write(codec, REG_CODEC_MUTE, data); + err = chipio_write(codec, REG_CODEC_MUTE, data); if (err < 0) - return err; + goto exit; spec->curr_speaker_switch = *valp; + exit: snd_hda_power_down(codec); - return 1; + return err < 0 ? err : 1; } static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol, @@ -819,25 +821,26 @@ static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol, err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data); if (err < 0) - return err; + goto exit; val = 31 - left_vol; data = (data & 0xe0) | val; - chipio_write(codec, REG_CODEC_HP_VOL_L, data); + err = chipio_write(codec, REG_CODEC_HP_VOL_L, data); if (err < 0) - return err; + goto exit; val = 31 - right_vol; data = (data & 0xe0) | val; - chipio_write(codec, REG_CODEC_HP_VOL_R, data); + err = chipio_write(codec, REG_CODEC_HP_VOL_R, data); if (err < 0) - return err; + goto exit; spec->curr_hp_volume[0] = left_vol; spec->curr_hp_volume[1] = right_vol; + exit: snd_hda_power_down(codec); - return 1; + return err < 0 ? err : 1; } static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid) @@ -936,6 +939,8 @@ static int ca0132_build_controls(struct hda_codec *codec) if (err < 0) return err; err = add_in_volume(codec, spec->dig_in, "IEC958"); + if (err < 0) + return err; } return 0; } From 217c8b2b1978aa4a02ce040a99c59ed3b6418fe5 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 7 Feb 2012 13:40:56 +0100 Subject: [PATCH 365/380] HID: wiimote: fix invalid power_supply_powers call Analogically to d7cb3dbd1 ("HID: wacom: Fix invalid power_supply_powers calls"), fix also the same occurence in wiimote driver. Reported-by: przemo@firszt.eu Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index fc253b472f9d..cac3589b1ed5 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -1226,14 +1226,14 @@ static int wiimote_hid_probe(struct hid_device *hdev, wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; wdata->battery.use_for_apm = 0; - power_supply_powers(&wdata->battery, &hdev->dev); - ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); if (ret) { hid_err(hdev, "Cannot register battery device\n"); goto err_battery; } + power_supply_powers(&wdata->battery, &hdev->dev); + ret = wiimote_leds_create(wdata); if (ret) goto err_free; From 416846d2b31fc740ed9d5a5ec116964fb43c4358 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 7 Feb 2012 14:18:14 +0100 Subject: [PATCH 366/380] ALSA: hda - add support for Uniwill ECS M31EI notebook This hardware requires same fixup for the node 0x0f like Asus A6Rp. More information: https://bugzilla.redhat.com/show_bug.cgi?id=785417 Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 485a83746e5a..9350f3c3bdf8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5627,6 +5627,7 @@ static const struct alc_fixup alc861_fixups[] = { static const struct snd_pci_quirk alc861_fixup_tbl[] = { SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP), + SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP), SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP), SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505), {} From 59c1204d464075fcb5d02e7daa6b23782dd4a088 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 7 Feb 2012 08:20:37 -0800 Subject: [PATCH 367/380] ACPI: remove duplicated lines of merging problems with acpi_processor_add Those lines have two copies. Signed-off-by: Yinghai Lu Cc: Thomas Renninger Signed-off-by: Linus Torvalds --- drivers/acpi/processor_driver.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 2b805d7ef317..8ae05ce18500 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -579,13 +579,6 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) goto err_free_cpumask; } - /* - * Do not start hotplugged CPUs now, but when they - * are onlined the first time - */ - if (pr->flags.need_hotplug_init) - return 0; - /* * Do not start hotplugged CPUs now, but when they * are onlined the first time From 8eef05dd3e70233f3e391774d612dab44c3f023b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 3 Feb 2012 15:20:39 -0800 Subject: [PATCH 368/380] checkpatch: Warn on code with 6+ tab indentation Overly indented code should be refactored. Suggest refactoring excessive indentation of of if/else/for/do/while/switch statements. For example: $ cat t.c #include #include int main(int argc, char **argv) { if (1) if (2) if (3) if (4) if (5) if (6) if (7) if (8) ; return 0; } $ ./scripts/checkpatch.pl -f t.c WARNING: Too many leading tabs - consider code refactoring #12: FILE: t.c:12: + if (6) WARNING: Too many leading tabs - consider code refactoring #13: FILE: t.c:13: + if (7) WARNING: Too many leading tabs - consider code refactoring #14: FILE: t.c:14: + if (8) total: 0 errors, 3 warnings, 17 lines checked t.c has style problems, please review. If any of these errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. Signed-off-by: Joe Perches Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e3bfcbe8a520..a3b9782441f9 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1924,6 +1924,12 @@ sub process { my $pre_ctx = "$1$2"; my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); + + if ($line =~ /^\+\t{6,}/) { + WARN("DEEP_INDENTATION", + "Too many leading tabs - consider code refactoring\n" . $herecurr); + } + my $ctx_cnt = $realcnt - $#ctx - 1; my $ctx = join("\n", @ctx); From 927c9423dd5f2d1c0b93d5e694ab84b4a5559713 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sat, 4 Feb 2012 20:51:43 +0100 Subject: [PATCH 369/380] ALSA: usb-audio: add Edirol UM-3G support Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 8edc5035fc8f..d89ab4c7d44b 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -1617,6 +1617,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + /* Edirol UM-3G */ + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + .ifnum = 0, + .type = QUIRK_MIDI_STANDARD_INTERFACE + } +}, { /* Boss JS-8 Jam Station */ USB_DEVICE(0x0582, 0x0109), From 2492250e4412c6411324c14ab289629360640b0a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sat, 4 Feb 2012 20:56:47 +0100 Subject: [PATCH 370/380] ALSA: oxygen, virtuoso: fix exchanged L/R volumes of aux and CD inputs The driver accidentally exchanged the left/right fields for stereo AC'97 mixer registers. This affected only the aux and CD inputs because the line input bypasses the AC'97 codec and the mic input is mono; cards without AC'97 (Xonar DS/DG/HDAV Slim, HG2PCI, HiFier) were not affected. Reported-and-tested-by: Abby Cedar Signed-off-by: Clemens Ladisch Cc: 2.6.31+ Signed-off-by: Takashi Iwai --- sound/pci/oxygen/oxygen_mixer.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index 26c7e8bcb229..c0dbb52d45be 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c @@ -618,9 +618,12 @@ static int ac97_volume_get(struct snd_kcontrol *ctl, mutex_lock(&chip->mutex); reg = oxygen_read_ac97(chip, codec, index); mutex_unlock(&chip->mutex); - value->value.integer.value[0] = 31 - (reg & 0x1f); - if (stereo) - value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f); + if (!stereo) { + value->value.integer.value[0] = 31 - (reg & 0x1f); + } else { + value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f); + value->value.integer.value[1] = 31 - (reg & 0x1f); + } return 0; } @@ -636,14 +639,14 @@ static int ac97_volume_put(struct snd_kcontrol *ctl, mutex_lock(&chip->mutex); oldreg = oxygen_read_ac97(chip, codec, index); - newreg = oldreg; - newreg = (newreg & ~0x1f) | - (31 - (value->value.integer.value[0] & 0x1f)); - if (stereo) - newreg = (newreg & ~0x1f00) | - ((31 - (value->value.integer.value[1] & 0x1f)) << 8); - else - newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8); + if (!stereo) { + newreg = oldreg & ~0x1f; + newreg |= 31 - (value->value.integer.value[0] & 0x1f); + } else { + newreg = oldreg & ~0x1f1f; + newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8; + newreg |= 31 - (value->value.integer.value[1] & 0x1f); + } change = newreg != oldreg; if (change) oxygen_write_ac97(chip, codec, index, newreg); From f647e1526fd6c7c8ab720781c40d11e11f930e93 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Feb 2012 17:24:19 +0000 Subject: [PATCH 371/380] ASoC: wm8994: Fix typo in VMID ramp setting The VMID ramp rate is supposed to be 0x3, not 11b. Fix that. Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/wm8994.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 81795ebcab17..b75a65273dab 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -785,7 +785,7 @@ static void vmid_reference(struct snd_soc_codec *codec) WM8994_VMID_RAMP_MASK, WM8994_STARTUP_BIAS_ENA | WM8994_VMID_BUF_ENA | - (0x11 << WM8994_VMID_RAMP_SHIFT)); + (0x3 << WM8994_VMID_RAMP_SHIFT)); /* Main bias enable, VMID=2x40k */ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, From a7c4183be2d6a7da8c97a9b671b5f3aed321127e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Feb 2012 14:18:29 +0000 Subject: [PATCH 372/380] ASoC: wm8994: Disable line output discharge prior to ramping VMID Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b75a65273dab..ec69a6c152fe 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -787,6 +787,11 @@ static void vmid_reference(struct snd_soc_codec *codec) WM8994_VMID_BUF_ENA | (0x3 << WM8994_VMID_RAMP_SHIFT)); + /* Remove discharge for line out */ + snd_soc_update_bits(codec, WM8994_ANTIPOP_1, + WM8994_LINEOUT1_DISCH | + WM8994_LINEOUT2_DISCH, 0); + /* Main bias enable, VMID=2x40k */ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, WM8994_BIAS_ENA | From 1ecd3c7ea76488c63b4b0a2561fd7eaf96cc8028 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 8 Feb 2012 17:13:37 -0800 Subject: [PATCH 373/380] nilfs2: avoid overflowing segment numbers in nilfs_ioctl_clean_segments() nsegs is read from userspace. Limit its value and avoid overflowing nsegs * sizeof(__u64) in the subsequent call to memdup_user(). This patch complements 481fe17e973fb9 ("nilfs2: potential integer overflow in nilfs_ioctl_clean_segments()"). Signed-off-by: Xi Wang Cc: Haogang Chen Acked-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 886649627c3d..2a70fce70c65 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -603,6 +603,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, nsegs = argv[4].v_nmembs; if (argv[4].v_size != argsz[4]) goto out; + if (nsegs > UINT_MAX / sizeof(__u64)) + goto out; /* * argv[4] points to segment numbers this ioctl cleans. We From dc9086004b3d5db75997a645b3fe08d9138b7ad0 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 8 Feb 2012 17:13:38 -0800 Subject: [PATCH 374/380] mm: compaction: check for overlapping nodes during isolation for migration When isolating pages for migration, migration starts at the start of a zone while the free scanner starts at the end of the zone. Migration avoids entering a new zone by never going beyond the free scanned. Unfortunately, in very rare cases nodes can overlap. When this happens, migration isolates pages without the LRU lock held, corrupting lists which will trigger errors in reclaim or during page free such as in the following oops BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 IP: [] free_pcppages_bulk+0xcc/0x450 PGD 1dda554067 PUD 1e1cb58067 PMD 0 Oops: 0000 [#1] SMP CPU 37 Pid: 17088, comm: memcg_process_s Tainted: G X RIP: free_pcppages_bulk+0xcc/0x450 Process memcg_process_s (pid: 17088, threadinfo ffff881c2926e000, task ffff881c2926c0c0) Call Trace: free_hot_cold_page+0x17e/0x1f0 __pagevec_free+0x90/0xb0 release_pages+0x22a/0x260 pagevec_lru_move_fn+0xf3/0x110 putback_lru_page+0x66/0xe0 unmap_and_move+0x156/0x180 migrate_pages+0x9e/0x1b0 compact_zone+0x1f3/0x2f0 compact_zone_order+0xa2/0xe0 try_to_compact_pages+0xdf/0x110 __alloc_pages_direct_compact+0xee/0x1c0 __alloc_pages_slowpath+0x370/0x830 __alloc_pages_nodemask+0x1b1/0x1c0 alloc_pages_vma+0x9b/0x160 do_huge_pmd_anonymous_page+0x160/0x270 do_page_fault+0x207/0x4c0 page_fault+0x25/0x30 The "X" in the taint flag means that external modules were loaded but but is unrelated to the bug triggering. The real problem was because the PFN layout looks like this Zone PFN ranges: DMA 0x00000010 -> 0x00001000 DMA32 0x00001000 -> 0x00100000 Normal 0x00100000 -> 0x01e80000 Movable zone start PFN for each node early_node_map[14] active PFN ranges 0: 0x00000010 -> 0x0000009b 0: 0x00000100 -> 0x0007a1ec 0: 0x0007a354 -> 0x0007a379 0: 0x0007f7ff -> 0x0007f800 0: 0x00100000 -> 0x00680000 1: 0x00680000 -> 0x00e80000 0: 0x00e80000 -> 0x01080000 1: 0x01080000 -> 0x01280000 0: 0x01280000 -> 0x01480000 1: 0x01480000 -> 0x01680000 0: 0x01680000 -> 0x01880000 1: 0x01880000 -> 0x01a80000 0: 0x01a80000 -> 0x01c80000 1: 0x01c80000 -> 0x01e80000 The fix is straight-forward. isolate_migratepages() has to make a similar check to isolate_freepage to ensure that it never isolates pages from a zone it does not hold the LRU lock for. This was discovered in a 3.0-based kernel but it affects 3.1.x, 3.2.x and current mainline. Signed-off-by: Mel Gorman Acked-by: Michal Nazarewicz Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/compaction.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mm/compaction.c b/mm/compaction.c index bd939a574b84..d9ebebe1a2aa 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -330,8 +330,17 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, continue; nr_scanned++; - /* Get the page and skip if free */ + /* + * Get the page and ensure the page is within the same zone. + * See the comment in isolate_freepages about overlapping + * nodes. It is deliberate that the new zone lock is not taken + * as memory compaction should not move pages between nodes. + */ page = pfn_to_page(low_pfn); + if (page_zone(page) != zone) + continue; + + /* Skip if free */ if (PageBuddy(page)) continue; From ec44fd429879f7d4f28021f1a7f9fb0b5f831aab Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 8 Feb 2012 17:13:39 -0800 Subject: [PATCH 375/380] drivers/leds/leds-lm3530.c: fix setting pltfm->als_vmax In current code, pltfm->als_vmin is set to LM3530_ALS_WINDOW_mV and pltfm->als_vmax is 0. This does not make sense. I think what we want here is setting pltfm->als_vmax to LM3530_ALS_WINDOW_mV. Both als_vmin and als_vmax local variables will be set to pltfm->als_vmin and pltfm->als_vmax by a few lines latter. Thus also remove a redundant assignment for als_vmin and als_vmax in this patch. Signed-off-by: Axel Lin Cc: Shreshtha Kumar Sahu Acked-by: Milo(Woogyom) Kim Tested-by: Milo(Woogyom) Kim Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/leds-lm3530.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index 45e6878d7374..e59c166a0ce2 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c @@ -164,8 +164,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata) if (drvdata->mode == LM3530_BL_MODE_ALS) { if (pltfm->als_vmax == 0) { - pltfm->als_vmin = als_vmin = 0; - pltfm->als_vmin = als_vmax = LM3530_ALS_WINDOW_mV; + pltfm->als_vmin = 0; + pltfm->als_vmax = LM3530_ALS_WINDOW_mV; } als_vmin = pltfm->als_vmin; From b9980cdcf2524c5fe15d8cbae9c97b3ed6385563 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 8 Feb 2012 17:13:40 -0800 Subject: [PATCH 376/380] mm: fix UP THP spin_is_locked BUGs Fix CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_SMP=n CONFIG_DEBUG_VM=y CONFIG_DEBUG_SPINLOCK=n kernel: spin_is_locked() is then always false, and so triggers some BUGs in Transparent HugePage codepaths. asm-generic/bug.h mentions this problem, and provides a WARN_ON_SMP(x); but being too lazy to add VM_BUG_ON_SMP, BUG_ON_SMP, WARN_ON_SMP_ONCE, VM_WARN_ON_SMP_ONCE, just test NR_CPUS != 1 in the existing VM_BUG_ONs. Signed-off-by: Hugh Dickins Cc: Andrea Arcangeli Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/huge_memory.c | 4 ++-- mm/swap.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index b3ffc21ce801..91d3efb25d15 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2083,7 +2083,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot) { struct mm_struct *mm = mm_slot->mm; - VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock)); + VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock)); if (khugepaged_test_exit(mm)) { /* free mm_slot */ @@ -2113,7 +2113,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int progress = 0; VM_BUG_ON(!pages); - VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock)); + VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock)); if (khugepaged_scan.mm_slot) mm_slot = khugepaged_scan.mm_slot; diff --git a/mm/swap.c b/mm/swap.c index b0f529b38979..fff1ff7fb9ad 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -659,7 +659,7 @@ void lru_add_page_tail(struct zone* zone, VM_BUG_ON(!PageHead(page)); VM_BUG_ON(PageCompound(page_tail)); VM_BUG_ON(PageLRU(page_tail)); - VM_BUG_ON(!spin_is_locked(&zone->lru_lock)); + VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&zone->lru_lock)); SetPageLRU(page_tail); From 025e4ab3db07fcbf62c01e4f30d1012234beb980 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 8 Feb 2012 17:13:41 -0800 Subject: [PATCH 377/380] pcmcia: fix socket refcount decrementing on each resume This fixes a memory-corrupting bug: not only does it cause the warning, but as a result of dropping the refcount to zero, it causes the pcmcia_socket0 device structure to be freed while it still has references, causing slab caches corruption. A fatal oops quickly follows this warning - often even just a 'dmesg' following the warning causes the kernel to oops. While testing suspend/resume on an ARM device with PCMCIA support, and a CF card inserted, I found that after five suspend and resumes, the kernel would complain, and shortly die after with slab corruption. WARNING: at include/linux/kref.h:41 kobject_get+0x28/0x50() As the message doesn't give a clue about which kobject, and the built-in debugging in drivers/base/power/main.c happens too late, this was added right before each get_device(): printk("%s: %p [%s] %u\n", __func__, dev, kobject_name(&dev->kobj), atomic_read(&dev->kobj.kref.refcount)); and on the 3rd s2ram cycle, the following behaviour observed: On the 3rd suspend/resume cycle: dpm_prepare: c1a0d998 [pcmcia_socket0] 3 dpm_suspend: c1a0d998 [pcmcia_socket0] 3 dpm_suspend_noirq: c1a0d998 [pcmcia_socket0] 3 dpm_resume_noirq: c1a0d998 [pcmcia_socket0] 3 dpm_resume: c1a0d998 [pcmcia_socket0] 3 dpm_complete: c1a0d998 [pcmcia_socket0] 2 4th: dpm_prepare: c1a0d998 [pcmcia_socket0] 2 dpm_suspend: c1a0d998 [pcmcia_socket0] 2 dpm_suspend_noirq: c1a0d998 [pcmcia_socket0] 2 dpm_resume_noirq: c1a0d998 [pcmcia_socket0] 2 dpm_resume: c1a0d998 [pcmcia_socket0] 2 dpm_complete: c1a0d998 [pcmcia_socket0] 1 5th: dpm_prepare: c1a0d998 [pcmcia_socket0] 1 dpm_suspend: c1a0d998 [pcmcia_socket0] 1 dpm_suspend_noirq: c1a0d998 [pcmcia_socket0] 1 dpm_resume_noirq: c1a0d998 [pcmcia_socket0] 1 dpm_resume: c1a0d998 [pcmcia_socket0] 1 dpm_complete: c1a0d998 [pcmcia_socket0] 0 ------------[ cut here ]------------ WARNING: at include/linux/kref.h:41 kobject_get+0x28/0x50() Modules linked in: ucb1x00_core Backtrace: [] (dump_backtrace+0x0/0x110) from [] (dump_stack+0x18/0x1c) [] (dump_stack+0x0/0x1c) from [] (warn_slowpath_common+0x50/0x68) [] (warn_slowpath_common+0x0/0x68) from [] (warn_slowpath_null+0x24/0x28) [] (warn_slowpath_null+0x0/0x28) from [] (kobject_get+0x28/0x50) [] (kobject_get+0x0/0x50) from [] (get_device+0x1c/0x24) [] (dpm_complete+0x0/0x1a0) from [] (dpm_resume_end+0x1c/0x20) ... Looking at commit 7b24e7988263 ("pcmcia: split up central event handler"), the following change was made to cs.c: return 0; } #endif - - send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); + if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) + skt->callback->early_resume(skt); return 0; } And the corresponding change in ds.c is from: -static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) -{ - struct pcmcia_socket *s = pcmcia_get_socket(skt); ... - switch (event) { ... - case CS_EVENT_PM_RESUME: - if (verify_cis_cache(skt) != 0) { - dev_dbg(&skt->dev, "cis mismatch - different card\n"); - /* first, remove the card */ - ds_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); - mutex_lock(&s->ops_mutex); - destroy_cis_cache(skt); - kfree(skt->fake_cis); - skt->fake_cis = NULL; - s->functions = 0; - mutex_unlock(&s->ops_mutex); - /* now, add the new card */ - ds_event(skt, CS_EVENT_CARD_INSERTION, - CS_EVENT_PRI_LOW); - } - break; ... - } - pcmcia_put_socket(s); - return 0; -} /* ds_event */ to: +static int pcmcia_bus_early_resume(struct pcmcia_socket *skt) +{ + if (!verify_cis_cache(skt)) { + pcmcia_put_socket(skt); + return 0; + } + dev_dbg(&skt->dev, "cis mismatch - different card\n"); + /* first, remove the card */ + pcmcia_bus_remove(skt); + mutex_lock(&skt->ops_mutex); + destroy_cis_cache(skt); + kfree(skt->fake_cis); + skt->fake_cis = NULL; + skt->functions = 0; + mutex_unlock(&skt->ops_mutex); + /* now, add the new card */ + pcmcia_bus_add(skt); + return 0; +} As can be seen, the original function called pcmcia_get_socket() and pcmcia_put_socket() around the guts, whereas the replacement code calls pcmcia_put_socket() only in one path. This creates an imbalance in the refcounting. Testing with pcmcia_put_socket() put removed shows that the bug is gone: dpm_suspend: c1a10998 [pcmcia_socket0] 5 dpm_suspend_noirq: c1a10998 [pcmcia_socket0] 5 dpm_resume_noirq: c1a10998 [pcmcia_socket0] 5 dpm_resume: c1a10998 [pcmcia_socket0] 5 dpm_complete: c1a10998 [pcmcia_socket0] 5 Tested-by: Russell King Signed-off-by: Russell King Cc: Dominik Brodowski Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 749c2a16012c..1932029de48d 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1269,10 +1269,8 @@ static int pcmcia_bus_add(struct pcmcia_socket *skt) static int pcmcia_bus_early_resume(struct pcmcia_socket *skt) { - if (!verify_cis_cache(skt)) { - pcmcia_put_socket(skt); + if (!verify_cis_cache(skt)) return 0; - } dev_dbg(&skt->dev, "cis mismatch - different card\n"); From d65b4e98d7ea3038b767b70fe8be959b2913f16d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Feb 2012 19:21:53 -0800 Subject: [PATCH 378/380] Linux 3.3-rc3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e3b23e864a53..7c44b676b77a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 3 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Saber-toothed Squirrel # *DOCUMENTATION* From 35bded8f91e887bf2d692071bb720b03c6ccd3fe Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 8 Feb 2012 11:42:39 +0900 Subject: [PATCH 379/380] ARM: EXYNOS: Bring exynos4-dt up to date This commit brings exynos4-dt in line with recent changes to mach-exynos tree, specifically: - Fixes build break related to replacing plat/exynos4.h with common.h in commit cc511b8d84d8 ("ARM: 7257/1: EXYNOS: introduce arch/arm/mach-exynos/common.[ch]") - Converts machine to use CONFIG_MULTI_IRQ_HANDLER as done for other machines in commit 4e44d2cb95bd ("ARM: exynos4: convert to CONFIG_MULTI_IRQ_HANDLER") - Adds restart specifier as done for other machines in commit 9eb4859564d6 ("ARM: 7262/1: restart: EXYNOS: use new restart hook") Signed-off-by: Karol Lewandowski Signed-off-by: Kyungmin Park Cc: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/mach-exynos4-dt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index 85fa02767d67..e6b02fdf1b09 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -15,11 +15,13 @@ #include #include +#include #include #include #include -#include + +#include "common.h" /* * The following lookup table is used to override device names when devices @@ -60,7 +62,7 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = { static void __init exynos4210_dt_map_io(void) { - s5p_init_io(NULL, 0, S5P_VA_CHIPID); + exynos_init_io(NULL, 0); s3c24xx_init_clocks(24000000); } @@ -79,7 +81,9 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)") /* Maintainer: Thomas Abraham */ .init_irq = exynos4_init_irq, .map_io = exynos4210_dt_map_io, + .handle_irq = gic_handle_irq, .init_machine = exynos4210_dt_machine_init, .timer = &exynos4_timer, .dt_compat = exynos4210_dt_compat, + .restart = exynos4_restart, MACHINE_END From da911782be4c82dc1222aa0cb5bef28605d1e117 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Wed, 8 Feb 2012 11:42:43 +0900 Subject: [PATCH 380/380] ARM: EXYNOS: Add cpu-offset property in gic device tree node Commit db0d4db22a78 ('ARM: gic: allow GIC to support non-banked setups) requires a cpu-offset property to be specified for non-banked gic controllers, which is the case for Exynos4. Reported-and-Tested-by: Karol Lewandowski Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4210.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index 63d7578856c1..a1dd2ee83753 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -29,6 +29,7 @@ compatible = "arm,cortex-a9-gic"; #interrupt-cells = <3>; interrupt-controller; + cpu-offset = <0x8000>; reg = <0x10490000 0x1000>, <0x10480000 0x100>; };