commit: 47fa915ee949add7495467389f5b892f887161a1 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Thu Mar 10 00:49:12 2016 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Thu Mar 10 00:49:12 2016 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=47fa915e
Linux patch 3.14.64 0000_README | 4 + 1063_linux-3.14.64.patch | 2749 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2753 insertions(+) diff --git a/0000_README b/0000_README index 1173db7..52ef4aa 100644 --- a/0000_README +++ b/0000_README @@ -294,6 +294,10 @@ Patch: 1062_linux-3.14.63.patch From: http://www.kernel.org Desc: Linux 3.14.63 +Patch: 1063_linux-3.14.64.patch +From: http://www.kernel.org +Desc: Linux 3.14.64 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1063_linux-3.14.64.patch b/1063_linux-3.14.64.patch new file mode 100644 index 0000000..4e1bc88 --- /dev/null +++ b/1063_linux-3.14.64.patch @@ -0,0 +1,2749 @@ +diff --git a/Makefile b/Makefile +index 0843ef4cc0a4..de41fa82652f 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 63 ++SUBLEVEL = 64 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c +index 81e6ae0220bc..887535c4c93d 100644 +--- a/arch/mips/kernel/traps.c ++++ b/arch/mips/kernel/traps.c +@@ -688,15 +688,15 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) + asmlinkage void do_ov(struct pt_regs *regs) + { + enum ctx_state prev_state; +- siginfo_t info; ++ siginfo_t info = { ++ .si_signo = SIGFPE, ++ .si_code = FPE_INTOVF, ++ .si_addr = (void __user *)regs->cp0_epc, ++ }; + + prev_state = exception_enter(); + die_if_kernel("Integer overflow", regs); + +- info.si_code = FPE_INTOVF; +- info.si_signo = SIGFPE; +- info.si_errno = 0; +- info.si_addr = (void __user *) regs->cp0_epc; + force_sig_info(SIGFPE, &info, current); + exception_exit(prev_state); + } +@@ -797,7 +797,7 @@ out: + static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, + const char *str) + { +- siginfo_t info; ++ siginfo_t info = { 0 }; + char b[40]; + + #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP +@@ -825,7 +825,6 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, + else + info.si_code = FPE_INTOVF; + info.si_signo = SIGFPE; +- info.si_errno = 0; + info.si_addr = (void __user *) regs->cp0_epc; + force_sig_info(SIGFPE, &info, current); + break; +diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S +index 92a2e9333620..b74ac9c5710b 100644 +--- a/arch/x86/ia32/ia32entry.S ++++ b/arch/x86/ia32/ia32entry.S +@@ -422,6 +422,7 @@ ENTRY(ia32_syscall) + /*CFI_REL_OFFSET cs,CS-RIP*/ + CFI_REL_OFFSET rip,RIP-RIP + PARAVIRT_ADJUST_EXCEPTION_FRAME ++ ASM_CLAC /* Do this early to minimize exposure */ + SWAPGS + /* + * No need to follow this irqs on/off section: the syscall +diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c +index 3a2ae4c88948..398c7a908c17 100644 +--- a/arch/x86/kernel/acpi/sleep.c ++++ b/arch/x86/kernel/acpi/sleep.c +@@ -16,6 +16,7 @@ + #include <asm/cacheflush.h> + #include <asm/realmode.h> + ++#include <linux/ftrace.h> + #include "../../realmode/rm/wakeup.h" + #include "sleep.h" + +@@ -107,7 +108,13 @@ int x86_acpi_suspend_lowlevel(void) + saved_magic = 0x123456789abcdef0L; + #endif /* CONFIG_64BIT */ + ++ /* ++ * Pause/unpause graph tracing around do_suspend_lowlevel as it has ++ * inconsistent call/return info after it jumps to the wakeup vector. ++ */ ++ pause_graph_tracing(); + do_suspend_lowlevel(); ++ unpause_graph_tracing(); + return 0; + } + +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index 6fecf0bde105..1e82d2a1e205 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -674,19 +674,18 @@ static int ata_ioc32(struct ata_port *ap) + int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev, + int cmd, void __user *arg) + { +- int val = -EINVAL, rc = -EINVAL; ++ unsigned long val; ++ int rc = -EINVAL; + unsigned long flags; + + switch (cmd) { +- case ATA_IOC_GET_IO32: ++ case HDIO_GET_32BIT: + spin_lock_irqsave(ap->lock, flags); + val = ata_ioc32(ap); + spin_unlock_irqrestore(ap->lock, flags); +- if (copy_to_user(arg, &val, 1)) +- return -EFAULT; +- return 0; ++ return put_user(val, (unsigned long __user *)arg); + +- case ATA_IOC_SET_IO32: ++ case HDIO_SET_32BIT: + val = (unsigned long) arg; + rc = 0; + spin_lock_irqsave(ap->lock, flags); +diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c +index b335c6ab5efe..b2dd473237e8 100644 +--- a/drivers/edac/edac_mc_sysfs.c ++++ b/drivers/edac/edac_mc_sysfs.c +@@ -973,21 +973,26 @@ nomem: + */ + int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) + { ++ char *name; + int i, err; + + /* + * The memory controller needs its own bus, in order to avoid + * namespace conflicts at /sys/bus/edac. + */ +- mci->bus->name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); +- if (!mci->bus->name) ++ name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); ++ if (!name) + return -ENOMEM; + ++ mci->bus->name = name; ++ + edac_dbg(0, "creating bus %s\n", mci->bus->name); + + err = bus_register(mci->bus); +- if (err < 0) ++ if (err < 0) { ++ kfree(name); + return err; ++ } + + /* get the /sys/devices/system/edac subsys reference */ + mci->dev.type = &mci_attr_type; +@@ -1071,7 +1076,8 @@ fail: + fail2: + device_unregister(&mci->dev); + bus_unregister(mci->bus); +- kfree(mci->bus->name); ++ kfree(name); ++ + return err; + } + +@@ -1102,10 +1108,12 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) + + void edac_unregister_sysfs(struct mem_ctl_info *mci) + { ++ const char *name = mci->bus->name; ++ + edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev)); + device_unregister(&mci->dev); + bus_unregister(mci->bus); +- kfree(mci->bus->name); ++ kfree(name); + } + + static void mc_attr_release(struct device *dev) +diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c +index c0f284230a39..ed8d93cbd1ca 100644 +--- a/drivers/gpu/drm/ast/ast_main.c ++++ b/drivers/gpu/drm/ast/ast_main.c +@@ -124,7 +124,7 @@ static int ast_get_dram_info(struct drm_device *dev) + } while (ast_read32(ast, 0x10000) != 0x01); + data = ast_read32(ast, 0x10004); + +- if (data & 0x400) ++ if (data & 0x40) + ast->dram_bus_width = 16; + else + ast->dram_bus_width = 32; +diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c +index a49ce4a6e72f..1320a81df792 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -2071,6 +2071,24 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd) + return isert_post_response(isert_conn, isert_cmd); + } + ++static void ++isert_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd) ++{ ++ struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); ++ struct isert_conn *isert_conn = (struct isert_conn *)conn->context; ++ struct isert_device *device = isert_conn->conn_device; ++ ++ spin_lock_bh(&conn->cmd_lock); ++ if (!list_empty(&cmd->i_conn_node)) ++ list_del_init(&cmd->i_conn_node); ++ spin_unlock_bh(&conn->cmd_lock); ++ ++ if (cmd->data_direction == DMA_TO_DEVICE) ++ iscsit_stop_dataout_timer(cmd); ++ ++ device->unreg_rdma_mem(isert_cmd, isert_conn); ++} ++ + static int + isert_put_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn, + bool nopout_response) +@@ -2999,6 +3017,7 @@ static struct iscsit_transport iser_target_transport = { + .iscsit_get_dataout = isert_get_dataout, + .iscsit_queue_data_in = isert_put_datain, + .iscsit_queue_status = isert_put_response, ++ .iscsit_aborted_task = isert_aborted_task, + }; + + static int __init isert_init(void) +diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c +index 0097b8dae5bc..727a88d9a708 100644 +--- a/drivers/infiniband/ulp/srpt/ib_srpt.c ++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c +@@ -3093,6 +3093,14 @@ static void srpt_queue_tm_rsp(struct se_cmd *cmd) + srpt_queue_response(cmd); + } + ++static void srpt_aborted_task(struct se_cmd *cmd) ++{ ++ struct srpt_send_ioctx *ioctx = container_of(cmd, ++ struct srpt_send_ioctx, cmd); ++ ++ srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx); ++} ++ + static int srpt_queue_status(struct se_cmd *cmd) + { + struct srpt_send_ioctx *ioctx; +@@ -3940,6 +3948,7 @@ static struct target_core_fabric_ops srpt_template = { + .queue_data_in = srpt_queue_data_in, + .queue_status = srpt_queue_status, + .queue_tm_rsp = srpt_queue_tm_rsp, ++ .aborted_task = srpt_aborted_task, + /* + * Setup function pointers for generic logic in + * target_core_fabric_configfs.c +diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c +index 28b4bea7c109..a8e52ef6e266 100644 +--- a/drivers/iommu/amd_iommu_init.c ++++ b/drivers/iommu/amd_iommu_init.c +@@ -226,6 +226,10 @@ static enum iommu_init_state init_state = IOMMU_START_STATE; + static int amd_iommu_enable_interrupts(void); + static int __init iommu_go_to_state(enum iommu_init_state state); + ++static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, ++ u8 bank, u8 cntr, u8 fxn, ++ u64 *value, bool is_write); ++ + static inline void update_last_devid(u16 devid) + { + if (devid > amd_iommu_last_bdf) +@@ -1182,8 +1186,8 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu) + amd_iommu_pc_present = true; + + /* Check if the performance counters can be written to */ +- if ((0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val, true)) || +- (0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val2, false)) || ++ if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) || ++ (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) || + (val != val2)) { + pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n"); + amd_iommu_pc_present = false; +@@ -2314,22 +2318,15 @@ u8 amd_iommu_pc_get_max_counters(u16 devid) + } + EXPORT_SYMBOL(amd_iommu_pc_get_max_counters); + +-int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, ++static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, ++ u8 bank, u8 cntr, u8 fxn, + u64 *value, bool is_write) + { +- struct amd_iommu *iommu; + u32 offset; + u32 max_offset_lim; + +- /* Make sure the IOMMU PC resource is available */ +- if (!amd_iommu_pc_present) +- return -ENODEV; +- +- /* Locate the iommu associated with the device ID */ +- iommu = amd_iommu_rlookup_table[devid]; +- + /* Check for valid iommu and pc register indexing */ +- if (WARN_ON((iommu == NULL) || (fxn > 0x28) || (fxn & 7))) ++ if (WARN_ON((fxn > 0x28) || (fxn & 7))) + return -ENODEV; + + offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn); +@@ -2353,3 +2350,16 @@ int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, + return 0; + } + EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val); ++ ++int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, ++ u64 *value, bool is_write) ++{ ++ struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; ++ ++ /* Make sure the IOMMU PC resource is available */ ++ if (!amd_iommu_pc_present || iommu == NULL) ++ return -ENODEV; ++ ++ return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn, ++ value, is_write); ++} +diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c +index 2a1b6e037e1a..0134ba32a057 100644 +--- a/drivers/mtd/ubi/upd.c ++++ b/drivers/mtd/ubi/upd.c +@@ -193,7 +193,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, + vol->changing_leb = 1; + vol->ch_lnum = req->lnum; + +- vol->upd_buf = vmalloc(req->bytes); ++ vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size)); + if (!vol->upd_buf) + return -ENOMEM; + +diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +index 1817f3f2b02d..f46c0a6c5016 100644 +--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c ++++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +@@ -684,6 +684,20 @@ static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd) + qlt_xmit_tm_rsp(mcmd); + } + ++static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd) ++{ ++ struct qla_tgt_cmd *cmd = container_of(se_cmd, ++ struct qla_tgt_cmd, se_cmd); ++ struct scsi_qla_host *vha = cmd->vha; ++ struct qla_hw_data *ha = vha->hw; ++ ++ if (!cmd->sg_mapped) ++ return; ++ ++ pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); ++ cmd->sg_mapped = 0; ++} ++ + /* Local pointer to allocated TCM configfs fabric module */ + struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs; + struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs; +@@ -1886,6 +1900,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = { + .queue_data_in = tcm_qla2xxx_queue_data_in, + .queue_status = tcm_qla2xxx_queue_status, + .queue_tm_rsp = tcm_qla2xxx_queue_tm_rsp, ++ .aborted_task = tcm_qla2xxx_aborted_task, + /* + * Setup function pointers for generic logic in + * target_core_fabric_configfs.c +@@ -1935,6 +1950,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { + .queue_data_in = tcm_qla2xxx_queue_data_in, + .queue_status = tcm_qla2xxx_queue_status, + .queue_tm_rsp = tcm_qla2xxx_queue_tm_rsp, ++ .aborted_task = tcm_qla2xxx_aborted_task, + /* + * Setup function pointers for generic logic in + * target_core_fabric_configfs.c +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index c066e6e298c3..5600eab07865 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -500,6 +500,18 @@ static int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd) + return 0; + } + ++static void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd) ++{ ++ bool scsi_cmd = (cmd->iscsi_opcode == ISCSI_OP_SCSI_CMD); ++ ++ spin_lock_bh(&conn->cmd_lock); ++ if (!list_empty(&cmd->i_conn_node)) ++ list_del_init(&cmd->i_conn_node); ++ spin_unlock_bh(&conn->cmd_lock); ++ ++ __iscsit_free_cmd(cmd, scsi_cmd, true); ++} ++ + static struct iscsit_transport iscsi_target_transport = { + .name = "iSCSI/TCP", + .transport_type = ISCSI_TCP, +@@ -514,6 +526,7 @@ static struct iscsit_transport iscsi_target_transport = { + .iscsit_response_queue = iscsit_response_queue, + .iscsit_queue_data_in = iscsit_queue_rsp, + .iscsit_queue_status = iscsit_queue_rsp, ++ .iscsit_aborted_task = iscsit_aborted_task, + }; + + static int __init iscsi_target_init_module(void) +diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c +index 83465617ad6d..4a28c5f0dfd1 100644 +--- a/drivers/target/iscsi/iscsi_target_configfs.c ++++ b/drivers/target/iscsi/iscsi_target_configfs.c +@@ -1815,6 +1815,13 @@ static void lio_queue_tm_rsp(struct se_cmd *se_cmd) + iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); + } + ++static void lio_aborted_task(struct se_cmd *se_cmd) ++{ ++ struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); ++ ++ cmd->conn->conn_transport->iscsit_aborted_task(cmd->conn, cmd); ++} ++ + static char *lio_tpg_get_endpoint_wwn(struct se_portal_group *se_tpg) + { + struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr; +@@ -2013,6 +2020,7 @@ int iscsi_target_register_configfs(void) + fabric->tf_ops.queue_data_in = &lio_queue_data_in; + fabric->tf_ops.queue_status = &lio_queue_status; + fabric->tf_ops.queue_tm_rsp = &lio_queue_tm_rsp; ++ fabric->tf_ops.aborted_task = &lio_aborted_task; + /* + * Setup function pointers for generic logic in target_core_fabric_configfs.c + */ +diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c +index 1e406af4ee47..2e96ae6cf3c1 100644 +--- a/drivers/target/iscsi/iscsi_target_util.c ++++ b/drivers/target/iscsi/iscsi_target_util.c +@@ -705,8 +705,8 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd) + } + EXPORT_SYMBOL(iscsit_release_cmd); + +-static void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool scsi_cmd, +- bool check_queues) ++void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool scsi_cmd, ++ bool check_queues) + { + struct iscsi_conn *conn = cmd->conn; + +diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h +index 561a424d1980..a68508c4fec8 100644 +--- a/drivers/target/iscsi/iscsi_target_util.h ++++ b/drivers/target/iscsi/iscsi_target_util.h +@@ -30,6 +30,7 @@ extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_co + extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); + extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); + extern void iscsit_release_cmd(struct iscsi_cmd *); ++extern void __iscsit_free_cmd(struct iscsi_cmd *, bool, bool); + extern void iscsit_free_cmd(struct iscsi_cmd *, bool); + extern int iscsit_check_session_usage_count(struct iscsi_session *); + extern void iscsit_dec_session_usage_count(struct iscsi_session *); +diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c +index 67c802c93ef3..fd974d69458b 100644 +--- a/drivers/target/loopback/tcm_loop.c ++++ b/drivers/target/loopback/tcm_loop.c +@@ -892,6 +892,11 @@ static void tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd) + wake_up(&tl_tmr->tl_tmr_wait); + } + ++static void tcm_loop_aborted_task(struct se_cmd *se_cmd) ++{ ++ return; ++} ++ + static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba) + { + switch (tl_hba->tl_proto_id) { +@@ -1456,6 +1461,7 @@ static int tcm_loop_register_configfs(void) + fabric->tf_ops.queue_data_in = &tcm_loop_queue_data_in; + fabric->tf_ops.queue_status = &tcm_loop_queue_status; + fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp; ++ fabric->tf_ops.aborted_task = &tcm_loop_aborted_task; + + /* + * Setup function pointers for generic logic in target_core_fabric_configfs.c +diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c +index 24884cac19ce..ad04ea928e4f 100644 +--- a/drivers/target/sbp/sbp_target.c ++++ b/drivers/target/sbp/sbp_target.c +@@ -1846,6 +1846,11 @@ static void sbp_queue_tm_rsp(struct se_cmd *se_cmd) + { + } + ++static void sbp_aborted_task(struct se_cmd *se_cmd) ++{ ++ return; ++} ++ + static int sbp_check_stop_free(struct se_cmd *se_cmd) + { + struct sbp_target_request *req = container_of(se_cmd, +@@ -2526,6 +2531,7 @@ static struct target_core_fabric_ops sbp_ops = { + .queue_data_in = sbp_queue_data_in, + .queue_status = sbp_queue_status, + .queue_tm_rsp = sbp_queue_tm_rsp, ++ .aborted_task = sbp_aborted_task, + .check_stop_free = sbp_check_stop_free, + + .fabric_make_wwn = sbp_make_tport, +diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c +index f30385385544..756def38c77a 100644 +--- a/drivers/target/target_core_configfs.c ++++ b/drivers/target/target_core_configfs.c +@@ -457,6 +457,10 @@ static int target_fabric_tf_ops_check( + pr_err("Missing tfo->queue_tm_rsp()\n"); + return -EINVAL; + } ++ if (!tfo->aborted_task) { ++ pr_err("Missing tfo->aborted_task()\n"); ++ return -EINVAL; ++ } + /* + * We at least require tfo->fabric_make_wwn(), tfo->fabric_drop_wwn() + * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index 093b8cb85de7..e366b812f0e1 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -1577,6 +1577,49 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) + return dev; + } + ++/* ++ * Check if the underlying struct block_device request_queue supports ++ * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM ++ * in ATA and we need to set TPE=1 ++ */ ++bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, ++ struct request_queue *q, int block_size) ++{ ++ if (!blk_queue_discard(q)) ++ return false; ++ ++ attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) / ++ block_size; ++ /* ++ * Currently hardcoded to 1 in Linux/SCSI code.. ++ */ ++ attrib->max_unmap_block_desc_count = 1; ++ attrib->unmap_granularity = q->limits.discard_granularity / block_size; ++ attrib->unmap_granularity_alignment = q->limits.discard_alignment / ++ block_size; ++ return true; ++} ++EXPORT_SYMBOL(target_configure_unmap_from_queue); ++ ++/* ++ * Convert from blocksize advertised to the initiator to the 512 byte ++ * units unconditionally used by the Linux block layer. ++ */ ++sector_t target_to_linux_sector(struct se_device *dev, sector_t lb) ++{ ++ switch (dev->dev_attrib.block_size) { ++ case 4096: ++ return lb << 3; ++ case 2048: ++ return lb << 2; ++ case 1024: ++ return lb << 1; ++ default: ++ return lb; ++ } ++} ++EXPORT_SYMBOL(target_to_linux_sector); ++ + int target_configure_device(struct se_device *dev) + { + struct se_hba *hba = dev->se_hba; +diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c +index b199f1e21d0e..6fe5b503f6e1 100644 +--- a/drivers/target/target_core_file.c ++++ b/drivers/target/target_core_file.c +@@ -164,25 +164,11 @@ static int fd_configure_device(struct se_device *dev) + " block_device blocks: %llu logical_block_size: %d\n", + dev_size, div_u64(dev_size, fd_dev->fd_block_size), + fd_dev->fd_block_size); +- /* +- * Check if the underlying struct block_device request_queue supports +- * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM +- * in ATA and we need to set TPE=1 +- */ +- if (blk_queue_discard(q)) { +- dev->dev_attrib.max_unmap_lba_count = +- q->limits.max_discard_sectors; +- /* +- * Currently hardcoded to 1 in Linux/SCSI code.. +- */ +- dev->dev_attrib.max_unmap_block_desc_count = 1; +- dev->dev_attrib.unmap_granularity = +- q->limits.discard_granularity >> 9; +- dev->dev_attrib.unmap_granularity_alignment = +- q->limits.discard_alignment; ++ ++ if (target_configure_unmap_from_queue(&dev->dev_attrib, q, ++ fd_dev->fd_block_size)) + pr_debug("IFILE: BLOCK Discard support available," +- " disabled by default\n"); +- } ++ " disabled by default\n"); + /* + * Enable write same emulation for IBLOCK and use 0xFFFF as + * the smaller WRITE_SAME(10) only has a two-byte block count. +@@ -545,9 +531,12 @@ fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb) + if (S_ISBLK(inode->i_mode)) { + /* The backend is block device, use discard */ + struct block_device *bdev = inode->i_bdev; ++ struct se_device *dev = cmd->se_dev; + +- ret = blkdev_issue_discard(bdev, lba, +- nolb, GFP_KERNEL, 0); ++ ret = blkdev_issue_discard(bdev, ++ target_to_linux_sector(dev, lba), ++ target_to_linux_sector(dev, nolb), ++ GFP_KERNEL, 0); + if (ret < 0) { + pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n", + ret); +diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c +index feefe24a88f7..357b9fb61499 100644 +--- a/drivers/target/target_core_iblock.c ++++ b/drivers/target/target_core_iblock.c +@@ -126,27 +126,11 @@ static int iblock_configure_device(struct se_device *dev) + dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); + dev->dev_attrib.hw_queue_depth = q->nr_requests; + +- /* +- * Check if the underlying struct block_device request_queue supports +- * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM +- * in ATA and we need to set TPE=1 +- */ +- if (blk_queue_discard(q)) { +- dev->dev_attrib.max_unmap_lba_count = +- q->limits.max_discard_sectors; +- +- /* +- * Currently hardcoded to 1 in Linux/SCSI code.. +- */ +- dev->dev_attrib.max_unmap_block_desc_count = 1; +- dev->dev_attrib.unmap_granularity = +- q->limits.discard_granularity >> 9; +- dev->dev_attrib.unmap_granularity_alignment = +- q->limits.discard_alignment; +- ++ if (target_configure_unmap_from_queue(&dev->dev_attrib, q, ++ dev->dev_attrib.hw_block_size)) + pr_debug("IBLOCK: BLOCK Discard support available," +- " disabled by default\n"); +- } ++ " disabled by default\n"); ++ + /* + * Enable write same emulation for IBLOCK and use 0xFFFF as + * the smaller WRITE_SAME(10) only has a two-byte block count. +@@ -418,9 +402,13 @@ iblock_do_unmap(struct se_cmd *cmd, void *priv, + sector_t lba, sector_t nolb) + { + struct block_device *bdev = priv; ++ struct se_device *dev = cmd->se_dev; + int ret; + +- ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0); ++ ret = blkdev_issue_discard(bdev, ++ target_to_linux_sector(dev, lba), ++ target_to_linux_sector(dev, nolb), ++ GFP_KERNEL, 0); + if (ret < 0) { + pr_err("blkdev_issue_discard() failed: %d\n", ret); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; +@@ -460,8 +448,10 @@ iblock_execute_write_same(struct se_cmd *cmd) + struct scatterlist *sg; + struct bio *bio; + struct bio_list list; +- sector_t block_lba = cmd->t_task_lba; +- sector_t sectors = sbc_get_write_same_sectors(cmd); ++ struct se_device *dev = cmd->se_dev; ++ sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba); ++ sector_t sectors = target_to_linux_sector(dev, ++ sbc_get_write_same_sectors(cmd)); + + sg = &cmd->t_data_sg[0]; + +@@ -670,12 +660,12 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + enum dma_data_direction data_direction) + { + struct se_device *dev = cmd->se_dev; ++ sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba); + struct iblock_req *ibr; + struct bio *bio, *bio_start; + struct bio_list list; + struct scatterlist *sg; + u32 sg_num = sgl_nents; +- sector_t block_lba; + unsigned bio_cnt; + int rw = 0; + int i; +@@ -701,24 +691,6 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + rw = READ; + } + +- /* +- * Convert the blocksize advertised to the initiator to the 512 byte +- * units unconditionally used by the Linux block layer. +- */ +- if (dev->dev_attrib.block_size == 4096) +- block_lba = (cmd->t_task_lba << 3); +- else if (dev->dev_attrib.block_size == 2048) +- block_lba = (cmd->t_task_lba << 2); +- else if (dev->dev_attrib.block_size == 1024) +- block_lba = (cmd->t_task_lba << 1); +- else if (dev->dev_attrib.block_size == 512) +- block_lba = cmd->t_task_lba; +- else { +- pr_err("Unsupported SCSI -> BLOCK LBA conversion:" +- " %u\n", dev->dev_attrib.block_size); +- return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; +- } +- + ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); + if (!ibr) + goto fail; +diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c +index 70c638f730af..47a90d631a90 100644 +--- a/drivers/target/target_core_tmr.c ++++ b/drivers/target/target_core_tmr.c +@@ -76,25 +76,29 @@ void core_tmr_release_req( + } + + spin_lock_irqsave(&dev->se_tmr_lock, flags); +- list_del(&tmr->tmr_list); ++ list_del_init(&tmr->tmr_list); + spin_unlock_irqrestore(&dev->se_tmr_lock, flags); + + kfree(tmr); + } + +-static void core_tmr_handle_tas_abort( +- struct se_node_acl *tmr_nacl, +- struct se_cmd *cmd, +- int tas) ++static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas) + { ++ unsigned long flags; ++ bool remove = true, send_tas; + /* + * TASK ABORTED status (TAS) bit support +- */ +- if ((tmr_nacl && +- (tmr_nacl == cmd->se_sess->se_node_acl)) || tas) ++ */ ++ spin_lock_irqsave(&cmd->t_state_lock, flags); ++ send_tas = (cmd->transport_state & CMD_T_TAS); ++ spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ ++ if (send_tas) { ++ remove = false; + transport_send_task_abort(cmd); ++ } + +- transport_cmd_finish_abort(cmd, 0); ++ transport_cmd_finish_abort(cmd, remove); + } + + static int target_check_cdb_and_preempt(struct list_head *list, +@@ -112,6 +116,47 @@ static int target_check_cdb_and_preempt(struct list_head *list, + return 1; + } + ++static bool __target_check_io_state(struct se_cmd *se_cmd, ++ struct se_session *tmr_sess, int tas) ++{ ++ struct se_session *sess = se_cmd->se_sess; ++ ++ assert_spin_locked(&sess->sess_cmd_lock); ++ WARN_ON_ONCE(!irqs_disabled()); ++ /* ++ * If command already reached CMD_T_COMPLETE state within ++ * target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown, ++ * this se_cmd has been passed to fabric driver and will ++ * not be aborted. ++ * ++ * Otherwise, obtain a local se_cmd->cmd_kref now for TMR ++ * ABORT_TASK + LUN_RESET for CMD_T_ABORTED processing as ++ * long as se_cmd->cmd_kref is still active unless zero. ++ */ ++ spin_lock(&se_cmd->t_state_lock); ++ if (se_cmd->transport_state & (CMD_T_COMPLETE | CMD_T_FABRIC_STOP)) { ++ pr_debug("Attempted to abort io tag: %u already complete or" ++ " fabric stop, skipping\n", ++ se_cmd->se_tfo->get_task_tag(se_cmd)); ++ spin_unlock(&se_cmd->t_state_lock); ++ return false; ++ } ++ if (sess->sess_tearing_down || se_cmd->cmd_wait_set) { ++ pr_debug("Attempted to abort io tag: %u already shutdown," ++ " skipping\n", se_cmd->se_tfo->get_task_tag(se_cmd)); ++ spin_unlock(&se_cmd->t_state_lock); ++ return false; ++ } ++ se_cmd->transport_state |= CMD_T_ABORTED; ++ ++ if ((tmr_sess != se_cmd->se_sess) && tas) ++ se_cmd->transport_state |= CMD_T_TAS; ++ ++ spin_unlock(&se_cmd->t_state_lock); ++ ++ return kref_get_unless_zero(&se_cmd->cmd_kref); ++} ++ + void core_tmr_abort_task( + struct se_device *dev, + struct se_tmr_req *tmr, +@@ -134,33 +179,19 @@ void core_tmr_abort_task( + printk("ABORT_TASK: Found referenced %s task_tag: %u\n", + se_cmd->se_tfo->get_fabric_name(), ref_tag); + +- spin_lock(&se_cmd->t_state_lock); +- if (se_cmd->transport_state & CMD_T_COMPLETE) { +- printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); +- spin_unlock(&se_cmd->t_state_lock); ++ if (!__target_check_io_state(se_cmd, se_sess, 0)) { + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); ++ target_put_sess_cmd(se_sess, se_cmd); + goto out; + } +- se_cmd->transport_state |= CMD_T_ABORTED; +- spin_unlock(&se_cmd->t_state_lock); + + list_del_init(&se_cmd->se_cmd_list); +- kref_get(&se_cmd->cmd_kref); + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + + cancel_work_sync(&se_cmd->work); + transport_wait_for_tasks(se_cmd); +- /* +- * Now send SAM_STAT_TASK_ABORTED status for the referenced +- * se_cmd descriptor.. +- */ +- transport_send_task_abort(se_cmd); +- /* +- * Also deal with possible extra acknowledge reference.. +- */ +- if (se_cmd->se_cmd_flags & SCF_ACK_KREF) +- target_put_sess_cmd(se_sess, se_cmd); + ++ transport_cmd_finish_abort(se_cmd, true); + target_put_sess_cmd(se_sess, se_cmd); + + printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" +@@ -182,9 +213,11 @@ static void core_tmr_drain_tmr_list( + struct list_head *preempt_and_abort_list) + { + LIST_HEAD(drain_tmr_list); ++ struct se_session *sess; + struct se_tmr_req *tmr_p, *tmr_pp; + struct se_cmd *cmd; + unsigned long flags; ++ bool rc; + /* + * Release all pending and outgoing TMRs aside from the received + * LUN_RESET tmr.. +@@ -210,17 +243,39 @@ static void core_tmr_drain_tmr_list( + if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd)) + continue; + ++ sess = cmd->se_sess; ++ if (WARN_ON_ONCE(!sess)) ++ continue; ++ ++ spin_lock(&sess->sess_cmd_lock); + spin_lock(&cmd->t_state_lock); +- if (!(cmd->transport_state & CMD_T_ACTIVE)) { ++ if (!(cmd->transport_state & CMD_T_ACTIVE) || ++ (cmd->transport_state & CMD_T_FABRIC_STOP)) { + spin_unlock(&cmd->t_state_lock); ++ spin_unlock(&sess->sess_cmd_lock); + continue; + } + if (cmd->t_state == TRANSPORT_ISTATE_PROCESSING) { + spin_unlock(&cmd->t_state_lock); ++ spin_unlock(&sess->sess_cmd_lock); + continue; + } ++ if (sess->sess_tearing_down || cmd->cmd_wait_set) { ++ spin_unlock(&cmd->t_state_lock); ++ spin_unlock(&sess->sess_cmd_lock); ++ continue; ++ } ++ cmd->transport_state |= CMD_T_ABORTED; + spin_unlock(&cmd->t_state_lock); + ++ rc = kref_get_unless_zero(&cmd->cmd_kref); ++ if (!rc) { ++ printk("LUN_RESET TMR: non-zero kref_get_unless_zero\n"); ++ spin_unlock(&sess->sess_cmd_lock); ++ continue; ++ } ++ spin_unlock(&sess->sess_cmd_lock); ++ + list_move_tail(&tmr_p->tmr_list, &drain_tmr_list); + } + spin_unlock_irqrestore(&dev->se_tmr_lock, flags); +@@ -234,20 +289,26 @@ static void core_tmr_drain_tmr_list( + (preempt_and_abort_list) ? "Preempt" : "", tmr_p, + tmr_p->function, tmr_p->response, cmd->t_state); + ++ cancel_work_sync(&cmd->work); ++ transport_wait_for_tasks(cmd); ++ + transport_cmd_finish_abort(cmd, 1); ++ target_put_sess_cmd(cmd->se_sess, cmd); + } + } + + static void core_tmr_drain_state_list( + struct se_device *dev, + struct se_cmd *prout_cmd, +- struct se_node_acl *tmr_nacl, ++ struct se_session *tmr_sess, + int tas, + struct list_head *preempt_and_abort_list) + { + LIST_HEAD(drain_task_list); ++ struct se_session *sess; + struct se_cmd *cmd, *next; + unsigned long flags; ++ int rc; + + /* + * Complete outstanding commands with TASK_ABORTED SAM status. +@@ -286,6 +347,16 @@ static void core_tmr_drain_state_list( + if (prout_cmd == cmd) + continue; + ++ sess = cmd->se_sess; ++ if (WARN_ON_ONCE(!sess)) ++ continue; ++ ++ spin_lock(&sess->sess_cmd_lock); ++ rc = __target_check_io_state(cmd, tmr_sess, tas); ++ spin_unlock(&sess->sess_cmd_lock); ++ if (!rc) ++ continue; ++ + list_move_tail(&cmd->state_list, &drain_task_list); + cmd->state_active = false; + } +@@ -293,7 +364,7 @@ static void core_tmr_drain_state_list( + + while (!list_empty(&drain_task_list)) { + cmd = list_entry(drain_task_list.next, struct se_cmd, state_list); +- list_del(&cmd->state_list); ++ list_del_init(&cmd->state_list); + + pr_debug("LUN_RESET: %s cmd: %p" + " ITT/CmdSN: 0x%08x/0x%08x, i_state: %d, t_state: %d" +@@ -317,16 +388,11 @@ static void core_tmr_drain_state_list( + * loop above, but we do it down here given that + * cancel_work_sync may block. + */ +- if (cmd->t_state == TRANSPORT_COMPLETE) +- cancel_work_sync(&cmd->work); +- +- spin_lock_irqsave(&cmd->t_state_lock, flags); +- target_stop_cmd(cmd, &flags); +- +- cmd->transport_state |= CMD_T_ABORTED; +- spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ cancel_work_sync(&cmd->work); ++ transport_wait_for_tasks(cmd); + +- core_tmr_handle_tas_abort(tmr_nacl, cmd, tas); ++ core_tmr_handle_tas_abort(cmd, tas); ++ target_put_sess_cmd(cmd->se_sess, cmd); + } + } + +@@ -338,6 +404,7 @@ int core_tmr_lun_reset( + { + struct se_node_acl *tmr_nacl = NULL; + struct se_portal_group *tmr_tpg = NULL; ++ struct se_session *tmr_sess = NULL; + int tas; + /* + * TASK_ABORTED status bit, this is configurable via ConfigFS +@@ -356,8 +423,9 @@ int core_tmr_lun_reset( + * or struct se_device passthrough.. + */ + if (tmr && tmr->task_cmd && tmr->task_cmd->se_sess) { +- tmr_nacl = tmr->task_cmd->se_sess->se_node_acl; +- tmr_tpg = tmr->task_cmd->se_sess->se_tpg; ++ tmr_sess = tmr->task_cmd->se_sess; ++ tmr_nacl = tmr_sess->se_node_acl; ++ tmr_tpg = tmr_sess->se_tpg; + if (tmr_nacl && tmr_tpg) { + pr_debug("LUN_RESET: TMR caller fabric: %s" + " initiator port %s\n", +@@ -370,7 +438,7 @@ int core_tmr_lun_reset( + dev->transport->name, tas); + + core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list); +- core_tmr_drain_state_list(dev, prout_cmd, tmr_nacl, tas, ++ core_tmr_drain_state_list(dev, prout_cmd, tmr_sess, tas, + preempt_and_abort_list); + + /* +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index 7afea9b59e2c..cbf927a67160 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -509,9 +509,6 @@ void transport_deregister_session(struct se_session *se_sess) + } + EXPORT_SYMBOL(transport_deregister_session); + +-/* +- * Called with cmd->t_state_lock held. +- */ + static void target_remove_from_state_list(struct se_cmd *cmd) + { + struct se_device *dev = cmd->se_dev; +@@ -536,10 +533,6 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists, + { + unsigned long flags; + +- spin_lock_irqsave(&cmd->t_state_lock, flags); +- if (write_pending) +- cmd->t_state = TRANSPORT_WRITE_PENDING; +- + if (remove_from_lists) { + target_remove_from_state_list(cmd); + +@@ -549,6 +542,10 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists, + cmd->se_lun = NULL; + } + ++ spin_lock_irqsave(&cmd->t_state_lock, flags); ++ if (write_pending) ++ cmd->t_state = TRANSPORT_WRITE_PENDING; ++ + /* + * Determine if frontend context caller is requesting the stopping of + * this command for frontend exceptions. +@@ -603,9 +600,20 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) + + void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) + { ++ bool ack_kref = (cmd->se_cmd_flags & SCF_ACK_KREF); ++ ++ if (cmd->se_cmd_flags & SCF_SE_LUN_CMD) ++ transport_lun_remove_cmd(cmd); ++ /* ++ * Allow the fabric driver to unmap any resources before ++ * releasing the descriptor via TFO->release_cmd() ++ */ ++ if (remove) ++ cmd->se_tfo->aborted_task(cmd); ++ + if (transport_cmd_check_stop_to_fabric(cmd)) + return; +- if (remove) ++ if (remove && ack_kref) + transport_put_cmd(cmd); + } + +@@ -673,7 +681,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) + * Check for case where an explicit ABORT_TASK has been received + * and transport_wait_for_tasks() will be waiting for completion.. + */ +- if (cmd->transport_state & CMD_T_ABORTED && ++ if (cmd->transport_state & CMD_T_ABORTED || + cmd->transport_state & CMD_T_STOP) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + complete_all(&cmd->t_transport_stop_comp); +@@ -1746,19 +1754,21 @@ static bool target_handle_task_attr(struct se_cmd *cmd) + return true; + } + ++static int __transport_check_aborted_status(struct se_cmd *, int); ++ + void target_execute_cmd(struct se_cmd *cmd) + { + /* +- * If the received CDB has aleady been aborted stop processing it here. +- */ +- if (transport_check_aborted_status(cmd, 1)) +- return; +- +- /* + * Determine if frontend context caller is requesting the stopping of + * this command for frontend exceptions. ++ * ++ * If the received CDB has aleady been aborted stop processing it here. + */ + spin_lock_irq(&cmd->t_state_lock); ++ if (__transport_check_aborted_status(cmd, 1)) { ++ spin_unlock_irq(&cmd->t_state_lock); ++ return; ++ } + if (cmd->transport_state & CMD_T_STOP) { + pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n", + __func__, __LINE__, +@@ -2076,20 +2086,14 @@ static inline void transport_free_pages(struct se_cmd *cmd) + } + + /** +- * transport_release_cmd - free a command +- * @cmd: command to free ++ * transport_put_cmd - release a reference to a command ++ * @cmd: command to release + * +- * This routine unconditionally frees a command, and reference counting +- * or list removal must be done in the caller. ++ * This routine releases our reference to the command and frees it if possible. + */ +-static int transport_release_cmd(struct se_cmd *cmd) ++static int transport_put_cmd(struct se_cmd *cmd) + { + BUG_ON(!cmd->se_tfo); +- +- if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) +- core_tmr_release_req(cmd->se_tmr_req); +- if (cmd->t_task_cdb != cmd->__t_task_cdb) +- kfree(cmd->t_task_cdb); + /* + * If this cmd has been setup with target_get_sess_cmd(), drop + * the kref and call ->release_cmd() in kref callback. +@@ -2097,18 +2101,6 @@ static int transport_release_cmd(struct se_cmd *cmd) + return target_put_sess_cmd(cmd->se_sess, cmd); + } + +-/** +- * transport_put_cmd - release a reference to a command +- * @cmd: command to release +- * +- * This routine releases our reference to the command and frees it if possible. +- */ +-static int transport_put_cmd(struct se_cmd *cmd) +-{ +- transport_free_pages(cmd); +- return transport_release_cmd(cmd); +-} +- + void *transport_kmap_data_sg(struct se_cmd *cmd) + { + struct scatterlist *sg = cmd->t_data_sg; +@@ -2296,34 +2288,59 @@ static void transport_write_pending_qf(struct se_cmd *cmd) + } + } + +-int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) ++static bool ++__transport_wait_for_tasks(struct se_cmd *, bool, bool *, bool *, ++ unsigned long *flags); ++ ++static void target_wait_free_cmd(struct se_cmd *cmd, bool *aborted, bool *tas) + { + unsigned long flags; ++ ++ spin_lock_irqsave(&cmd->t_state_lock, flags); ++ __transport_wait_for_tasks(cmd, true, aborted, tas, &flags); ++ spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++} ++ ++int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) ++{ + int ret = 0; ++ bool aborted = false, tas = false; + + if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) { + if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) +- transport_wait_for_tasks(cmd); ++ target_wait_free_cmd(cmd, &aborted, &tas); + +- ret = transport_release_cmd(cmd); ++ if (!aborted || tas) ++ ret = transport_put_cmd(cmd); + } else { + if (wait_for_tasks) +- transport_wait_for_tasks(cmd); ++ target_wait_free_cmd(cmd, &aborted, &tas); + /* + * Handle WRITE failure case where transport_generic_new_cmd() + * has already added se_cmd to state_list, but fabric has + * failed command before I/O submission. + */ +- if (cmd->state_active) { +- spin_lock_irqsave(&cmd->t_state_lock, flags); ++ if (cmd->state_active) + target_remove_from_state_list(cmd); +- spin_unlock_irqrestore(&cmd->t_state_lock, flags); +- } + + if (cmd->se_lun) + transport_lun_remove_cmd(cmd); + +- ret = transport_put_cmd(cmd); ++ if (!aborted || tas) ++ ret = transport_put_cmd(cmd); ++ } ++ /* ++ * If the task has been internally aborted due to TMR ABORT_TASK ++ * or LUN_RESET, target_core_tmr.c is responsible for performing ++ * the remaining calls to target_put_sess_cmd(), and not the ++ * callers of this function. ++ */ ++ if (aborted) { ++ pr_debug("Detected CMD_T_ABORTED for ITT: %u\n", ++ cmd->se_tfo->get_task_tag(cmd)); ++ wait_for_completion(&cmd->cmd_wait_comp); ++ cmd->se_tfo->release_cmd(cmd); ++ ret = 1; + } + return ret; + } +@@ -2366,24 +2383,44 @@ out: + } + EXPORT_SYMBOL(target_get_sess_cmd); + ++static void target_free_cmd_mem(struct se_cmd *cmd) ++{ ++ transport_free_pages(cmd); ++ ++ if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) ++ core_tmr_release_req(cmd->se_tmr_req); ++ if (cmd->t_task_cdb != cmd->__t_task_cdb) ++ kfree(cmd->t_task_cdb); ++} ++ + static void target_release_cmd_kref(struct kref *kref) + { + struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref); + struct se_session *se_sess = se_cmd->se_sess; ++ bool fabric_stop; + + if (list_empty(&se_cmd->se_cmd_list)) { + spin_unlock(&se_sess->sess_cmd_lock); ++ target_free_cmd_mem(se_cmd); + se_cmd->se_tfo->release_cmd(se_cmd); + return; + } +- if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) { ++ ++ spin_lock(&se_cmd->t_state_lock); ++ fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP); ++ spin_unlock(&se_cmd->t_state_lock); ++ ++ if (se_cmd->cmd_wait_set || fabric_stop) { ++ list_del_init(&se_cmd->se_cmd_list); + spin_unlock(&se_sess->sess_cmd_lock); ++ target_free_cmd_mem(se_cmd); + complete(&se_cmd->cmd_wait_comp); + return; + } +- list_del(&se_cmd->se_cmd_list); ++ list_del_init(&se_cmd->se_cmd_list); + spin_unlock(&se_sess->sess_cmd_lock); + ++ target_free_cmd_mem(se_cmd); + se_cmd->se_tfo->release_cmd(se_cmd); + } + +@@ -2394,6 +2431,7 @@ static void target_release_cmd_kref(struct kref *kref) + int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd) + { + if (!se_sess) { ++ target_free_cmd_mem(se_cmd); + se_cmd->se_tfo->release_cmd(se_cmd); + return 1; + } +@@ -2411,6 +2449,7 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess) + { + struct se_cmd *se_cmd; + unsigned long flags; ++ int rc; + + spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); + if (se_sess->sess_tearing_down) { +@@ -2420,8 +2459,15 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess) + se_sess->sess_tearing_down = 1; + list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list); + +- list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) +- se_cmd->cmd_wait_set = 1; ++ list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) { ++ rc = kref_get_unless_zero(&se_cmd->cmd_kref); ++ if (rc) { ++ se_cmd->cmd_wait_set = 1; ++ spin_lock(&se_cmd->t_state_lock); ++ se_cmd->transport_state |= CMD_T_FABRIC_STOP; ++ spin_unlock(&se_cmd->t_state_lock); ++ } ++ } + + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + } +@@ -2434,15 +2480,25 @@ void target_wait_for_sess_cmds(struct se_session *se_sess) + { + struct se_cmd *se_cmd, *tmp_cmd; + unsigned long flags; ++ bool tas; + + list_for_each_entry_safe(se_cmd, tmp_cmd, + &se_sess->sess_wait_list, se_cmd_list) { +- list_del(&se_cmd->se_cmd_list); ++ list_del_init(&se_cmd->se_cmd_list); + + pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:" + " %d\n", se_cmd, se_cmd->t_state, + se_cmd->se_tfo->get_cmd_state(se_cmd)); + ++ spin_lock_irqsave(&se_cmd->t_state_lock, flags); ++ tas = (se_cmd->transport_state & CMD_T_TAS); ++ spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); ++ ++ if (!target_put_sess_cmd(se_sess, se_cmd)) { ++ if (tas) ++ target_put_sess_cmd(se_sess, se_cmd); ++ } ++ + wait_for_completion(&se_cmd->cmd_wait_comp); + pr_debug("After cmd_wait_comp: se_cmd: %p t_state: %d" + " fabric state: %d\n", se_cmd, se_cmd->t_state, +@@ -2485,34 +2541,38 @@ int transport_clear_lun_ref(struct se_lun *lun) + return 0; + } + +-/** +- * transport_wait_for_tasks - wait for completion to occur +- * @cmd: command to wait +- * +- * Called from frontend fabric context to wait for storage engine +- * to pause and/or release frontend generated struct se_cmd. +- */ +-bool transport_wait_for_tasks(struct se_cmd *cmd) ++static bool ++__transport_wait_for_tasks(struct se_cmd *cmd, bool fabric_stop, ++ bool *aborted, bool *tas, unsigned long *flags) ++ __releases(&cmd->t_state_lock) ++ __acquires(&cmd->t_state_lock) + { +- unsigned long flags; + +- spin_lock_irqsave(&cmd->t_state_lock, flags); ++ assert_spin_locked(&cmd->t_state_lock); ++ WARN_ON_ONCE(!irqs_disabled()); ++ ++ if (fabric_stop) ++ cmd->transport_state |= CMD_T_FABRIC_STOP; ++ ++ if (cmd->transport_state & CMD_T_ABORTED) ++ *aborted = true; ++ ++ if (cmd->transport_state & CMD_T_TAS) ++ *tas = true; ++ + if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD) && +- !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) { +- spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) + return false; +- } + + if (!(cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) && +- !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) { +- spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) + return false; +- } + +- if (!(cmd->transport_state & CMD_T_ACTIVE)) { +- spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ if (!(cmd->transport_state & CMD_T_ACTIVE)) ++ return false; ++ ++ if (fabric_stop && *aborted) + return false; +- } + + cmd->transport_state |= CMD_T_STOP; + +@@ -2521,20 +2581,37 @@ bool transport_wait_for_tasks(struct se_cmd *cmd) + cmd, cmd->se_tfo->get_task_tag(cmd), + cmd->se_tfo->get_cmd_state(cmd), cmd->t_state); + +- spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ spin_unlock_irqrestore(&cmd->t_state_lock, *flags); + + wait_for_completion(&cmd->t_transport_stop_comp); + +- spin_lock_irqsave(&cmd->t_state_lock, flags); ++ spin_lock_irqsave(&cmd->t_state_lock, *flags); + cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP); + + pr_debug("wait_for_tasks: Stopped wait_for_completion(" + "&cmd->t_transport_stop_comp) for ITT: 0x%08x\n", + cmd->se_tfo->get_task_tag(cmd)); + ++ return true; ++} ++ ++/** ++ * transport_wait_for_tasks - wait for completion to occur ++ * @cmd: command to wait ++ * ++ * Called from frontend fabric context to wait for storage engine ++ * to pause and/or release frontend generated struct se_cmd. ++ */ ++bool transport_wait_for_tasks(struct se_cmd *cmd) ++{ ++ unsigned long flags; ++ bool ret, aborted = false, tas = false; ++ ++ spin_lock_irqsave(&cmd->t_state_lock, flags); ++ ret = __transport_wait_for_tasks(cmd, false, &aborted, &tas, &flags); + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + +- return true; ++ return ret; + } + EXPORT_SYMBOL(transport_wait_for_tasks); + +@@ -2820,24 +2897,51 @@ after_reason: + } + EXPORT_SYMBOL(transport_send_check_condition_and_sense); + +-int transport_check_aborted_status(struct se_cmd *cmd, int send_status) ++static int __transport_check_aborted_status(struct se_cmd *cmd, int send_status) ++ __releases(&cmd->t_state_lock) ++ __acquires(&cmd->t_state_lock) + { ++ assert_spin_locked(&cmd->t_state_lock); ++ WARN_ON_ONCE(!irqs_disabled()); ++ + if (!(cmd->transport_state & CMD_T_ABORTED)) + return 0; + +- if (!send_status || (cmd->se_cmd_flags & SCF_SENT_DELAYED_TAS)) ++ /* ++ * If cmd has been aborted but either no status is to be sent or it has ++ * already been sent, just return ++ */ ++ if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS)) { ++ if (send_status) ++ cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS; + return 1; ++ } + +- pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08x\n", +- cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); ++ pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB:" ++ " 0x%02x ITT: 0x%08x\n", cmd->t_task_cdb[0], ++ cmd->se_tfo->get_task_tag(cmd)); + +- cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS; ++ cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS; + cmd->scsi_status = SAM_STAT_TASK_ABORTED; + trace_target_cmd_complete(cmd); ++ ++ spin_unlock_irq(&cmd->t_state_lock); + cmd->se_tfo->queue_status(cmd); ++ spin_lock_irq(&cmd->t_state_lock); + + return 1; + } ++ ++int transport_check_aborted_status(struct se_cmd *cmd, int send_status) ++{ ++ int ret; ++ ++ spin_lock_irq(&cmd->t_state_lock); ++ ret = __transport_check_aborted_status(cmd, send_status); ++ spin_unlock_irq(&cmd->t_state_lock); ++ ++ return ret; ++} + EXPORT_SYMBOL(transport_check_aborted_status); + + void transport_send_task_abort(struct se_cmd *cmd) +@@ -2845,7 +2949,7 @@ void transport_send_task_abort(struct se_cmd *cmd) + unsigned long flags; + + spin_lock_irqsave(&cmd->t_state_lock, flags); +- if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION | SCF_SENT_DELAYED_TAS)) { ++ if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION)) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return; + } +@@ -2859,11 +2963,17 @@ void transport_send_task_abort(struct se_cmd *cmd) + */ + if (cmd->data_direction == DMA_TO_DEVICE) { + if (cmd->se_tfo->write_pending_status(cmd) != 0) { +- cmd->transport_state |= CMD_T_ABORTED; +- smp_mb__after_atomic_inc(); ++ spin_lock_irqsave(&cmd->t_state_lock, flags); ++ if (cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS) { ++ spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ goto send_abort; ++ } ++ cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS; ++ spin_unlock_irqrestore(&cmd->t_state_lock, flags); + return; + } + } ++send_abort: + cmd->scsi_status = SAM_STAT_TASK_ABORTED; + + transport_lun_remove_cmd(cmd); +@@ -2881,8 +2991,17 @@ static void target_tmr_work(struct work_struct *work) + struct se_cmd *cmd = container_of(work, struct se_cmd, work); + struct se_device *dev = cmd->se_dev; + struct se_tmr_req *tmr = cmd->se_tmr_req; ++ unsigned long flags; + int ret; + ++ spin_lock_irqsave(&cmd->t_state_lock, flags); ++ if (cmd->transport_state & CMD_T_ABORTED) { ++ tmr->response = TMR_FUNCTION_REJECTED; ++ spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ goto check_stop; ++ } ++ spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ + switch (tmr->function) { + case TMR_ABORT_TASK: + core_tmr_abort_task(dev, tmr, cmd->se_sess); +@@ -2910,9 +3029,17 @@ static void target_tmr_work(struct work_struct *work) + break; + } + ++ spin_lock_irqsave(&cmd->t_state_lock, flags); ++ if (cmd->transport_state & CMD_T_ABORTED) { ++ spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ goto check_stop; ++ } + cmd->t_state = TRANSPORT_ISTATE_PROCESSING; ++ spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ + cmd->se_tfo->queue_tm_rsp(cmd); + ++check_stop: + transport_cmd_check_stop_to_fabric(cmd); + } + +diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h +index 752863acecb8..4f4b97161228 100644 +--- a/drivers/target/tcm_fc/tcm_fc.h ++++ b/drivers/target/tcm_fc/tcm_fc.h +@@ -163,6 +163,7 @@ int ft_write_pending_status(struct se_cmd *); + u32 ft_get_task_tag(struct se_cmd *); + int ft_get_cmd_state(struct se_cmd *); + void ft_queue_tm_resp(struct se_cmd *); ++void ft_aborted_task(struct se_cmd *); + + /* + * other internal functions. +diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c +index d22cdc77e9d4..f5fd515b2bee 100644 +--- a/drivers/target/tcm_fc/tfc_cmd.c ++++ b/drivers/target/tcm_fc/tfc_cmd.c +@@ -426,6 +426,11 @@ void ft_queue_tm_resp(struct se_cmd *se_cmd) + ft_send_resp_code(cmd, code); + } + ++void ft_aborted_task(struct se_cmd *se_cmd) ++{ ++ return; ++} ++ + static void ft_send_work(struct work_struct *work); + + /* +diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c +index e879da81ad93..b8b5a719a784 100644 +--- a/drivers/target/tcm_fc/tfc_conf.c ++++ b/drivers/target/tcm_fc/tfc_conf.c +@@ -536,6 +536,7 @@ static struct target_core_fabric_ops ft_fabric_ops = { + .queue_data_in = ft_queue_data_in, + .queue_status = ft_queue_status, + .queue_tm_rsp = ft_queue_tm_resp, ++ .aborted_task = ft_aborted_task, + /* + * Setup function pointers for generic logic in + * target_core_fabric_configfs.c +diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c +index 39bd7ec8bf75..f66a14b6fc73 100644 +--- a/drivers/usb/chipidea/otg.c ++++ b/drivers/usb/chipidea/otg.c +@@ -96,7 +96,7 @@ static void ci_otg_work(struct work_struct *work) + int ci_hdrc_otg_init(struct ci_hdrc *ci) + { + INIT_WORK(&ci->work, ci_otg_work); +- ci->wq = create_singlethread_workqueue("ci_otg"); ++ ci->wq = create_freezable_workqueue("ci_otg"); + if (!ci->wq) { + dev_err(ci->dev, "can't create workqueue\n"); + return -ENODEV; +diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c +index 460c266b8e24..cdec2492ff40 100644 +--- a/drivers/usb/gadget/tcm_usb_gadget.c ++++ b/drivers/usb/gadget/tcm_usb_gadget.c +@@ -1471,6 +1471,11 @@ static void usbg_queue_tm_rsp(struct se_cmd *se_cmd) + { + } + ++static void usbg_aborted_task(struct se_cmd *se_cmd) ++{ ++ return; ++} ++ + static const char *usbg_check_wwn(const char *name) + { + const char *n; +@@ -1897,6 +1902,7 @@ static struct target_core_fabric_ops usbg_ops = { + .queue_data_in = usbg_send_read_response, + .queue_status = usbg_send_status_response, + .queue_tm_rsp = usbg_queue_tm_rsp, ++ .aborted_task = usbg_aborted_task, + .check_stop_free = usbg_check_stop_free, + + .fabric_make_wwn = usbg_make_tport, +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 21bf168981f9..922723edd6b0 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -164,6 +164,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */ + { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ + { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ ++ { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ + { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ + { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ + { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */ +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 9bab34cf01d4..24366a2afea6 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -271,6 +271,7 @@ static void option_instat_callback(struct urb *urb); + #define TELIT_PRODUCT_UE910_V2 0x1012 + #define TELIT_PRODUCT_LE922_USBCFG0 0x1042 + #define TELIT_PRODUCT_LE922_USBCFG3 0x1043 ++#define TELIT_PRODUCT_LE922_USBCFG5 0x1045 + #define TELIT_PRODUCT_LE920 0x1200 + #define TELIT_PRODUCT_LE910 0x1201 + +@@ -1140,6 +1141,8 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ ++ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */ ++ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003), +@@ -1191,6 +1194,8 @@ static const struct usb_device_id option_ids[] = { + .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3), + .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff), ++ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), + .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index 6aeea1936aea..8f48f2bf34d4 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -539,6 +539,11 @@ static void tcm_vhost_queue_tm_rsp(struct se_cmd *se_cmd) + return; + } + ++static void tcm_vhost_aborted_task(struct se_cmd *se_cmd) ++{ ++ return; ++} ++ + static void tcm_vhost_free_evt(struct vhost_scsi *vs, struct tcm_vhost_evt *evt) + { + vs->vs_events_nr--; +@@ -2173,6 +2178,7 @@ static struct target_core_fabric_ops tcm_vhost_ops = { + .queue_data_in = tcm_vhost_queue_data_in, + .queue_status = tcm_vhost_queue_status, + .queue_tm_rsp = tcm_vhost_queue_tm_rsp, ++ .aborted_task = tcm_vhost_aborted_task, + /* + * Setup callers for generic logic in target_core_fabric_configfs.c + */ +diff --git a/fs/bio.c b/fs/bio.c +index b2b1451912b5..6d8cf434bf94 100644 +--- a/fs/bio.c ++++ b/fs/bio.c +@@ -1096,9 +1096,12 @@ int bio_uncopy_user(struct bio *bio) + ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs, + bio_data_dir(bio) == READ, + 0, bmd->is_our_pages); +- else if (bmd->is_our_pages) +- bio_for_each_segment_all(bvec, bio, i) +- __free_page(bvec->bv_page); ++ else { ++ ret = -EINTR; ++ if (bmd->is_our_pages) ++ bio_for_each_segment_all(bvec, bio, i) ++ __free_page(bvec->bv_page); ++ } + } + kfree(bmd); + bio_put(bio); +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index f3264bd7a83d..3f709ab0223b 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -1399,11 +1399,10 @@ openRetry: + * current bigbuf. + */ + static int +-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) ++discard_remaining_data(struct TCP_Server_Info *server) + { + unsigned int rfclen = get_rfc1002_length(server->smallbuf); + int remaining = rfclen + 4 - server->total_read; +- struct cifs_readdata *rdata = mid->callback_data; + + while (remaining > 0) { + int length; +@@ -1417,10 +1416,20 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) + remaining -= length; + } + +- dequeue_mid(mid, rdata->result); + return 0; + } + ++static int ++cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) ++{ ++ int length; ++ struct cifs_readdata *rdata = mid->callback_data; ++ ++ length = discard_remaining_data(server); ++ dequeue_mid(mid, rdata->result); ++ return length; ++} ++ + int + cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) + { +@@ -1449,6 +1458,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) + return length; + server->total_read += length; + ++ if (server->ops->is_status_pending && ++ server->ops->is_status_pending(buf, server, 0)) { ++ discard_remaining_data(server); ++ return -1; ++ } ++ + /* Was the SMB read successful? */ + rdata->result = server->ops->map_error(buf, false); + if (rdata->result != 0) { +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 348792911e1f..ae375dff03da 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1004,21 +1004,25 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, + { + char *data_offset; + struct create_context *cc; +- unsigned int next = 0; ++ unsigned int next; ++ unsigned int remaining; + char *name; + + data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset); ++ remaining = le32_to_cpu(rsp->CreateContextsLength); + cc = (struct create_context *)data_offset; +- do { +- cc = (struct create_context *)((char *)cc + next); ++ while (remaining >= sizeof(struct create_context)) { + name = le16_to_cpu(cc->NameOffset) + (char *)cc; +- if (le16_to_cpu(cc->NameLength) != 4 || +- strncmp(name, "RqLs", 4)) { +- next = le32_to_cpu(cc->Next); +- continue; +- } +- return server->ops->parse_lease_buf(cc, epoch); +- } while (next != 0); ++ if (le16_to_cpu(cc->NameLength) == 4 && ++ strncmp(name, "RqLs", 4) == 0) ++ return server->ops->parse_lease_buf(cc, epoch); ++ ++ next = le32_to_cpu(cc->Next); ++ if (!next) ++ break; ++ remaining -= next; ++ cc = (struct create_context *)((char *)cc + next); ++ } + + return 0; + } +diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking +index 3ea36554107f..8918ac905a3b 100644 +--- a/fs/jffs2/README.Locking ++++ b/fs/jffs2/README.Locking +@@ -2,10 +2,6 @@ + JFFS2 LOCKING DOCUMENTATION + --------------------------- + +-At least theoretically, JFFS2 does not require the Big Kernel Lock +-(BKL), which was always helpfully obtained for it by Linux 2.4 VFS +-code. It has its own locking, as described below. +- + This document attempts to describe the existing locking rules for + JFFS2. It is not expected to remain perfectly up to date, but ought to + be fairly close. +@@ -69,6 +65,7 @@ Ordering constraints: + any f->sem held. + 2. Never attempt to lock two file mutexes in one thread. + No ordering rules have been made for doing so. ++ 3. Never lock a page cache page with f->sem held. + + + erase_completion_lock spinlock +diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c +index a3750f902adc..c1f04947d7dc 100644 +--- a/fs/jffs2/build.c ++++ b/fs/jffs2/build.c +@@ -49,7 +49,8 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c) + + + static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, +- struct jffs2_inode_cache *ic) ++ struct jffs2_inode_cache *ic, ++ int *dir_hardlinks) + { + struct jffs2_full_dirent *fd; + +@@ -68,19 +69,21 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, + dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", + fd->name, fd->ino, ic->ino); + jffs2_mark_node_obsolete(c, fd->raw); ++ /* Clear the ic/raw union so it doesn't cause problems later. */ ++ fd->ic = NULL; + continue; + } + ++ /* From this point, fd->raw is no longer used so we can set fd->ic */ ++ fd->ic = child_ic; ++ child_ic->pino_nlink++; ++ /* If we appear (at this stage) to have hard-linked directories, ++ * set a flag to trigger a scan later */ + if (fd->type == DT_DIR) { +- if (child_ic->pino_nlink) { +- JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", +- fd->name, fd->ino, ic->ino); +- /* TODO: What do we do about it? */ +- } else { +- child_ic->pino_nlink = ic->ino; +- } +- } else +- child_ic->pino_nlink++; ++ child_ic->flags |= INO_FLAGS_IS_DIR; ++ if (child_ic->pino_nlink > 1) ++ *dir_hardlinks = 1; ++ } + + dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino); + /* Can't free scan_dents so far. We might need them in pass 2 */ +@@ -94,8 +97,7 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, + */ + static int jffs2_build_filesystem(struct jffs2_sb_info *c) + { +- int ret; +- int i; ++ int ret, i, dir_hardlinks = 0; + struct jffs2_inode_cache *ic; + struct jffs2_full_dirent *fd; + struct jffs2_full_dirent *dead_fds = NULL; +@@ -119,7 +121,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) + /* Now scan the directory tree, increasing nlink according to every dirent found. */ + for_each_inode(i, c, ic) { + if (ic->scan_dents) { +- jffs2_build_inode_pass1(c, ic); ++ jffs2_build_inode_pass1(c, ic, &dir_hardlinks); + cond_resched(); + } + } +@@ -155,6 +157,20 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) + } + + dbg_fsbuild("pass 2a complete\n"); ++ ++ if (dir_hardlinks) { ++ /* If we detected directory hardlinks earlier, *hopefully* ++ * they are gone now because some of the links were from ++ * dead directories which still had some old dirents lying ++ * around and not yet garbage-collected, but which have ++ * been discarded above. So clear the pino_nlink field ++ * in each directory, so that the final scan below can ++ * print appropriate warnings. */ ++ for_each_inode(i, c, ic) { ++ if (ic->flags & INO_FLAGS_IS_DIR) ++ ic->pino_nlink = 0; ++ } ++ } + dbg_fsbuild("freeing temporary data structures\n"); + + /* Finally, we can scan again and free the dirent structs */ +@@ -162,6 +178,33 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) + while(ic->scan_dents) { + fd = ic->scan_dents; + ic->scan_dents = fd->next; ++ /* We do use the pino_nlink field to count nlink of ++ * directories during fs build, so set it to the ++ * parent ino# now. Now that there's hopefully only ++ * one. */ ++ if (fd->type == DT_DIR) { ++ if (!fd->ic) { ++ /* We'll have complained about it and marked the coresponding ++ raw node obsolete already. Just skip it. */ ++ continue; ++ } ++ ++ /* We *have* to have set this in jffs2_build_inode_pass1() */ ++ BUG_ON(!(fd->ic->flags & INO_FLAGS_IS_DIR)); ++ ++ /* We clear ic->pino_nlink ∀ directories' ic *only* if dir_hardlinks ++ * is set. Otherwise, we know this should never trigger anyway, so ++ * we don't do the check. And ic->pino_nlink still contains the nlink ++ * value (which is 1). */ ++ if (dir_hardlinks && fd->ic->pino_nlink) { ++ JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u is also hard linked from dir ino #%u\n", ++ fd->name, fd->ino, ic->ino, fd->ic->pino_nlink); ++ /* Should we unlink it from its previous parent? */ ++ } ++ ++ /* For directories, ic->pino_nlink holds that parent inode # */ ++ fd->ic->pino_nlink = ic->ino; ++ } + jffs2_free_full_dirent(fd); + } + ic->scan_dents = NULL; +@@ -240,11 +283,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, + + /* Reduce nlink of the child. If it's now zero, stick it on the + dead_fds list to be cleaned up later. Else just free the fd */ +- +- if (fd->type == DT_DIR) +- child_ic->pino_nlink = 0; +- else +- child_ic->pino_nlink--; ++ child_ic->pino_nlink--; + + if (!child_ic->pino_nlink) { + dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n", +diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c +index 256cd19a3b78..d2570ae2e998 100644 +--- a/fs/jffs2/file.c ++++ b/fs/jffs2/file.c +@@ -139,39 +139,33 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, + struct page *pg; + struct inode *inode = mapping->host; + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); +- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); +- struct jffs2_raw_inode ri; +- uint32_t alloc_len = 0; + pgoff_t index = pos >> PAGE_CACHE_SHIFT; + uint32_t pageofs = index << PAGE_CACHE_SHIFT; + int ret = 0; + +- jffs2_dbg(1, "%s()\n", __func__); +- +- if (pageofs > inode->i_size) { +- ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, +- ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); +- if (ret) +- return ret; +- } +- +- mutex_lock(&f->sem); + pg = grab_cache_page_write_begin(mapping, index, flags); +- if (!pg) { +- if (alloc_len) +- jffs2_complete_reservation(c); +- mutex_unlock(&f->sem); ++ if (!pg) + return -ENOMEM; +- } + *pagep = pg; + +- if (alloc_len) { ++ jffs2_dbg(1, "%s()\n", __func__); ++ ++ if (pageofs > inode->i_size) { + /* Make new hole frag from old EOF to new page */ ++ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); ++ struct jffs2_raw_inode ri; + struct jffs2_full_dnode *fn; ++ uint32_t alloc_len; + + jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", + (unsigned int)inode->i_size, pageofs); + ++ ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, ++ ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); ++ if (ret) ++ goto out_page; ++ ++ mutex_lock(&f->sem); + memset(&ri, 0, sizeof(ri)); + + ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); +@@ -198,6 +192,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, + if (IS_ERR(fn)) { + ret = PTR_ERR(fn); + jffs2_complete_reservation(c); ++ mutex_unlock(&f->sem); + goto out_page; + } + ret = jffs2_add_full_dnode_to_inode(c, f, fn); +@@ -212,10 +207,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, + jffs2_mark_node_obsolete(c, fn->raw); + jffs2_free_full_dnode(fn); + jffs2_complete_reservation(c); ++ mutex_unlock(&f->sem); + goto out_page; + } + jffs2_complete_reservation(c); + inode->i_size = pageofs; ++ mutex_unlock(&f->sem); + } + + /* +@@ -224,18 +221,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, + * case of a short-copy. + */ + if (!PageUptodate(pg)) { ++ mutex_lock(&f->sem); + ret = jffs2_do_readpage_nolock(inode, pg); ++ mutex_unlock(&f->sem); + if (ret) + goto out_page; + } +- mutex_unlock(&f->sem); + jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); + return ret; + + out_page: + unlock_page(pg); + page_cache_release(pg); +- mutex_unlock(&f->sem); + return ret; + } + +diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c +index 5a2dec2b064c..95d5880a63ee 100644 +--- a/fs/jffs2/gc.c ++++ b/fs/jffs2/gc.c +@@ -1296,14 +1296,17 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era + BUG_ON(start > orig_start); + } + +- /* First, use readpage() to read the appropriate page into the page cache */ +- /* Q: What happens if we actually try to GC the _same_ page for which commit_write() +- * triggered garbage collection in the first place? +- * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the +- * page OK. We'll actually write it out again in commit_write, which is a little +- * suboptimal, but at least we're correct. +- */ ++ /* The rules state that we must obtain the page lock *before* f->sem, so ++ * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's ++ * actually going to *change* so we're safe; we only allow reading. ++ * ++ * It is important to note that jffs2_write_begin() will ensure that its ++ * page is marked Uptodate before allocating space. That means that if we ++ * end up here trying to GC the *same* page that jffs2_write_begin() is ++ * trying to write out, read_cache_page() will not deadlock. */ ++ mutex_unlock(&f->sem); + pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg); ++ mutex_lock(&f->sem); + + if (IS_ERR(pg_ptr)) { + pr_warn("read_cache_page() returned error: %ld\n", +diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h +index fa35ff79ab35..0637271f3770 100644 +--- a/fs/jffs2/nodelist.h ++++ b/fs/jffs2/nodelist.h +@@ -194,6 +194,7 @@ struct jffs2_inode_cache { + #define INO_STATE_CLEARING 6 /* In clear_inode() */ + + #define INO_FLAGS_XATTR_CHECKED 0x01 /* has no duplicate xattr_ref */ ++#define INO_FLAGS_IS_DIR 0x02 /* is a directory */ + + #define RAWNODE_CLASS_INODE_CACHE 0 + #define RAWNODE_CLASS_XATTR_DATUM 1 +@@ -249,7 +250,10 @@ struct jffs2_readinode_info + + struct jffs2_full_dirent + { +- struct jffs2_raw_node_ref *raw; ++ union { ++ struct jffs2_raw_node_ref *raw; ++ struct jffs2_inode_cache *ic; /* Just during part of build */ ++ }; + struct jffs2_full_dirent *next; + uint32_t version; + uint32_t ino; /* == zero for unlink */ +diff --git a/fs/locks.c b/fs/locks.c +index 2c61c4e9368c..f3197830f07e 100644 +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -2007,7 +2007,6 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, + goto out; + } + +-again: + error = flock_to_posix_lock(filp, file_lock, &flock); + if (error) + goto out; +@@ -2038,19 +2037,22 @@ again: + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ +- /* +- * we need that spin_lock here - it prevents reordering between +- * update of inode->i_flock and check for it done in close(). +- * rcu_read_lock() wouldn't do. +- */ +- spin_lock(¤t->files->file_lock); +- f = fcheck(fd); +- spin_unlock(¤t->files->file_lock); +- if (!error && f != filp && flock.l_type != F_UNLCK) { +- flock.l_type = F_UNLCK; +- goto again; ++ if (!error && file_lock->fl_type != F_UNLCK) { ++ /* ++ * We need that spin_lock here - it prevents reordering between ++ * update of inode->i_flock and check for it done in ++ * close(). rcu_read_lock() wouldn't do. ++ */ ++ spin_lock(¤t->files->file_lock); ++ f = fcheck(fd); ++ spin_unlock(¤t->files->file_lock); ++ if (f != filp) { ++ file_lock->fl_type = F_UNLCK; ++ error = do_lock_file_wait(filp, cmd, file_lock); ++ WARN_ON_ONCE(error); ++ error = -EBADF; ++ } + } +- + out: + locks_free_lock(file_lock); + return error; +@@ -2125,7 +2127,6 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, + goto out; + } + +-again: + error = flock64_to_posix_lock(filp, file_lock, &flock); + if (error) + goto out; +@@ -2156,14 +2157,22 @@ again: + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ +- spin_lock(¤t->files->file_lock); +- f = fcheck(fd); +- spin_unlock(¤t->files->file_lock); +- if (!error && f != filp && flock.l_type != F_UNLCK) { +- flock.l_type = F_UNLCK; +- goto again; ++ if (!error && file_lock->fl_type != F_UNLCK) { ++ /* ++ * We need that spin_lock here - it prevents reordering between ++ * update of inode->i_flock and check for it done in ++ * close(). rcu_read_lock() wouldn't do. ++ */ ++ spin_lock(¤t->files->file_lock); ++ f = fcheck(fd); ++ spin_unlock(¤t->files->file_lock); ++ if (f != filp) { ++ file_lock->fl_type = F_UNLCK; ++ error = do_lock_file_wait(filp, cmd, file_lock); ++ WARN_ON_ONCE(error); ++ error = -EBADF; ++ } + } +- + out: + locks_free_lock(file_lock); + return error; +diff --git a/include/linux/ata.h b/include/linux/ata.h +index f2f4d8da97c0..f7ff6554a354 100644 +--- a/include/linux/ata.h ++++ b/include/linux/ata.h +@@ -484,8 +484,8 @@ enum ata_tf_protocols { + }; + + enum ata_ioctls { +- ATA_IOC_GET_IO32 = 0x309, +- ATA_IOC_SET_IO32 = 0x324, ++ ATA_IOC_GET_IO32 = 0x309, /* HDIO_GET_32BIT */ ++ ATA_IOC_SET_IO32 = 0x324, /* HDIO_SET_32BIT */ + }; + + /* core structures */ +diff --git a/include/linux/libata.h b/include/linux/libata.h +index 189c9ff97b29..a445209be917 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -712,7 +712,7 @@ struct ata_device { + union { + u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ + u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ +- }; ++ } ____cacheline_aligned; + + /* DEVSLP Timing Variables from Identify Device Data Log */ + u8 devslp_timing[ATA_LOG_DEVSLP_SIZE]; +diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h +index d1fb912740f3..0d7a62fea895 100644 +--- a/include/target/iscsi/iscsi_transport.h ++++ b/include/target/iscsi/iscsi_transport.h +@@ -21,6 +21,7 @@ struct iscsit_transport { + int (*iscsit_get_dataout)(struct iscsi_conn *, struct iscsi_cmd *, bool); + int (*iscsit_queue_data_in)(struct iscsi_conn *, struct iscsi_cmd *); + int (*iscsit_queue_status)(struct iscsi_conn *, struct iscsi_cmd *); ++ void (*iscsit_aborted_task)(struct iscsi_conn *, struct iscsi_cmd *); + }; + + static inline void *iscsit_priv_cmd(struct iscsi_cmd *cmd) +diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h +index f5915b39386a..522ae25a61a7 100644 +--- a/include/target/target_core_backend.h ++++ b/include/target/target_core_backend.h +@@ -94,4 +94,8 @@ sense_reason_t transport_generic_map_mem_to_cmd(struct se_cmd *, + + void array_free(void *array, int n); + ++sector_t target_to_linux_sector(struct se_device *dev, sector_t lb); ++bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, ++ struct request_queue *q, int block_size); ++ + #endif /* TARGET_CORE_BACKEND_H */ +diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h +index 42606764d830..3beb2fed86aa 100644 +--- a/include/target/target_core_base.h ++++ b/include/target/target_core_base.h +@@ -162,7 +162,7 @@ enum se_cmd_flags_table { + SCF_SENT_CHECK_CONDITION = 0x00000800, + SCF_OVERFLOW_BIT = 0x00001000, + SCF_UNDERFLOW_BIT = 0x00002000, +- SCF_SENT_DELAYED_TAS = 0x00004000, ++ SCF_SEND_DELAYED_TAS = 0x00004000, + SCF_ALUA_NON_OPTIMIZED = 0x00008000, + SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000, + SCF_ACK_KREF = 0x00040000, +@@ -528,6 +528,8 @@ struct se_cmd { + #define CMD_T_DEV_ACTIVE (1 << 7) + #define CMD_T_REQUEST_STOP (1 << 8) + #define CMD_T_BUSY (1 << 9) ++#define CMD_T_TAS (1 << 10) ++#define CMD_T_FABRIC_STOP (1 << 11) + spinlock_t t_state_lock; + struct completion t_transport_stop_comp; + +diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h +index 0218d689b3d7..1d1043644b9b 100644 +--- a/include/target/target_core_fabric.h ++++ b/include/target/target_core_fabric.h +@@ -62,6 +62,7 @@ struct target_core_fabric_ops { + int (*queue_data_in)(struct se_cmd *); + int (*queue_status)(struct se_cmd *); + void (*queue_tm_rsp)(struct se_cmd *); ++ void (*aborted_task)(struct se_cmd *); + /* + * fabric module calls for target_core_fabric_configfs.c + */ +diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c +index 2bb95a7a8809..c14565bde887 100644 +--- a/sound/core/control_compat.c ++++ b/sound/core/control_compat.c +@@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 { + unsigned char reserved[128]; + }; + ++#ifdef CONFIG_X86_X32 ++/* x32 has a different alignment for 64bit values from ia32 */ ++struct snd_ctl_elem_value_x32 { ++ struct snd_ctl_elem_id id; ++ unsigned int indirect; /* bit-field causes misalignment */ ++ union { ++ s32 integer[128]; ++ unsigned char data[512]; ++ s64 integer64[64]; ++ } value; ++ unsigned char reserved[128]; ++}; ++#endif /* CONFIG_X86_X32 */ + + /* get the value type and count of the control */ + static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, +@@ -219,9 +232,11 @@ static int get_elem_size(int type, int count) + + static int copy_ctl_value_from_user(struct snd_card *card, + struct snd_ctl_elem_value *data, +- struct snd_ctl_elem_value32 __user *data32, ++ void __user *userdata, ++ void __user *valuep, + int *typep, int *countp) + { ++ struct snd_ctl_elem_value32 __user *data32 = userdata; + int i, type, size; + int uninitialized_var(count); + unsigned int indirect; +@@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(struct snd_card *card, + if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || + type == SNDRV_CTL_ELEM_TYPE_INTEGER) { + for (i = 0; i < count; i++) { ++ s32 __user *intp = valuep; + int val; +- if (get_user(val, &data32->value.integer[i])) ++ if (get_user(val, &intp[i])) + return -EFAULT; + data->value.integer.value[i] = val; + } +@@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(struct snd_card *card, + printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); + return -EINVAL; + } +- if (copy_from_user(data->value.bytes.data, +- data32->value.data, size)) ++ if (copy_from_user(data->value.bytes.data, valuep, size)) + return -EFAULT; + } + +@@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(struct snd_card *card, + } + + /* restore the value to 32bit */ +-static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, ++static int copy_ctl_value_to_user(void __user *userdata, ++ void __user *valuep, + struct snd_ctl_elem_value *data, + int type, int count) + { +@@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, + if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || + type == SNDRV_CTL_ELEM_TYPE_INTEGER) { + for (i = 0; i < count; i++) { ++ s32 __user *intp = valuep; + int val; + val = data->value.integer.value[i]; +- if (put_user(val, &data32->value.integer[i])) ++ if (put_user(val, &intp[i])) + return -EFAULT; + } + } else { + size = get_elem_size(type, count); +- if (copy_to_user(data32->value.data, +- data->value.bytes.data, size)) ++ if (copy_to_user(valuep, data->value.bytes.data, size)) + return -EFAULT; + } + return 0; + } + +-static int snd_ctl_elem_read_user_compat(struct snd_card *card, +- struct snd_ctl_elem_value32 __user *data32) ++static int ctl_elem_read_user(struct snd_card *card, ++ void __user *userdata, void __user *valuep) + { + struct snd_ctl_elem_value *data; + int err, type, count; +@@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, + if (data == NULL) + return -ENOMEM; + +- if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) ++ err = copy_ctl_value_from_user(card, data, userdata, valuep, ++ &type, &count); ++ if (err < 0) + goto error; + + snd_power_lock(card); +@@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card, + err = snd_ctl_elem_read(card, data); + snd_power_unlock(card); + if (err >= 0) +- err = copy_ctl_value_to_user(data32, data, type, count); ++ err = copy_ctl_value_to_user(userdata, valuep, data, ++ type, count); + error: + kfree(data); + return err; + } + +-static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, +- struct snd_ctl_elem_value32 __user *data32) ++static int ctl_elem_write_user(struct snd_ctl_file *file, ++ void __user *userdata, void __user *valuep) + { + struct snd_ctl_elem_value *data; + struct snd_card *card = file->card; +@@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, + if (data == NULL) + return -ENOMEM; + +- if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) ++ err = copy_ctl_value_from_user(card, data, userdata, valuep, ++ &type, &count); ++ if (err < 0) + goto error; + + snd_power_lock(card); +@@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, + err = snd_ctl_elem_write(card, file, data); + snd_power_unlock(card); + if (err >= 0) +- err = copy_ctl_value_to_user(data32, data, type, count); ++ err = copy_ctl_value_to_user(userdata, valuep, data, ++ type, count); + error: + kfree(data); + return err; + } + ++static int snd_ctl_elem_read_user_compat(struct snd_card *card, ++ struct snd_ctl_elem_value32 __user *data32) ++{ ++ return ctl_elem_read_user(card, data32, &data32->value); ++} ++ ++static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, ++ struct snd_ctl_elem_value32 __user *data32) ++{ ++ return ctl_elem_write_user(file, data32, &data32->value); ++} ++ ++#ifdef CONFIG_X86_X32 ++static int snd_ctl_elem_read_user_x32(struct snd_card *card, ++ struct snd_ctl_elem_value_x32 __user *data32) ++{ ++ return ctl_elem_read_user(card, data32, &data32->value); ++} ++ ++static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file, ++ struct snd_ctl_elem_value_x32 __user *data32) ++{ ++ return ctl_elem_write_user(file, data32, &data32->value); ++} ++#endif /* CONFIG_X86_X32 */ ++ + /* add or replace a user control */ + static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, + struct snd_ctl_elem_info32 __user *data32, +@@ -393,6 +441,10 @@ enum { + SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), + SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), + SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), ++#ifdef CONFIG_X86_X32 ++ SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32), ++ SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32), ++#endif /* CONFIG_X86_X32 */ + }; + + static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +@@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns + return snd_ctl_elem_add_compat(ctl, argp, 0); + case SNDRV_CTL_IOCTL_ELEM_REPLACE32: + return snd_ctl_elem_add_compat(ctl, argp, 1); ++#ifdef CONFIG_X86_X32 ++ case SNDRV_CTL_IOCTL_ELEM_READ_X32: ++ return snd_ctl_elem_read_user_x32(ctl->card, argp); ++ case SNDRV_CTL_IOCTL_ELEM_WRITE_X32: ++ return snd_ctl_elem_write_user_x32(ctl, argp); ++#endif /* CONFIG_X86_X32 */ + } + + down_read(&snd_ioctl_rwsem); +diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c +index 5268c1f58c25..09a89094dcf7 100644 +--- a/sound/core/rawmidi_compat.c ++++ b/sound/core/rawmidi_compat.c +@@ -94,9 +94,58 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, + return 0; + } + ++#ifdef CONFIG_X86_X32 ++/* X32 ABI has 64bit timespec and 64bit alignment */ ++struct snd_rawmidi_status_x32 { ++ s32 stream; ++ u32 rsvd; /* alignment */ ++ struct timespec tstamp; ++ u32 avail; ++ u32 xruns; ++ unsigned char reserved[16]; ++} __attribute__((packed)); ++ ++#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) ++ ++static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, ++ struct snd_rawmidi_status_x32 __user *src) ++{ ++ int err; ++ struct snd_rawmidi_status status; ++ ++ if (rfile->output == NULL) ++ return -EINVAL; ++ if (get_user(status.stream, &src->stream)) ++ return -EFAULT; ++ ++ switch (status.stream) { ++ case SNDRV_RAWMIDI_STREAM_OUTPUT: ++ err = snd_rawmidi_output_status(rfile->output, &status); ++ break; ++ case SNDRV_RAWMIDI_STREAM_INPUT: ++ err = snd_rawmidi_input_status(rfile->input, &status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (err < 0) ++ return err; ++ ++ if (put_timespec(&status.tstamp, &src->tstamp) || ++ put_user(status.avail, &src->avail) || ++ put_user(status.xruns, &src->xruns)) ++ return -EFAULT; ++ ++ return 0; ++} ++#endif /* CONFIG_X86_X32 */ ++ + enum { + SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), + SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), ++#ifdef CONFIG_X86_X32 ++ SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32), ++#endif /* CONFIG_X86_X32 */ + }; + + static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +@@ -115,6 +164,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign + return snd_rawmidi_ioctl_params_compat(rfile, argp); + case SNDRV_RAWMIDI_IOCTL_STATUS32: + return snd_rawmidi_ioctl_status_compat(rfile, argp); ++#ifdef CONFIG_X86_X32 ++ case SNDRV_RAWMIDI_IOCTL_STATUS_X32: ++ return snd_rawmidi_ioctl_status_x32(rfile, argp); ++#endif /* CONFIG_X86_X32 */ + } + return -ENOIOCTLCMD; + } +diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c +index 8d4d5e853efe..ab774954c985 100644 +--- a/sound/core/seq/oss/seq_oss.c ++++ b/sound/core/seq/oss/seq_oss.c +@@ -150,8 +150,6 @@ odev_release(struct inode *inode, struct file *file) + if ((dp = file->private_data) == NULL) + return 0; + +- snd_seq_oss_drain_write(dp); +- + mutex_lock(®ister_mutex); + snd_seq_oss_release(dp); + mutex_unlock(®ister_mutex); +diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h +index c0154a959d55..2464112b08ad 100644 +--- a/sound/core/seq/oss/seq_oss_device.h ++++ b/sound/core/seq/oss/seq_oss_device.h +@@ -131,7 +131,6 @@ int snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int co + unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait); + + void snd_seq_oss_reset(struct seq_oss_devinfo *dp); +-void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp); + + /* */ + void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time); +diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c +index b3f39b5ed742..f9e09e458227 100644 +--- a/sound/core/seq/oss/seq_oss_init.c ++++ b/sound/core/seq/oss/seq_oss_init.c +@@ -457,23 +457,6 @@ snd_seq_oss_release(struct seq_oss_devinfo *dp) + + + /* +- * Wait until the queue is empty (if we don't have nonblock) +- */ +-void +-snd_seq_oss_drain_write(struct seq_oss_devinfo *dp) +-{ +- if (! dp->timer->running) +- return; +- if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) && +- dp->writeq) { +- debug_printk(("syncing..\n")); +- while (snd_seq_oss_writeq_sync(dp->writeq)) +- ; +- } +-} +- +- +-/* + * reset sequencer devices + */ + void +diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c +index e05802ae6e1b..2e908225d754 100644 +--- a/sound/core/timer_compat.c ++++ b/sound/core/timer_compat.c +@@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(struct file *file, + struct snd_timer_status32 __user *_status) + { + struct snd_timer_user *tu; +- struct snd_timer_status status; ++ struct snd_timer_status32 status; + + tu = file->private_data; + if (snd_BUG_ON(!tu->timeri)) + return -ENXIO; + memset(&status, 0, sizeof(status)); +- status.tstamp = tu->tstamp; ++ status.tstamp.tv_sec = tu->tstamp.tv_sec; ++ status.tstamp.tv_nsec = tu->tstamp.tv_nsec; + status.resolution = snd_timer_resolution(tu->timeri); + status.lost = tu->timeri->lost; + status.overrun = tu->overrun; +@@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(struct file *file, + return 0; + } + ++#ifdef CONFIG_X86_X32 ++/* X32 ABI has the same struct as x86-64 */ ++#define snd_timer_user_status_x32(file, s) \ ++ snd_timer_user_status(file, s) ++#endif /* CONFIG_X86_X32 */ ++ + /* + */ + + enum { + SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), + SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), ++#ifdef CONFIG_X86_X32 ++ SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status), ++#endif /* CONFIG_X86_X32 */ + }; + + static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +@@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns + return snd_timer_user_info_compat(file, argp); + case SNDRV_TIMER_IOCTL_STATUS32: + return snd_timer_user_status_compat(file, argp); ++#ifdef CONFIG_X86_X32 ++ case SNDRV_TIMER_IOCTL_STATUS_X32: ++ return snd_timer_user_status_x32(file, argp); ++#endif /* CONFIG_X86_X32 */ + } + return -ENOIOCTLCMD; + } +diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c +index bd90c80bb494..4bc0d66377d6 100644 +--- a/sound/pci/rme9652/hdsp.c ++++ b/sound/pci/rme9652/hdsp.c +@@ -2917,7 +2917,7 @@ static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl + { + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + +- ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp); ++ ucontrol->value.integer.value[0] = hdsp_dds_offset(hdsp); + return 0; + } + +@@ -2929,7 +2929,7 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl + + if (!snd_hdsp_use_is_exclusive(hdsp)) + return -EBUSY; +- val = ucontrol->value.enumerated.item[0]; ++ val = ucontrol->value.integer.value[0]; + spin_lock_irq(&hdsp->lock); + if (val != hdsp_dds_offset(hdsp)) + change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0; +diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c +index 21167503a3f9..dec173081798 100644 +--- a/sound/pci/rme9652/hdspm.c ++++ b/sound/pci/rme9652/hdspm.c +@@ -1602,6 +1602,9 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) + { + u64 n; + ++ if (snd_BUG_ON(rate <= 0)) ++ return; ++ + if (rate >= 112000) + rate /= 4; + else if (rate >= 56000) +@@ -2224,6 +2227,8 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm) + } else { + /* slave mode, return external sample rate */ + rate = hdspm_external_sample_rate(hdspm); ++ if (!rate) ++ rate = hdspm->system_sample_rate; + } + } + +@@ -2269,8 +2274,11 @@ static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol, + ucontrol) + { + struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); ++ int rate = ucontrol->value.integer.value[0]; + +- hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]); ++ if (rate < 27000 || rate > 207000) ++ return -EINVAL; ++ hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]); + return 0; + } + +@@ -4469,7 +4477,7 @@ static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol, + { + struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); + +- ucontrol->value.enumerated.item[0] = hdspm->tco->term; ++ ucontrol->value.integer.value[0] = hdspm->tco->term; + + return 0; + } +@@ -4480,8 +4488,8 @@ static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol, + { + struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); + +- if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) { +- hdspm->tco->term = ucontrol->value.enumerated.item[0]; ++ if (hdspm->tco->term != ucontrol->value.integer.value[0]) { ++ hdspm->tco->term = ucontrol->value.integer.value[0]; + + hdspm_tco_write(hdspm); +