From bdcfd44fb5b5fb8fd660e7f93f1095c507481024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Fabian=20Silva=20Delgado?= Date: Sat, 16 Apr 2016 15:30:54 -0300 Subject: Linux-libre 4.5.1-gnu --- drivers/acpi/resource.c | 14 +- drivers/acpi/sleep.c | 1 + drivers/block/brd.c | 2 +- drivers/block/loop.c | 18 ++ drivers/block/mtip32xx/mtip32xx.c | 267 ++++++++++++++++----- drivers/block/mtip32xx/mtip32xx.h | 11 +- drivers/bluetooth/ath3k.c | 8 + drivers/bluetooth/btusb.c | 4 + drivers/char/tpm/tpm-chip.c | 14 +- drivers/char/tpm/tpm_crb.c | 4 +- drivers/char/tpm/tpm_eventlog.c | 14 +- drivers/clk/bcm/clk-bcm2835.c | 12 +- drivers/clk/rockchip/clk-rk3188.c | 1 + drivers/clk/rockchip/clk-rk3368.c | 48 ++-- drivers/cpufreq/cpufreq.c | 7 + drivers/cpufreq/cpufreq_conservative.c | 6 + drivers/cpufreq/cpufreq_ondemand.c | 5 + drivers/cpufreq/intel_pstate.c | 9 +- drivers/crypto/atmel-aes.c | 4 +- drivers/crypto/atmel-sha.c | 4 +- drivers/crypto/atmel-tdes.c | 4 +- drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 36 +++ drivers/crypto/ccp/ccp-crypto-sha.c | 40 +++ drivers/crypto/ccp/ccp-crypto.h | 22 ++ drivers/crypto/marvell/cesa.c | 2 +- drivers/crypto/ux500/cryp/cryp_core.c | 4 +- drivers/crypto/ux500/hash/hash_core.c | 4 +- drivers/edac/amd64_edac.c | 2 +- drivers/edac/sb_edac.c | 26 +- drivers/firmware/broadcom/bcm47xx_nvram.c | 5 +- drivers/gpio/gpio-pca953x.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 +- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 4 +- drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 5 + drivers/gpu/drm/radeon/atombios_encoders.c | 6 +- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 8 +- drivers/gpu/drm/radeon/radeon_device.c | 8 +- drivers/gpu/drm/radeon/radeon_display.c | 6 +- drivers/gpu/drm/radeon/radeon_dp_mst.c | 12 +- drivers/gpu/drm/radeon/radeon_fb.c | 19 +- drivers/gpu/drm/vc4/vc4_bo.c | 7 +- drivers/hid/hid-core.c | 8 +- drivers/hid/hid-multitouch.c | 5 + drivers/hid/i2c-hid/i2c-hid.c | 16 +- drivers/idle/intel_idle.c | 108 +++++++-- drivers/infiniband/ulp/isert/ib_isert.c | 122 +++++----- drivers/infiniband/ulp/isert/ib_isert.h | 2 +- drivers/infiniband/ulp/srpt/ib_srpt.c | 59 +---- drivers/input/misc/ati_remote2.c | 36 ++- drivers/input/misc/ims-pcu.c | 4 + drivers/input/misc/powermate.c | 3 + drivers/input/mouse/synaptics.c | 5 +- drivers/md/bcache/super.c | 46 +++- drivers/md/dm-cache-metadata.c | 98 +++++--- drivers/md/dm-cache-metadata.h | 4 +- drivers/md/dm-cache-target.c | 12 +- drivers/md/dm-snap.c | 9 + drivers/md/dm-table.c | 36 ++- drivers/md/dm-thin-metadata.c | 5 +- drivers/md/dm.c | 15 +- drivers/md/multipath.c | 4 +- drivers/md/raid1.c | 7 +- drivers/md/raid10.c | 7 +- drivers/md/raid5.c | 51 ++-- drivers/md/raid5.h | 4 +- drivers/media/i2c/adv7511.c | 21 +- drivers/media/pci/bt8xx/bttv-driver.c | 26 +- drivers/media/pci/saa7134/saa7134-video.c | 18 +- drivers/media/platform/coda/coda-bit.c | 2 +- drivers/media/usb/pwc/pwc-if.c | 6 + drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 21 +- drivers/misc/mei/bus.c | 9 + drivers/mmc/card/block.c | 24 +- drivers/mmc/host/atmel-mci.c | 2 +- drivers/mmc/host/mmc_spi.c | 6 + drivers/mmc/host/sdhci-pxav3.c | 6 +- drivers/mmc/host/sdhci-tegra.c | 14 +- drivers/mmc/host/sdhci.c | 142 ++++++----- drivers/mtd/onenand/onenand_base.c | 3 +- drivers/net/ethernet/marvell/mvneta.c | 2 +- drivers/net/irda/irtty-sir.c | 10 - drivers/net/rionet.c | 4 +- .../broadcom/brcm80211/brcmfmac/flowring.c | 38 +-- .../broadcom/brcm80211/brcmfmac/flowring.h | 20 +- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 11 +- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | 2 +- drivers/net/wireless/ralink/rt2x00/rt2800usb.c | 1 + drivers/nvdimm/bus.c | 8 +- drivers/nvdimm/pmem.c | 11 +- drivers/of/of_reserved_mem.c | 4 +- drivers/pci/probe.c | 14 ++ drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 +- drivers/platform/x86/ideapad-laptop.c | 14 ++ drivers/scsi/NCR5380.c | 133 +++++----- drivers/scsi/aacraid/aacraid.h | 2 + drivers/scsi/aacraid/commsup.c | 37 ++- drivers/scsi/aacraid/linit.c | 12 +- drivers/scsi/aacraid/src.c | 30 +-- drivers/scsi/aic7xxx/aic7xxx_osm.c | 1 + drivers/scsi/atari_NCR5380.c | 133 +++++----- drivers/scsi/be2iscsi/be_main.c | 1 + drivers/scsi/scsi_common.c | 12 +- drivers/scsi/sd.c | 2 +- drivers/scsi/sg.c | 3 +- drivers/scsi/storvsc_drv.c | 5 +- drivers/staging/android/ion/ion_test.c | 4 +- drivers/staging/comedi/drivers/ni_mio_common.c | 12 +- drivers/staging/comedi/drivers/ni_tiocmd.c | 2 +- drivers/target/target_core_transport.c | 2 - drivers/thermal/thermal_core.c | 13 +- drivers/tty/serial/8250/8250_port.c | 18 +- drivers/usb/class/cdc-acm.c | 3 + drivers/usb/core/driver.c | 6 +- drivers/usb/core/hub.c | 16 +- drivers/usb/misc/iowarrior.c | 6 + drivers/usb/serial/cp210x.c | 1 + drivers/usb/serial/cypress_m8.c | 11 +- drivers/usb/serial/digi_acceleport.c | 19 ++ drivers/usb/serial/ftdi_sio.c | 4 + drivers/usb/serial/ftdi_sio_ids.h | 8 + drivers/usb/serial/mct_u232.c | 9 +- drivers/usb/serial/option.c | 2 + drivers/usb/storage/uas.c | 2 +- drivers/watchdog/rc32434_wdt.c | 2 +- 125 files changed, 1501 insertions(+), 812 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index d02fd5304..56241eb34 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -27,8 +27,20 @@ #ifdef CONFIG_X86 #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) +static inline bool acpi_iospace_resource_valid(struct resource *res) +{ + /* On X86 IO space is limited to the [0 - 64K] IO port range */ + return res->end < 0x10003; +} #else #define valid_IRQ(i) (true) +/* + * ACPI IO descriptors on arches other than X86 contain MMIO CPU physical + * addresses mapping IO space in CPU physical address space, IO space + * resources can be placed anywhere in the 64-bit physical address space. + */ +static inline bool +acpi_iospace_resource_valid(struct resource *res) { return true; } #endif static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io) @@ -127,7 +139,7 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len, if (!acpi_dev_resource_len_valid(res->start, res->end, len, true)) res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; - if (res->end >= 0x10003) + if (!acpi_iospace_resource_valid(res)) res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; if (io_decode == ACPI_DECODE_16) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 9cb975200..f054cadf3 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -714,6 +714,7 @@ static int acpi_hibernation_enter(void) static void acpi_hibernation_leave(void) { + pm_set_resume_via_firmware(); /* * If ACPI is not enabled by the BIOS and the boot kernel, we need to * enable it here. diff --git a/drivers/block/brd.c b/drivers/block/brd.c index cb27190e9..f7ecc287d 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -341,7 +341,7 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio) if (unlikely(bio->bi_rw & REQ_DISCARD)) { if (sector & ((PAGE_SIZE >> SECTOR_SHIFT) - 1) || - bio->bi_iter.bi_size & PAGE_MASK) + bio->bi_iter.bi_size & ~PAGE_MASK) goto io_error; discard_from_brd(brd, sector, bio->bi_iter.bi_size); goto out; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 423f4ca7d..0b816b24b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -706,6 +706,24 @@ static inline int is_loop_device(struct file *file) return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR; } +/* + * for AUFS + * no get/put for file. + */ +struct file *loop_backing_file(struct super_block *sb) +{ + struct file *ret; + struct loop_device *l; + + ret = NULL; + if (MAJOR(sb->s_dev) == LOOP_MAJOR) { + l = sb->s_bdev->bd_disk->private_data; + ret = l->lo_backing_file; + } + return ret; +} +EXPORT_SYMBOL_GPL(loop_backing_file); + /* loop sysfs attributes */ static ssize_t loop_attr_show(struct device *dev, char *page, diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 9b180dbbd..1c330b61f 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -173,7 +173,13 @@ static struct mtip_cmd *mtip_get_int_command(struct driver_data *dd) { struct request *rq; + if (mtip_check_surprise_removal(dd->pdev)) + return NULL; + rq = blk_mq_alloc_request(dd->queue, 0, BLK_MQ_REQ_RESERVED); + if (IS_ERR(rq)) + return NULL; + return blk_mq_rq_to_pdu(rq); } @@ -233,15 +239,9 @@ static void mtip_async_complete(struct mtip_port *port, "Command tag %d failed due to TFE\n", tag); } - /* Unmap the DMA scatter list entries */ - dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, cmd->direction); - rq = mtip_rq_from_tag(dd, tag); - if (unlikely(cmd->unaligned)) - up(&port->cmd_slot_unal); - - blk_mq_end_request(rq, status ? -EIO : 0); + blk_mq_complete_request(rq, status); } /* @@ -581,6 +581,8 @@ static void mtip_completion(struct mtip_port *port, dev_warn(&port->dd->pdev->dev, "Internal command %d completed with TFE\n", tag); + command->comp_func = NULL; + command->comp_data = NULL; complete(waiting); } @@ -618,8 +620,6 @@ static void mtip_handle_tfe(struct driver_data *dd) port = dd->port; - set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); - if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL); dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n"); @@ -628,7 +628,7 @@ static void mtip_handle_tfe(struct driver_data *dd) cmd->comp_func(port, MTIP_TAG_INTERNAL, cmd, PORT_IRQ_TF_ERR); } - goto handle_tfe_exit; + return; } /* clear the tag accumulator */ @@ -701,7 +701,7 @@ static void mtip_handle_tfe(struct driver_data *dd) fail_reason = "thermal shutdown"; } if (buf[288] == 0xBF) { - set_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag); + set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag); dev_info(&dd->pdev->dev, "Drive indicates rebuild has failed. Secure erase required.\n"); fail_all_ncq_cmds = 1; @@ -771,11 +771,6 @@ static void mtip_handle_tfe(struct driver_data *dd) } } print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt); - -handle_tfe_exit: - /* clear eh_active */ - clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); - wake_up_interruptible(&port->svc_wait); } /* @@ -1007,6 +1002,7 @@ static bool mtip_pause_ncq(struct mtip_port *port, (fis->features == 0x27 || fis->features == 0x72 || fis->features == 0x62 || fis->features == 0x26))) { clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag); + clear_bit(MTIP_DDF_REBUILD_FAILED_BIT, &port->dd->dd_flag); /* Com reset after secure erase or lowlevel format */ mtip_restart_port(port); clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); @@ -1021,12 +1017,14 @@ static bool mtip_pause_ncq(struct mtip_port *port, * * @port Pointer to port data structure * @timeout Max duration to wait (ms) + * @atomic gfp_t flag to indicate blockable context or not * * return value * 0 Success * -EBUSY Commands still active */ -static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) +static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout, + gfp_t atomic) { unsigned long to; unsigned int n; @@ -1037,16 +1035,21 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) to = jiffies + msecs_to_jiffies(timeout); do { if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) && - test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { + test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags) && + atomic == GFP_KERNEL) { msleep(20); continue; /* svc thd is actively issuing commands */ } - msleep(100); + if (atomic == GFP_KERNEL) + msleep(100); + else { + cpu_relax(); + udelay(100); + } + if (mtip_check_surprise_removal(port->dd->pdev)) goto err_fault; - if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) - goto err_fault; /* * Ignore s_active bit 0 of array element 0. @@ -1099,6 +1102,7 @@ static int mtip_exec_internal_command(struct mtip_port *port, struct mtip_cmd *int_cmd; struct driver_data *dd = port->dd; int rv = 0; + unsigned long start; /* Make sure the buffer is 8 byte aligned. This is asic specific. */ if (buffer & 0x00000007) { @@ -1107,6 +1111,10 @@ static int mtip_exec_internal_command(struct mtip_port *port, } int_cmd = mtip_get_int_command(dd); + if (!int_cmd) { + dbg_printk(MTIP_DRV_NAME "Unable to allocate tag for PIO cmd\n"); + return -EFAULT; + } set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); @@ -1119,7 +1127,7 @@ static int mtip_exec_internal_command(struct mtip_port *port, if (fis->command != ATA_CMD_STANDBYNOW1) { /* wait for io to complete if non atomic */ if (mtip_quiesce_io(port, - MTIP_QUIESCE_IO_TIMEOUT_MS) < 0) { + MTIP_QUIESCE_IO_TIMEOUT_MS, atomic) < 0) { dev_warn(&dd->pdev->dev, "Failed to quiesce IO\n"); mtip_put_int_command(dd, int_cmd); @@ -1162,6 +1170,8 @@ static int mtip_exec_internal_command(struct mtip_port *port, /* Populate the command header */ int_cmd->command_header->byte_count = 0; + start = jiffies; + /* Issue the command to the hardware */ mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL); @@ -1170,10 +1180,12 @@ static int mtip_exec_internal_command(struct mtip_port *port, if ((rv = wait_for_completion_interruptible_timeout( &wait, msecs_to_jiffies(timeout))) <= 0) { + if (rv == -ERESTARTSYS) { /* interrupted */ dev_err(&dd->pdev->dev, - "Internal command [%02X] was interrupted after %lu ms\n", - fis->command, timeout); + "Internal command [%02X] was interrupted after %u ms\n", + fis->command, + jiffies_to_msecs(jiffies - start)); rv = -EINTR; goto exec_ic_exit; } else if (rv == 0) /* timeout */ @@ -2890,6 +2902,42 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) return -EFAULT; } +static void mtip_softirq_done_fn(struct request *rq) +{ + struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq); + struct driver_data *dd = rq->q->queuedata; + + /* Unmap the DMA scatter list entries */ + dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, + cmd->direction); + + if (unlikely(cmd->unaligned)) + up(&dd->port->cmd_slot_unal); + + blk_mq_end_request(rq, rq->errors); +} + +static void mtip_abort_cmd(struct request *req, void *data, + bool reserved) +{ + struct driver_data *dd = data; + + dbg_printk(MTIP_DRV_NAME " Aborting request, tag = %d\n", req->tag); + + clear_bit(req->tag, dd->port->cmds_to_issue); + req->errors = -EIO; + mtip_softirq_done_fn(req); +} + +static void mtip_queue_cmd(struct request *req, void *data, + bool reserved) +{ + struct driver_data *dd = data; + + set_bit(req->tag, dd->port->cmds_to_issue); + blk_abort_request(req); +} + /* * service thread to issue queued commands * @@ -2902,7 +2950,7 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) static int mtip_service_thread(void *data) { struct driver_data *dd = (struct driver_data *)data; - unsigned long slot, slot_start, slot_wrap; + unsigned long slot, slot_start, slot_wrap, to; unsigned int num_cmd_slots = dd->slot_groups * 32; struct mtip_port *port = dd->port; @@ -2917,9 +2965,7 @@ static int mtip_service_thread(void *data) * is in progress nor error handling is active */ wait_event_interruptible(port->svc_wait, (port->flags) && - !(port->flags & MTIP_PF_PAUSE_IO)); - - set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); + (port->flags & MTIP_PF_SVC_THD_WORK)); if (kthread_should_stop() || test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags)) @@ -2929,6 +2975,8 @@ static int mtip_service_thread(void *data) &dd->dd_flag))) goto st_out; + set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); + restart_eh: /* Demux bits: start with error handling */ if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) { @@ -2939,6 +2987,32 @@ restart_eh: if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) goto restart_eh; + if (test_bit(MTIP_PF_TO_ACTIVE_BIT, &port->flags)) { + to = jiffies + msecs_to_jiffies(5000); + + do { + mdelay(100); + } while (atomic_read(&dd->irq_workers_active) != 0 && + time_before(jiffies, to)); + + if (atomic_read(&dd->irq_workers_active) != 0) + dev_warn(&dd->pdev->dev, + "Completion workers still active!"); + + spin_lock(dd->queue->queue_lock); + blk_mq_all_tag_busy_iter(*dd->tags.tags, + mtip_queue_cmd, dd); + spin_unlock(dd->queue->queue_lock); + + set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags); + + if (mtip_device_reset(dd)) + blk_mq_all_tag_busy_iter(*dd->tags.tags, + mtip_abort_cmd, dd); + + clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags); + } + if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { slot = 1; /* used to restrict the loop to one iteration */ @@ -2971,10 +3045,8 @@ restart_eh: } if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) { - if (mtip_ftl_rebuild_poll(dd) < 0) - set_bit(MTIP_DDF_REBUILD_FAILED_BIT, - &dd->dd_flag); - clear_bit(MTIP_PF_REBUILD_BIT, &port->flags); + if (mtip_ftl_rebuild_poll(dd) == 0) + clear_bit(MTIP_PF_REBUILD_BIT, &port->flags); } } @@ -3089,7 +3161,7 @@ static int mtip_hw_get_identify(struct driver_data *dd) if (buf[288] == 0xBF) { dev_info(&dd->pdev->dev, "Drive indicates rebuild has failed.\n"); - /* TODO */ + set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag); } } @@ -3263,20 +3335,25 @@ out1: return rv; } -static void mtip_standby_drive(struct driver_data *dd) +static int mtip_standby_drive(struct driver_data *dd) { - if (dd->sr) - return; + int rv = 0; + if (dd->sr || !dd->port) + return -ENODEV; /* * Send standby immediate (E0h) to the drive so that it * saves its state. */ if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags) && - !test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) - if (mtip_standby_immediate(dd->port)) + !test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag) && + !test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) { + rv = mtip_standby_immediate(dd->port); + if (rv) dev_warn(&dd->pdev->dev, "STANDBY IMMEDIATE failed\n"); + } + return rv; } /* @@ -3289,10 +3366,6 @@ static void mtip_standby_drive(struct driver_data *dd) */ static int mtip_hw_exit(struct driver_data *dd) { - /* - * Send standby immediate (E0h) to the drive so that it - * saves its state. - */ if (!dd->sr) { /* de-initialize the port. */ mtip_deinit_port(dd->port); @@ -3334,8 +3407,7 @@ static int mtip_hw_shutdown(struct driver_data *dd) * Send standby immediate (E0h) to the drive so that it * saves its state. */ - if (!dd->sr && dd->port) - mtip_standby_immediate(dd->port); + mtip_standby_drive(dd); return 0; } @@ -3358,7 +3430,7 @@ static int mtip_hw_suspend(struct driver_data *dd) * Send standby immediate (E0h) to the drive * so that it saves its state. */ - if (mtip_standby_immediate(dd->port) != 0) { + if (mtip_standby_drive(dd) != 0) { dev_err(&dd->pdev->dev, "Failed standby-immediate command\n"); return -EFAULT; @@ -3596,6 +3668,28 @@ static int mtip_block_getgeo(struct block_device *dev, return 0; } +static int mtip_block_open(struct block_device *dev, fmode_t mode) +{ + struct driver_data *dd; + + if (dev && dev->bd_disk) { + dd = (struct driver_data *) dev->bd_disk->private_data; + + if (dd) { + if (test_bit(MTIP_DDF_REMOVAL_BIT, + &dd->dd_flag)) { + return -ENODEV; + } + return 0; + } + } + return -ENODEV; +} + +void mtip_block_release(struct gendisk *disk, fmode_t mode) +{ +} + /* * Block device operation function. * @@ -3603,6 +3697,8 @@ static int mtip_block_getgeo(struct block_device *dev, * layer. */ static const struct block_device_operations mtip_block_ops = { + .open = mtip_block_open, + .release = mtip_block_release, .ioctl = mtip_block_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = mtip_block_compat_ioctl, @@ -3664,10 +3760,9 @@ static int mtip_submit_request(struct blk_mq_hw_ctx *hctx, struct request *rq) rq_data_dir(rq))) { return -ENODATA; } - if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))) + if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag) || + test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag))) return -ENODATA; - if (test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)) - return -ENXIO; } if (rq->cmd_flags & REQ_DISCARD) { @@ -3779,11 +3874,33 @@ static int mtip_init_cmd(void *data, struct request *rq, unsigned int hctx_idx, return 0; } +static enum blk_eh_timer_return mtip_cmd_timeout(struct request *req, + bool reserved) +{ + struct driver_data *dd = req->q->queuedata; + int ret = BLK_EH_RESET_TIMER; + + if (reserved) + goto exit_handler; + + if (test_bit(req->tag, dd->port->cmds_to_issue)) + goto exit_handler; + + if (test_and_set_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags)) + goto exit_handler; + + wake_up_interruptible(&dd->port->svc_wait); +exit_handler: + return ret; +} + static struct blk_mq_ops mtip_mq_ops = { .queue_rq = mtip_queue_rq, .map_queue = blk_mq_map_queue, .init_request = mtip_init_cmd, .exit_request = mtip_free_cmd, + .complete = mtip_softirq_done_fn, + .timeout = mtip_cmd_timeout, }; /* @@ -3850,7 +3967,6 @@ static int mtip_block_initialize(struct driver_data *dd) mtip_hw_debugfs_init(dd); -skip_create_disk: memset(&dd->tags, 0, sizeof(dd->tags)); dd->tags.ops = &mtip_mq_ops; dd->tags.nr_hw_queues = 1; @@ -3860,12 +3976,13 @@ skip_create_disk: dd->tags.numa_node = dd->numa_node; dd->tags.flags = BLK_MQ_F_SHOULD_MERGE; dd->tags.driver_data = dd; + dd->tags.timeout = MTIP_NCQ_CMD_TIMEOUT_MS; rv = blk_mq_alloc_tag_set(&dd->tags); if (rv) { dev_err(&dd->pdev->dev, "Unable to allocate request queue\n"); - goto block_queue_alloc_init_error; + goto block_queue_alloc_tag_error; } /* Allocate the request queue. */ @@ -3880,6 +3997,7 @@ skip_create_disk: dd->disk->queue = dd->queue; dd->queue->queuedata = dd; +skip_create_disk: /* Initialize the protocol layer. */ wait_for_rebuild = mtip_hw_get_identify(dd); if (wait_for_rebuild < 0) { @@ -3976,8 +4094,9 @@ kthread_run_error: read_capacity_error: init_hw_cmds_error: blk_cleanup_queue(dd->queue); - blk_mq_free_tag_set(&dd->tags); block_queue_alloc_init_error: + blk_mq_free_tag_set(&dd->tags); +block_queue_alloc_tag_error: mtip_hw_debugfs_exit(dd); disk_index_error: spin_lock(&rssd_index_lock); @@ -3994,6 +4113,22 @@ protocol_init_error: return rv; } +static void mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv) +{ + struct driver_data *dd = (struct driver_data *)data; + struct mtip_cmd *cmd; + + if (likely(!reserv)) + blk_mq_complete_request(rq, -ENODEV); + else if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &dd->port->flags)) { + + cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL); + if (cmd->comp_func) + cmd->comp_func(dd->port, MTIP_TAG_INTERNAL, + cmd, -ENODEV); + } +} + /* * Block layer deinitialization function. * @@ -4025,12 +4160,23 @@ static int mtip_block_remove(struct driver_data *dd) } } - if (!dd->sr) - mtip_standby_drive(dd); + if (!dd->sr) { + /* + * Explicitly wait here for IOs to quiesce, + * as mtip_standby_drive usually won't wait for IOs. + */ + if (!mtip_quiesce_io(dd->port, MTIP_QUIESCE_IO_TIMEOUT_MS, + GFP_KERNEL)) + mtip_standby_drive(dd); + } else dev_info(&dd->pdev->dev, "device %s surprise removal\n", dd->disk->disk_name); + blk_mq_freeze_queue_start(dd->queue); + blk_mq_stop_hw_queues(dd->queue); + blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd); + /* * Delete our gendisk structure. This also removes the device * from /dev @@ -4040,7 +4186,8 @@ static int mtip_block_remove(struct driver_data *dd) dd->bdev = NULL; } if (dd->disk) { - del_gendisk(dd->disk); + if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) + del_gendisk(dd->disk); if (dd->disk->queue) { blk_cleanup_queue(dd->queue); blk_mq_free_tag_set(&dd->tags); @@ -4081,7 +4228,8 @@ static int mtip_block_shutdown(struct driver_data *dd) dev_info(&dd->pdev->dev, "Shutting down %s ...\n", dd->disk->disk_name); - del_gendisk(dd->disk); + if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) + del_gendisk(dd->disk); if (dd->disk->queue) { blk_cleanup_queue(dd->queue); blk_mq_free_tag_set(&dd->tags); @@ -4426,7 +4574,7 @@ static void mtip_pci_remove(struct pci_dev *pdev) struct driver_data *dd = pci_get_drvdata(pdev); unsigned long flags, to; - set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); + set_bit(MTIP_DDF_REMOVAL_BIT, &dd->dd_flag); spin_lock_irqsave(&dev_lock, flags); list_del_init(&dd->online_list); @@ -4443,12 +4591,17 @@ static void mtip_pci_remove(struct pci_dev *pdev) } while (atomic_read(&dd->irq_workers_active) != 0 && time_before(jiffies, to)); + if (!dd->sr) + fsync_bdev(dd->bdev); + if (atomic_read(&dd->irq_workers_active) != 0) { dev_warn(&dd->pdev->dev, "Completion workers still active!\n"); } - blk_mq_stop_hw_queues(dd->queue); + blk_set_queue_dying(dd->queue); + set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); + /* Clean up the block layer. */ mtip_block_remove(dd); diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 327478400..7617888f7 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -134,16 +134,24 @@ enum { MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */ MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */ MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */ + MTIP_PF_TO_ACTIVE_BIT = 9, /* timeout handling */ MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) | (1 << MTIP_PF_EH_ACTIVE_BIT) | (1 << MTIP_PF_SE_ACTIVE_BIT) | - (1 << MTIP_PF_DM_ACTIVE_BIT)), + (1 << MTIP_PF_DM_ACTIVE_BIT) | + (1 << MTIP_PF_TO_ACTIVE_BIT)), MTIP_PF_SVC_THD_ACTIVE_BIT = 4, MTIP_PF_ISSUE_CMDS_BIT = 5, MTIP_PF_REBUILD_BIT = 6, MTIP_PF_SVC_THD_STOP_BIT = 8, + MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) | + (1 << MTIP_PF_ISSUE_CMDS_BIT) | + (1 << MTIP_PF_REBUILD_BIT) | + (1 << MTIP_PF_SVC_THD_STOP_BIT) | + (1 << MTIP_PF_TO_ACTIVE_BIT)), + /* below are bit numbers in 'dd_flag' defined in driver_data */ MTIP_DDF_SEC_LOCK_BIT = 0, MTIP_DDF_REMOVE_PENDING_BIT = 1, @@ -153,6 +161,7 @@ enum { MTIP_DDF_RESUME_BIT = 6, MTIP_DDF_INIT_DONE_BIT = 7, MTIP_DDF_REBUILD_FAILED_BIT = 8, + MTIP_DDF_REMOVAL_BIT = 9, MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | (1 << MTIP_DDF_SEC_LOCK_BIT) | diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index cda867ada..79129bf08 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x0489, 0xe05f) }, { USB_DEVICE(0x0489, 0xe076) }, { USB_DEVICE(0x0489, 0xe078) }, + { USB_DEVICE(0x0489, 0xe095) }, { USB_DEVICE(0x04c5, 0x1330) }, { USB_DEVICE(0x04CA, 0x3004) }, { USB_DEVICE(0x04CA, 0x3005) }, @@ -92,6 +93,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x04CA, 0x300d) }, { USB_DEVICE(0x04CA, 0x300f) }, { USB_DEVICE(0x04CA, 0x3010) }, + { USB_DEVICE(0x04CA, 0x3014) }, { USB_DEVICE(0x0930, 0x0219) }, { USB_DEVICE(0x0930, 0x021c) }, { USB_DEVICE(0x0930, 0x0220) }, @@ -113,10 +115,12 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3362) }, { USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x13d3, 0x3393) }, + { USB_DEVICE(0x13d3, 0x3395) }, { USB_DEVICE(0x13d3, 0x3402) }, { USB_DEVICE(0x13d3, 0x3408) }, { USB_DEVICE(0x13d3, 0x3423) }, { USB_DEVICE(0x13d3, 0x3432) }, + { USB_DEVICE(0x13d3, 0x3472) }, { USB_DEVICE(0x13d3, 0x3474) }, /* Atheros AR5BBU12 with sflash firmware */ @@ -144,6 +148,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, @@ -154,6 +159,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, @@ -175,10 +181,12 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d897e7454..154b9ecc9 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -196,6 +196,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, @@ -206,6 +207,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, @@ -227,10 +229,12 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 45cc39aab..252142524 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -136,11 +136,13 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, chip->cdev.owner = chip->pdev->driver->owner; chip->cdev.kobj.parent = &chip->dev.kobj; + devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev); + return chip; } EXPORT_SYMBOL_GPL(tpmm_chip_alloc); -static int tpm_dev_add_device(struct tpm_chip *chip) +static int tpm_add_char_device(struct tpm_chip *chip) { int rc; @@ -151,7 +153,6 @@ static int tpm_dev_add_device(struct tpm_chip *chip) chip->devname, MAJOR(chip->dev.devt), MINOR(chip->dev.devt), rc); - device_unregister(&chip->dev); return rc; } @@ -162,16 +163,17 @@ static int tpm_dev_add_device(struct tpm_chip *chip) chip->devname, MAJOR(chip->dev.devt), MINOR(chip->dev.devt), rc); + cdev_del(&chip->cdev); return rc; } return rc; } -static void tpm_dev_del_device(struct tpm_chip *chip) +static void tpm_del_char_device(struct tpm_chip *chip) { cdev_del(&chip->cdev); - device_unregister(&chip->dev); + device_del(&chip->dev); } static int tpm1_chip_register(struct tpm_chip *chip) @@ -222,7 +224,7 @@ int tpm_chip_register(struct tpm_chip *chip) tpm_add_ppi(chip); - rc = tpm_dev_add_device(chip); + rc = tpm_add_char_device(chip); if (rc) goto out_err; @@ -274,6 +276,6 @@ void tpm_chip_unregister(struct tpm_chip *chip) sysfs_remove_link(&chip->pdev->kobj, "ppi"); tpm1_chip_unregister(chip); - tpm_dev_del_device(chip); + tpm_del_char_device(chip); } EXPORT_SYMBOL_GPL(tpm_chip_unregister); diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 8342cf51f..26bab5a29 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -302,11 +302,11 @@ static int crb_acpi_remove(struct acpi_device *device) struct device *dev = &device->dev; struct tpm_chip *chip = dev_get_drvdata(dev); - tpm_chip_unregister(chip); - if (chip->flags & TPM_CHIP_FLAG_TPM2) tpm2_shutdown(chip, TPM2_SU_CLEAR); + tpm_chip_unregister(chip); + return 0; } diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c index bd72fb042..4e6940acf 100644 --- a/drivers/char/tpm/tpm_eventlog.c +++ b/drivers/char/tpm/tpm_eventlog.c @@ -232,7 +232,7 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) { struct tcpa_event *event = v; struct tcpa_event temp_event; - char *tempPtr; + char *temp_ptr; int i; memcpy(&temp_event, event, sizeof(struct tcpa_event)); @@ -242,10 +242,16 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) temp_event.event_type = do_endian_conversion(event->event_type); temp_event.event_size = do_endian_conversion(event->event_size); - tempPtr = (char *)&temp_event; + temp_ptr = (char *) &temp_event; - for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++) - seq_putc(m, tempPtr[i]); + for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++) + seq_putc(m, temp_ptr[i]); + + temp_ptr = (char *) v; + + for (i = (sizeof(struct tcpa_event) - 1); + i < (sizeof(struct tcpa_event) + temp_event.event_size); i++) + seq_putc(m, temp_ptr[i]); return 0; diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 015e687ff..9f4df8f64 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1107,13 +1107,15 @@ static int bcm2835_pll_divider_set_rate(struct clk_hw *hw, struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw); struct bcm2835_cprman *cprman = divider->cprman; const struct bcm2835_pll_divider_data *data = divider->data; - u32 cm; - int ret; + u32 cm, div, max_div = 1 << A2W_PLL_DIV_BITS; - ret = clk_divider_ops.set_rate(hw, rate, parent_rate); - if (ret) - return ret; + div = DIV_ROUND_UP_ULL(parent_rate, rate); + + div = min(div, max_div); + if (div == max_div) + div = 0; + cprman_write(cprman, data->a2w_reg, div); cm = cprman_read(cprman, data->cm_reg); cprman_write(cprman, data->cm_reg, cm | data->load_mask); cprman_write(cprman, data->cm_reg, cm & ~data->load_mask); diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 7f7444cbf..05263571c 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -748,6 +748,7 @@ static const char *const rk3188_critical_clocks[] __initconst = { "hclk_peri", "pclk_cpu", "pclk_peri", + "hclk_cpubus" }; static void __init rk3188_common_clk_init(struct device_node *np) diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 21f3ea909..57acb625c 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -165,7 +165,7 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = { .core_reg = RK3368_CLKSEL_CON(0), .div_core_shift = 0, .div_core_mask = 0x1f, - .mux_core_shift = 15, + .mux_core_shift = 7, }; static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { @@ -218,29 +218,29 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { } static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = { - RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6), - RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5), - RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5), - RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4), - RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4), - RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3), - RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3), - RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2), - RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2), - RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2), + RK3368_CPUCLKB_RATE(1512000000, 1, 5, 5), + RK3368_CPUCLKB_RATE(1488000000, 1, 4, 4), + RK3368_CPUCLKB_RATE(1416000000, 1, 4, 4), + RK3368_CPUCLKB_RATE(1200000000, 1, 3, 3), + RK3368_CPUCLKB_RATE(1008000000, 1, 3, 3), + RK3368_CPUCLKB_RATE( 816000000, 1, 2, 2), + RK3368_CPUCLKB_RATE( 696000000, 1, 2, 2), + RK3368_CPUCLKB_RATE( 600000000, 1, 1, 1), + RK3368_CPUCLKB_RATE( 408000000, 1, 1, 1), + RK3368_CPUCLKB_RATE( 312000000, 1, 1, 1), }; static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = { - RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7), - RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6), - RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6), - RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5), - RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5), - RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4), - RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3), - RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3), - RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2), - RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2), + RK3368_CPUCLKL_RATE(1512000000, 1, 6, 6), + RK3368_CPUCLKL_RATE(1488000000, 1, 5, 5), + RK3368_CPUCLKL_RATE(1416000000, 1, 5, 5), + RK3368_CPUCLKL_RATE(1200000000, 1, 4, 4), + RK3368_CPUCLKL_RATE(1008000000, 1, 4, 4), + RK3368_CPUCLKL_RATE( 816000000, 1, 3, 3), + RK3368_CPUCLKL_RATE( 696000000, 1, 2, 2), + RK3368_CPUCLKL_RATE( 600000000, 1, 2, 2), + RK3368_CPUCLKL_RATE( 408000000, 1, 1, 1), + RK3368_CPUCLKL_RATE( 312000000, 1, 1, 1), }; static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { @@ -384,10 +384,10 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { * Clock-Architecture Diagram 3 */ - COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0, + COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_npll_usb_p, 0, RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3368_CLKGATE_CON(4), 6, GFLAGS), - COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0, + COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_npll_usb_p, 0, RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3368_CLKGATE_CON(4), 7, GFLAGS), @@ -442,7 +442,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0, RK3368_CLKGATE_CON(4), 13, GFLAGS), GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0, - RK3368_CLKGATE_CON(5), 12, GFLAGS), + RK3368_CLKGATE_CON(4), 12, GFLAGS), COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0, RK3368_CLKSEL_CON(21), 15, 1, MFLAGS, diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index e979ec78b..da8b7b9f4 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1900,6 +1901,12 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, } out: + if (likely(retval != -EINVAL)) { + if (target_freq == policy->max) + cpu_nonscaling(policy->cpu); + else + cpu_scaling(policy->cpu); + } return retval; } EXPORT_SYMBOL_GPL(__cpufreq_driver_target); diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 606ad74ab..ce8a7e14d 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -15,8 +15,14 @@ #include "cpufreq_governor.h" /* Conservative governor macros */ +#ifdef CONFIG_SCHED_BFS +#define DEF_FREQUENCY_UP_THRESHOLD (63) +#define DEF_FREQUENCY_DOWN_THRESHOLD (26) +#else #define DEF_FREQUENCY_UP_THRESHOLD (80) #define DEF_FREQUENCY_DOWN_THRESHOLD (20) +#endif + #define DEF_FREQUENCY_STEP (5) #define DEF_SAMPLING_DOWN_FACTOR (1) #define MAX_SAMPLING_DOWN_FACTOR (10) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 9e6fe9e86..38fbd8771 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -19,7 +19,12 @@ #include "cpufreq_governor.h" /* On-demand governor macros */ +#ifdef CONFIG_SCHED_BFS +#define DEF_FREQUENCY_UP_THRESHOLD (63) +#else #define DEF_FREQUENCY_UP_THRESHOLD (80) +#endif + #ifdef CONFIG_PCK_INTERACTIVE #define DEF_SAMPLING_DOWN_FACTOR (10) #else diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index cd83d477e..0248282d4 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -575,8 +575,13 @@ static void atom_set_pstate(struct cpudata *cpudata, int pstate) vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max); vid = ceiling_fp(vid_fp); - if (pstate > cpudata->pstate.max_pstate) - vid = cpudata->vid.turbo; + if (pstate < cpudata->pstate.max_pstate) + cpu_scaling(cpudata->cpu); + else { + if (pstate > cpudata->pstate.max_pstate) + vid = cpudata->vid.turbo; + cpu_nonscaling(cpudata->cpu); + } val |= vid; diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 3eb3f1279..7de007abe 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -2085,9 +2085,9 @@ static int atmel_aes_probe(struct platform_device *pdev) } aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res); - if (!aes_dd->io_base) { + if (IS_ERR(aes_dd->io_base)) { dev_err(dev, "can't ioremap\n"); - err = -ENOMEM; + err = PTR_ERR(aes_dd->io_base); goto res_err; } diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 8bf9914d4..68d47a2da 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -1404,9 +1404,9 @@ static int atmel_sha_probe(struct platform_device *pdev) } sha_dd->io_base = devm_ioremap_resource(&pdev->dev, sha_res); - if (!sha_dd->io_base) { + if (IS_ERR(sha_dd->io_base)) { dev_err(dev, "can't ioremap\n"); - err = -ENOMEM; + err = PTR_ERR(sha_dd->io_base); goto res_err; } diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index 2c7a628d0..bf467d7be 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -1417,9 +1417,9 @@ static int atmel_tdes_probe(struct platform_device *pdev) } tdes_dd->io_base = devm_ioremap_resource(&pdev->dev, tdes_res); - if (!tdes_dd->io_base) { + if (IS_ERR(tdes_dd->io_base)) { dev_err(dev, "can't ioremap\n"); - err = -ENOMEM; + err = PTR_ERR(tdes_dd->io_base); goto res_err; } diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c index d89f20c04..3d9acc53d 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -220,6 +220,39 @@ static int ccp_aes_cmac_digest(struct ahash_request *req) return ccp_aes_cmac_finup(req); } +static int ccp_aes_cmac_export(struct ahash_request *req, void *out) +{ + struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); + struct ccp_aes_cmac_exp_ctx state; + + state.null_msg = rctx->null_msg; + memcpy(state.iv, rctx->iv, sizeof(state.iv)); + state.buf_count = rctx->buf_count; + memcpy(state.buf, rctx->buf, sizeof(state.buf)); + + /* 'out' may not be aligned so memcpy from local variable */ + memcpy(out, &state, sizeof(state)); + + return 0; +} + +static int ccp_aes_cmac_import(struct ahash_request *req, const void *in) +{ + struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); + struct ccp_aes_cmac_exp_ctx state; + + /* 'in' may not be aligned so memcpy to local variable */ + memcpy(&state, in, sizeof(state)); + + memset(rctx, 0, sizeof(*rctx)); + rctx->null_msg = state.null_msg; + memcpy(rctx->iv, state.iv, sizeof(rctx->iv)); + rctx->buf_count = state.buf_count; + memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); + + return 0; +} + static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int key_len) { @@ -352,10 +385,13 @@ int ccp_register_aes_cmac_algs(struct list_head *head) alg->final = ccp_aes_cmac_final; alg->finup = ccp_aes_cmac_finup; alg->digest = ccp_aes_cmac_digest; + alg->export = ccp_aes_cmac_export; + alg->import = ccp_aes_cmac_import; alg->setkey = ccp_aes_cmac_setkey; halg = &alg->halg; halg->digestsize = AES_BLOCK_SIZE; + halg->statesize = sizeof(struct ccp_aes_cmac_exp_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)"); diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index d14b3f28e..8ef06fad8 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -207,6 +207,43 @@ static int ccp_sha_digest(struct ahash_request *req) return ccp_sha_finup(req); } +static int ccp_sha_export(struct ahash_request *req, void *out) +{ + struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); + struct ccp_sha_exp_ctx state; + + state.type = rctx->type; + state.msg_bits = rctx->msg_bits; + state.first = rctx->first; + memcpy(state.ctx, rctx->ctx, sizeof(state.ctx)); + state.buf_count = rctx->buf_count; + memcpy(state.buf, rctx->buf, sizeof(state.buf)); + + /* 'out' may not be aligned so memcpy from local variable */ + memcpy(out, &state, sizeof(state)); + + return 0; +} + +static int ccp_sha_import(struct ahash_request *req, const void *in) +{ + struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); + struct ccp_sha_exp_ctx state; + + /* 'in' may not be aligned so memcpy to local variable */ + memcpy(&state, in, sizeof(state)); + + memset(rctx, 0, sizeof(*rctx)); + rctx->type = state.type; + rctx->msg_bits = state.msg_bits; + rctx->first = state.first; + memcpy(rctx->ctx, state.ctx, sizeof(rctx->ctx)); + rctx->buf_count = state.buf_count; + memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); + + return 0; +} + static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int key_len) { @@ -403,9 +440,12 @@ static int ccp_register_sha_alg(struct list_head *head, alg->final = ccp_sha_final; alg->finup = ccp_sha_finup; alg->digest = ccp_sha_digest; + alg->export = ccp_sha_export; + alg->import = ccp_sha_import; halg = &alg->halg; halg->digestsize = def->digest_size; + halg->statesize = sizeof(struct ccp_sha_exp_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h index 76a96f0f4..a326ec20b 100644 --- a/drivers/crypto/ccp/ccp-crypto.h +++ b/drivers/crypto/ccp/ccp-crypto.h @@ -129,6 +129,15 @@ struct ccp_aes_cmac_req_ctx { struct ccp_cmd cmd; }; +struct ccp_aes_cmac_exp_ctx { + unsigned int null_msg; + + u8 iv[AES_BLOCK_SIZE]; + + unsigned int buf_count; + u8 buf[AES_BLOCK_SIZE]; +}; + /***** SHA related defines *****/ #define MAX_SHA_CONTEXT_SIZE SHA256_DIGEST_SIZE #define MAX_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE @@ -171,6 +180,19 @@ struct ccp_sha_req_ctx { struct ccp_cmd cmd; }; +struct ccp_sha_exp_ctx { + enum ccp_sha_type type; + + u64 msg_bits; + + unsigned int first; + + u8 ctx[MAX_SHA_CONTEXT_SIZE]; + + unsigned int buf_count; + u8 buf[MAX_SHA_BLOCK_SIZE]; +}; + /***** Common Context Structure *****/ struct ccp_ctx { int (*complete)(struct crypto_async_request *req, int ret); diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c index c0656e7f3..80239ae69 100644 --- a/drivers/crypto/marvell/cesa.c +++ b/drivers/crypto/marvell/cesa.c @@ -420,7 +420,7 @@ static int mv_cesa_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); cesa->regs = devm_ioremap_resource(dev, res); if (IS_ERR(cesa->regs)) - return -ENOMEM; + return PTR_ERR(cesa->regs); ret = mv_cesa_dev_dma_init(cesa); if (ret) diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c index 4c243c1ff..790f7cadc 100644 --- a/drivers/crypto/ux500/cryp/cryp_core.c +++ b/drivers/crypto/ux500/cryp/cryp_core.c @@ -1440,9 +1440,9 @@ static int ux500_cryp_probe(struct platform_device *pdev) device_data->phybase = res->start; device_data->base = devm_ioremap_resource(dev, res); - if (!device_data->base) { + if (IS_ERR(device_data->base)) { dev_err(dev, "[%s]: ioremap failed!", __func__); - ret = -ENOMEM; + ret = PTR_ERR(device_data->base); goto out; } diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c index d6fdc583c..574e87c7f 100644 --- a/drivers/crypto/ux500/hash/hash_core.c +++ b/drivers/crypto/ux500/hash/hash_core.c @@ -1659,9 +1659,9 @@ static int ux500_hash_probe(struct platform_device *pdev) device_data->phybase = res->start; device_data->base = devm_ioremap_resource(dev, res); - if (!device_data->base) { + if (IS_ERR(device_data->base)) { dev_err(dev, "%s: ioremap() failed!\n", __func__); - ret = -ENOMEM; + ret = PTR_ERR(device_data->base); goto out; } spin_lock_init(&device_data->ctx_lock); diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 9eee13ef8..d87a47547 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1452,7 +1452,7 @@ static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range, u64 chan_off; u64 dram_base = get_dram_base(pvt, range); u64 hole_off = f10_dhar_offset(pvt); - u64 dct_sel_base_off = (pvt->dct_sel_hi & 0xFFFFFC00) << 16; + u64 dct_sel_base_off = (u64)(pvt->dct_sel_hi & 0xFFFFFC00) << 16; if (hi_rng) { /* diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index f5c6b97c8..93f0d4120 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1839,8 +1839,8 @@ static void get_memory_layout(const struct mem_ctl_info *mci) edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n", n_tads, gb, (mb*1000)/1024, ((u64)tmp_mb) << 20L, - (u32)TAD_SOCK(reg), - (u32)TAD_CH(reg), + (u32)(1 << TAD_SOCK(reg)), + (u32)TAD_CH(reg) + 1, (u32)TAD_TGT0(reg), (u32)TAD_TGT1(reg), (u32)TAD_TGT2(reg), @@ -2118,7 +2118,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, } ch_way = TAD_CH(reg) + 1; - sck_way = TAD_SOCK(reg) + 1; + sck_way = 1 << TAD_SOCK(reg); if (ch_way == 3) idx = addr >> 6; @@ -2175,7 +2175,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, n_tads, addr, limit, - (u32)TAD_SOCK(reg), + sck_way, ch_way, offset, idx, @@ -2190,18 +2190,12 @@ static int get_memory_error_data(struct mem_ctl_info *mci, offset, addr); return -EINVAL; } - addr -= offset; - /* Store the low bits [0:6] of the addr */ - ch_addr = addr & 0x7f; - /* Remove socket wayness and remove 6 bits */ - addr >>= 6; - addr = div_u64(addr, sck_xch); -#if 0 - /* Divide by channel way */ - addr = addr / ch_way; -#endif - /* Recover the last 6 bits */ - ch_addr |= addr << 6; + + ch_addr = addr - offset; + ch_addr >>= (6 + shiftup); + ch_addr /= ch_way * sck_way; + ch_addr <<= (6 + shiftup); + ch_addr |= addr & ((1 << (6 + shiftup)) - 1); /* * Step 3) Decode rank diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index 0c2f0a61b..0b631e5b5 100644 --- a/drivers/firmware/broadcom/bcm47xx_nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -94,15 +94,14 @@ static int nvram_find_and_copy(void __iomem *iobase, u32 lim) found: __ioread32_copy(nvram_buf, header, sizeof(*header) / 4); - header = (struct nvram_header *)nvram_buf; - nvram_len = header->len; + nvram_len = ((struct nvram_header *)(nvram_buf))->len; if (nvram_len > size) { pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n"); nvram_len = size; } if (nvram_len >= NVRAM_SPACE) { pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", - header->len, NVRAM_SPACE - 1); + nvram_len, NVRAM_SPACE - 1); nvram_len = NVRAM_SPACE - 1; } /* proceed reading data after header */ diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 23196c5fc..99b375c95 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -367,9 +367,11 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc, memcpy(reg_val, chip->reg_output, NBANK(chip)); mutex_lock(&chip->i2c_lock); for(bank=0; bank> ((bank % 4) * 8); + unsigned bankmask = mask[bank / sizeof(*mask)] >> + ((bank % sizeof(*mask)) * 8); if(bankmask) { - unsigned bankval = bits[bank/4] >> ((bank % 4) * 8); + unsigned bankval = bits[bank / sizeof(*bits)] >> + ((bank % sizeof(*bits)) * 8); reg_val[bank] = (reg_val[bank] & ~bankmask) | bankval; } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index 3c895863f..81dc6b654 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c @@ -63,6 +63,10 @@ bool amdgpu_has_atpx(void) { return amdgpu_atpx_priv.atpx_detected; } +bool amdgpu_has_atpx_dgpu_power_cntl(void) { + return amdgpu_atpx_priv.atpx.functions.power_cntl; +} + /** * amdgpu_atpx_call - call an ATPX method * @@ -142,10 +146,6 @@ static void amdgpu_atpx_parse_functions(struct amdgpu_atpx_functions *f, u32 mas */ static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx) { - /* make sure required functions are enabled */ - /* dGPU power control is required */ - atpx->functions.power_cntl = true; - if (atpx->functions.px_params) { union acpi_object *info; struct atpx_px_params output; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 51bfc1145..d6c68d00c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -62,6 +62,12 @@ static const char *amdgpu_asic_name[] = { "LAST", }; +#if defined(CONFIG_VGA_SWITCHEROO) +bool amdgpu_has_atpx_dgpu_power_cntl(void); +#else +static inline bool amdgpu_has_atpx_dgpu_power_cntl(void) { return false; } +#endif + bool amdgpu_device_is_px(struct drm_device *dev) { struct amdgpu_device *adev = dev->dev_private; @@ -1511,7 +1517,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, if (amdgpu_runtime_pm == 1) runtime = true; - if (amdgpu_device_is_px(ddev)) + if (amdgpu_device_is_px(ddev) && amdgpu_has_atpx_dgpu_power_cntl()) runtime = true; vga_switcheroo_register_client(adev->pdev, &amdgpu_switcheroo_ops, runtime); if (runtime) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index ed90e3b64..8c01e1565 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -32,8 +32,8 @@ #include "oss/oss_2_4_d.h" #include "oss/oss_2_4_sh_mask.h" -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" #include "gca/gfx_8_0_d.h" #include "gca/gfx_8_0_enum.h" diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index cf01177ca..2ea012e88 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -241,6 +241,11 @@ static int cz_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicUVDState); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEDPM); + cz_hwmgr->cc6_settings.cpu_cc6_disable = false; cz_hwmgr->cc6_settings.cpu_pstate_disable = false; cz_hwmgr->cc6_settings.nb_pstate_switch_disable = false; diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 01b20e14a..6104d7d74 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -892,8 +892,6 @@ atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_m else args.v1.ucLaneNum = 4; - if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000)) - args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; @@ -910,6 +908,10 @@ atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_m args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; else args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; + + if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000)) + args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; + break; case 2: case 3: diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index c4b4f298a..9bc408c9f 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -62,6 +62,10 @@ bool radeon_has_atpx(void) { return radeon_atpx_priv.atpx_detected; } +bool radeon_has_atpx_dgpu_power_cntl(void) { + return radeon_atpx_priv.atpx.functions.power_cntl; +} + /** * radeon_atpx_call - call an ATPX method * @@ -141,10 +145,6 @@ static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mas */ static int radeon_atpx_validate(struct radeon_atpx *atpx) { - /* make sure required functions are enabled */ - /* dGPU power control is required */ - atpx->functions.power_cntl = true; - if (atpx->functions.px_params) { union acpi_object *info; struct atpx_px_params output; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 4197ca1bb..e2396336f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -103,6 +103,12 @@ static const char radeon_family_name[][16] = { "LAST", }; +#if defined(CONFIG_VGA_SWITCHEROO) +bool radeon_has_atpx_dgpu_power_cntl(void); +#else +static inline bool radeon_has_atpx_dgpu_power_cntl(void) { return false; } +#endif + #define RADEON_PX_QUIRK_DISABLE_PX (1 << 0) #define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1) @@ -1433,7 +1439,7 @@ int radeon_device_init(struct radeon_device *rdev, * ignore it */ vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); - if (rdev->flags & RADEON_IS_PX) + if ((rdev->flags & RADEON_IS_PX) && radeon_has_atpx_dgpu_power_cntl()) runtime = true; vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime); if (runtime) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 2d9196a44..bfcef4db8 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1683,10 +1683,8 @@ int radeon_modeset_init(struct radeon_device *rdev) /* setup afmt */ radeon_afmt_init(rdev); - if (!list_empty(&rdev->ddev->mode_config.connector_list)) { - radeon_fbdev_init(rdev); - drm_kms_helper_poll_init(rdev->ddev); - } + radeon_fbdev_init(rdev); + drm_kms_helper_poll_init(rdev->ddev); /* do pm late init */ ret = radeon_pm_late_init(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index df7a1719c..9d210bbca 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c @@ -525,17 +525,9 @@ static bool radeon_mst_mode_fixup(struct drm_encoder *encoder, drm_mode_set_crtcinfo(adjusted_mode, 0); { struct radeon_connector_atom_dig *dig_connector; - int ret; - dig_connector = mst_enc->connector->con_priv; - ret = radeon_dp_get_dp_link_config(&mst_enc->connector->base, - dig_connector->dpcd, adjusted_mode->clock, - &dig_connector->dp_lane_count, - &dig_connector->dp_clock); - if (ret) { - dig_connector->dp_lane_count = 0; - dig_connector->dp_clock = 0; - } + dig_connector->dp_lane_count = drm_dp_max_lane_count(dig_connector->dpcd); + dig_connector->dp_clock = drm_dp_max_link_rate(dig_connector->dpcd); DRM_DEBUG_KMS("dig clock %p %d %d\n", dig_connector, dig_connector->dp_lane_count, dig_connector->dp_clock); } diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index d2e628eea..d17959633 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -292,7 +292,8 @@ out_unref: void radeon_fb_output_poll_changed(struct radeon_device *rdev) { - drm_fb_helper_hotplug_event(&rdev->mode_info.rfbdev->helper); + if (rdev->mode_info.rfbdev) + drm_fb_helper_hotplug_event(&rdev->mode_info.rfbdev->helper); } static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev) @@ -325,6 +326,10 @@ int radeon_fbdev_init(struct radeon_device *rdev) int bpp_sel = 32; int ret; + /* don't enable fbdev if no connectors */ + if (list_empty(&rdev->ddev->mode_config.connector_list)) + return 0; + /* select 8 bpp console on RN50 or 16MB cards */ if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024)) bpp_sel = 8; @@ -377,11 +382,15 @@ void radeon_fbdev_fini(struct radeon_device *rdev) void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state) { - fb_set_suspend(rdev->mode_info.rfbdev->helper.fbdev, state); + if (rdev->mode_info.rfbdev) + fb_set_suspend(rdev->mode_info.rfbdev->helper.fbdev, state); } bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) { + if (!rdev->mode_info.rfbdev) + return false; + if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj)) return true; return false; @@ -389,12 +398,14 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) void radeon_fb_add_connector(struct radeon_device *rdev, struct drm_connector *connector) { - drm_fb_helper_add_one_connector(&rdev->mode_info.rfbdev->helper, connector); + if (rdev->mode_info.rfbdev) + drm_fb_helper_add_one_connector(&rdev->mode_info.rfbdev->helper, connector); } void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector *connector) { - drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector); + if (rdev->mode_info.rfbdev) + drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector); } void radeon_fbdev_restore_mode(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 22278bcfc..ac8eafea6 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -499,11 +499,12 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, if (IS_ERR(bo)) return PTR_ERR(bo); - ret = copy_from_user(bo->base.vaddr, + if (copy_from_user(bo->base.vaddr, (void __user *)(uintptr_t)args->data, - args->size); - if (ret != 0) + args->size)) { + ret = -EFAULT; goto fail; + } /* Clear the rest of the memory from allocating from the BO * cache. */ diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7e89288b1..99446ffd7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1891,6 +1891,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, @@ -2615,9 +2616,10 @@ int hid_add_device(struct hid_device *hdev) /* * Scan generic devices for group information */ - if (hid_ignore_special_drivers || - (!hdev->group && - !hid_match_id(hdev, hid_have_special_driver))) { + if (hid_ignore_special_drivers) { + hdev->group = HID_GROUP_GENERIC; + } else if (!hdev->group && + !hid_match_id(hdev, hid_have_special_driver)) { ret = hid_scan_report(hdev); if (ret) hid_warn(hdev, "bad device descriptor (%d)\n", ret); diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 296d49915..a20fc604f 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -396,6 +396,11 @@ static void mt_feature_mapping(struct hid_device *hdev, td->is_buttonpad = true; break; + case 0xff0000c5: + /* Retrieve the Win8 blob once to enable some devices */ + if (usage->usage_index == 0) + mt_get_feature(hdev, field->report); + break; } } diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index b9216938a..bb897497f 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -283,17 +283,21 @@ static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType, u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister); u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister); u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength); + u16 size; + int args_len; + int index = 0; + + i2c_hid_dbg(ihid, "%s\n", __func__); + + if (data_len > ihid->bufsize) + return -EINVAL; - /* hid_hw_* already checked that data_len < HID_MAX_BUFFER_SIZE */ - u16 size = 2 /* size */ + + size = 2 /* size */ + (reportID ? 1 : 0) /* reportID */ + data_len /* buf */; - int args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ + + args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ + 2 /* dataRegister */ + size /* args */; - int index = 0; - - i2c_hid_dbg(ihid, "%s\n", __func__); if (!use_data && maxOutputLength == 0) return -ENOSYS; diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index cd4510a63..146eed70b 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -65,7 +65,7 @@ #include #include -#define INTEL_IDLE_VERSION "0.4" +#define INTEL_IDLE_VERSION "0.4.1" #define PREFIX "intel_idle: " static struct cpuidle_driver intel_idle_driver = { @@ -994,36 +994,92 @@ static void intel_idle_cpuidle_devices_uninit(void) } /* - * intel_idle_state_table_update() - * - * Update the default state_table for this CPU-id + * ivt_idle_state_table_update(void) * - * Currently used to access tuned IVT multi-socket targets + * Tune IVT multi-socket targets * Assumption: num_sockets == (max_package_num + 1) */ -void intel_idle_state_table_update(void) +static void ivt_idle_state_table_update(void) { /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */ - if (boot_cpu_data.x86_model == 0x3e) { /* IVT */ - int cpu, package_num, num_sockets = 1; - - for_each_online_cpu(cpu) { - package_num = topology_physical_package_id(cpu); - if (package_num + 1 > num_sockets) { - num_sockets = package_num + 1; - - if (num_sockets > 4) { - cpuidle_state_table = ivt_cstates_8s; - return; - } + int cpu, package_num, num_sockets = 1; + + for_each_online_cpu(cpu) { + package_num = topology_physical_package_id(cpu); + if (package_num + 1 > num_sockets) { + num_sockets = package_num + 1; + + if (num_sockets > 4) { + cpuidle_state_table = ivt_cstates_8s; + return; } } + } + + if (num_sockets > 2) + cpuidle_state_table = ivt_cstates_4s; + + /* else, 1 and 2 socket systems use default ivt_cstates */ +} +/* + * sklh_idle_state_table_update(void) + * + * On SKL-H (model 0x5e) disable C8 and C9 if: + * C10 is enabled and SGX disabled + */ +static void sklh_idle_state_table_update(void) +{ + unsigned long long msr; + unsigned int eax, ebx, ecx, edx; + + + /* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */ + if (max_cstate <= 7) + return; + + /* if PC10 not present in CPUID.MWAIT.EDX */ + if ((mwait_substates & (0xF << 28)) == 0) + return; + + rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr); + + /* PC10 is not enabled in PKG C-state limit */ + if ((msr & 0xF) != 8) + return; + + ecx = 0; + cpuid(7, &eax, &ebx, &ecx, &edx); + + /* if SGX is present */ + if (ebx & (1 << 2)) { - if (num_sockets > 2) - cpuidle_state_table = ivt_cstates_4s; - /* else, 1 and 2 socket systems use default ivt_cstates */ + rdmsrl(MSR_IA32_FEATURE_CONTROL, msr); + + /* if SGX is enabled */ + if (msr & (1 << 18)) + return; + } + + skl_cstates[5].disabled = 1; /* C8-SKL */ + skl_cstates[6].disabled = 1; /* C9-SKL */ +} +/* + * intel_idle_state_table_update() + * + * Update the default state_table for this CPU-id + */ + +static void intel_idle_state_table_update(void) +{ + switch (boot_cpu_data.x86_model) { + + case 0x3e: /* IVT */ + ivt_idle_state_table_update(); + break; + case 0x5e: /* SKL-H */ + sklh_idle_state_table_update(); + break; } - return; } /* @@ -1063,6 +1119,14 @@ static int __init intel_idle_cpuidle_driver_init(void) if (num_substates == 0) continue; + /* if state marked as disabled, skip it */ + if (cpuidle_state_table[cstate].disabled != 0) { + pr_debug(PREFIX "state %s is disabled", + cpuidle_state_table[cstate].name); + continue; + } + + if (((mwait_cstate + 1) > 2) && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) mark_tsc_unstable("TSC halts in idle" diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index f121e6129..0e1a802c3 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -65,6 +65,7 @@ isert_rdma_accept(struct isert_conn *isert_conn); struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np); static void isert_release_work(struct work_struct *work); +static void isert_wait4flush(struct isert_conn *isert_conn); static inline bool isert_prot_cmd(struct isert_conn *conn, struct se_cmd *cmd) @@ -820,12 +821,31 @@ isert_put_conn(struct isert_conn *isert_conn) kref_put(&isert_conn->kref, isert_release_kref); } +static void +isert_handle_unbound_conn(struct isert_conn *isert_conn) +{ + struct isert_np *isert_np = isert_conn->cm_id->context; + + mutex_lock(&isert_np->mutex); + if (!list_empty(&isert_conn->node)) { + /* + * This means iscsi doesn't know this connection + * so schedule a cleanup ourselves + */ + list_del_init(&isert_conn->node); + isert_put_conn(isert_conn); + complete(&isert_conn->wait); + queue_work(isert_release_wq, &isert_conn->release_work); + } + mutex_unlock(&isert_np->mutex); +} + /** * isert_conn_terminate() - Initiate connection termination * @isert_conn: isert connection struct * * Notes: - * In case the connection state is FULL_FEATURE, move state + * In case the connection state is BOUND, move state * to TEMINATING and start teardown sequence (rdma_disconnect). * In case the connection state is UP, complete flush as well. * @@ -837,23 +857,19 @@ isert_conn_terminate(struct isert_conn *isert_conn) { int err; - switch (isert_conn->state) { - case ISER_CONN_TERMINATING: - break; - case ISER_CONN_UP: - case ISER_CONN_FULL_FEATURE: /* FALLTHRU */ - isert_info("Terminating conn %p state %d\n", - isert_conn, isert_conn->state); - isert_conn->state = ISER_CONN_TERMINATING; - err = rdma_disconnect(isert_conn->cm_id); - if (err) - isert_warn("Failed rdma_disconnect isert_conn %p\n", - isert_conn); - break; - default: - isert_warn("conn %p teminating in state %d\n", - isert_conn, isert_conn->state); - } + if (isert_conn->state >= ISER_CONN_TERMINATING) + return; + + isert_info("Terminating conn %p state %d\n", + isert_conn, isert_conn->state); + isert_conn->state = ISER_CONN_TERMINATING; + err = rdma_disconnect(isert_conn->cm_id); + if (err) + isert_warn("Failed rdma_disconnect isert_conn %p\n", + isert_conn); + + isert_info("conn %p completing wait\n", isert_conn); + complete(&isert_conn->wait); } static int @@ -887,35 +903,27 @@ static int isert_disconnected_handler(struct rdma_cm_id *cma_id, enum rdma_cm_event_type event) { - struct isert_np *isert_np = cma_id->context; - struct isert_conn *isert_conn; - bool terminating = false; - - if (isert_np->cm_id == cma_id) - return isert_np_cma_handler(cma_id->context, event); - - isert_conn = cma_id->qp->qp_context; + struct isert_conn *isert_conn = cma_id->qp->qp_context; mutex_lock(&isert_conn->mutex); - terminating = (isert_conn->state == ISER_CONN_TERMINATING); - isert_conn_terminate(isert_conn); - mutex_unlock(&isert_conn->mutex); - - isert_info("conn %p completing wait\n", isert_conn); - complete(&isert_conn->wait); - - if (terminating) - goto out; - - mutex_lock(&isert_np->mutex); - if (!list_empty(&isert_conn->node)) { - list_del_init(&isert_conn->node); - isert_put_conn(isert_conn); - queue_work(isert_release_wq, &isert_conn->release_work); + switch (isert_conn->state) { + case ISER_CONN_TERMINATING: + break; + case ISER_CONN_UP: + isert_conn_terminate(isert_conn); + isert_wait4flush(isert_conn); + isert_handle_unbound_conn(isert_conn); + break; + case ISER_CONN_BOUND: + case ISER_CONN_FULL_FEATURE: /* FALLTHRU */ + iscsit_cause_connection_reinstatement(isert_conn->conn, 0); + break; + default: + isert_warn("conn %p teminating in state %d\n", + isert_conn, isert_conn->state); } - mutex_unlock(&isert_np->mutex); + mutex_unlock(&isert_conn->mutex); -out: return 0; } @@ -934,12 +942,16 @@ isert_connect_error(struct rdma_cm_id *cma_id) static int isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) { + struct isert_np *isert_np = cma_id->context; int ret = 0; isert_info("%s (%d): status %d id %p np %p\n", rdma_event_msg(event->event), event->event, event->status, cma_id, cma_id->context); + if (isert_np->cm_id == cma_id) + return isert_np_cma_handler(cma_id->context, event->event); + switch (event->event) { case RDMA_CM_EVENT_CONNECT_REQUEST: ret = isert_connect_request(cma_id, event); @@ -985,13 +997,10 @@ isert_post_recvm(struct isert_conn *isert_conn, u32 count) rx_wr--; rx_wr->next = NULL; /* mark end of work requests list */ - isert_conn->post_recv_buf_count += count; ret = ib_post_recv(isert_conn->qp, isert_conn->rx_wr, &rx_wr_failed); - if (ret) { + if (ret) isert_err("ib_post_recv() failed with ret: %d\n", ret); - isert_conn->post_recv_buf_count -= count; - } return ret; } @@ -1007,12 +1016,9 @@ isert_post_recv(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc) rx_wr.num_sge = 1; rx_wr.next = NULL; - isert_conn->post_recv_buf_count++; ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_failed); - if (ret) { + if (ret) isert_err("ib_post_recv() failed with ret: %d\n", ret); - isert_conn->post_recv_buf_count--; - } return ret; } @@ -1132,12 +1138,9 @@ isert_rdma_post_recvl(struct isert_conn *isert_conn) rx_wr.sg_list = &sge; rx_wr.num_sge = 1; - isert_conn->post_recv_buf_count++; ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_fail); - if (ret) { + if (ret) isert_err("ib_post_recv() failed: %d\n", ret); - isert_conn->post_recv_buf_count--; - } return ret; } @@ -1633,7 +1636,6 @@ isert_rcv_completion(struct iser_rx_desc *desc, ib_dma_sync_single_for_device(ib_dev, rx_dma, rx_buflen, DMA_FROM_DEVICE); - isert_conn->post_recv_buf_count--; } static int @@ -2048,7 +2050,8 @@ is_isert_tx_desc(struct isert_conn *isert_conn, void *wr_id) void *start = isert_conn->rx_descs; int len = ISERT_QP_MAX_RECV_DTOS * sizeof(*isert_conn->rx_descs); - if (wr_id >= start && wr_id < start + len) + if ((wr_id >= start && wr_id < start + len) || + (wr_id == isert_conn->login_req_buf)) return false; return true; @@ -2072,10 +2075,6 @@ isert_cq_comp_err(struct isert_conn *isert_conn, struct ib_wc *wc) isert_unmap_tx_desc(desc, ib_dev); else isert_completion_put(desc, isert_cmd, ib_dev, true); - } else { - isert_conn->post_recv_buf_count--; - if (!isert_conn->post_recv_buf_count) - iscsit_cause_connection_reinstatement(isert_conn->conn, 0); } } @@ -3214,6 +3213,7 @@ accept_wait: conn->context = isert_conn; isert_conn->conn = conn; + isert_conn->state = ISER_CONN_BOUND; isert_set_conn_info(np, conn, isert_conn); diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 8d50453ee..1aa019ab9 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -84,6 +84,7 @@ enum iser_ib_op_code { enum iser_conn_state { ISER_CONN_INIT, ISER_CONN_UP, + ISER_CONN_BOUND, ISER_CONN_FULL_FEATURE, ISER_CONN_TERMINATING, ISER_CONN_DOWN, @@ -179,7 +180,6 @@ struct isert_device; struct isert_conn { enum iser_conn_state state; - int post_recv_buf_count; u32 responder_resources; u32 initiator_depth; bool pi_support; diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 0c37fee36..4328679a6 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1670,47 +1670,6 @@ send_sense: return -1; } -/** - * srpt_rx_mgmt_fn_tag() - Process a task management function by tag. - * @ch: RDMA channel of the task management request. - * @fn: Task management function to perform. - * @req_tag: Tag of the SRP task management request. - * @mgmt_ioctx: I/O context of the task management request. - * - * Returns zero if the target core will process the task management - * request asynchronously. - * - * Note: It is assumed that the initiator serializes tag-based task management - * requests. - */ -static int srpt_rx_mgmt_fn_tag(struct srpt_send_ioctx *ioctx, u64 tag) -{ - struct srpt_device *sdev; - struct srpt_rdma_ch *ch; - struct srpt_send_ioctx *target; - int ret, i; - - ret = -EINVAL; - ch = ioctx->ch; - BUG_ON(!ch); - BUG_ON(!ch->sport); - sdev = ch->sport->sdev; - BUG_ON(!sdev); - spin_lock_irq(&sdev->spinlock); - for (i = 0; i < ch->rq_size; ++i) { - target = ch->ioctx_ring[i]; - if (target->cmd.se_lun == ioctx->cmd.se_lun && - target->cmd.tag == tag && - srpt_get_cmd_state(target) != SRPT_STATE_DONE) { - ret = 0; - /* now let the target core abort &target->cmd; */ - break; - } - } - spin_unlock_irq(&sdev->spinlock); - return ret; -} - static int srp_tmr_to_tcm(int fn) { switch (fn) { @@ -1745,7 +1704,6 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, struct se_cmd *cmd; struct se_session *sess = ch->sess; uint64_t unpacked_lun; - uint32_t tag = 0; int tcm_tmr; int rc; @@ -1761,25 +1719,10 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT); send_ioctx->cmd.tag = srp_tsk->tag; tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); - if (tcm_tmr < 0) { - send_ioctx->cmd.se_tmr_req->response = - TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; - goto fail; - } unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun, sizeof(srp_tsk->lun)); - - if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) { - rc = srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); - if (rc < 0) { - send_ioctx->cmd.se_tmr_req->response = - TMR_TASK_DOES_NOT_EXIST; - goto fail; - } - tag = srp_tsk->task_tag; - } rc = target_submit_tmr(&send_ioctx->cmd, sess, NULL, unpacked_lun, - srp_tsk, tcm_tmr, GFP_KERNEL, tag, + srp_tsk, tcm_tmr, GFP_KERNEL, srp_tsk->task_tag, TARGET_SCF_ACK_KREF); if (rc != 0) { send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index cfd58e87d..1c5914cae 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -817,26 +817,49 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d ar2->udev = udev; + /* Sanity check, first interface must have an endpoint */ + if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) { + dev_err(&interface->dev, + "%s(): interface 0 must have an endpoint\n", __func__); + r = -ENODEV; + goto fail1; + } ar2->intf[0] = interface; ar2->ep[0] = &alt->endpoint[0].desc; + /* Sanity check, the device must have two interfaces */ ar2->intf[1] = usb_ifnum_to_if(udev, 1); + if ((udev->actconfig->desc.bNumInterfaces < 2) || !ar2->intf[1]) { + dev_err(&interface->dev, "%s(): need 2 interfaces, found %d\n", + __func__, udev->actconfig->desc.bNumInterfaces); + r = -ENODEV; + goto fail1; + } + r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2); if (r) goto fail1; + + /* Sanity check, second interface must have an endpoint */ alt = ar2->intf[1]->cur_altsetting; + if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) { + dev_err(&interface->dev, + "%s(): interface 1 must have an endpoint\n", __func__); + r = -ENODEV; + goto fail2; + } ar2->ep[1] = &alt->endpoint[0].desc; r = ati_remote2_urb_init(ar2); if (r) - goto fail2; + goto fail3; ar2->channel_mask = channel_mask; ar2->mode_mask = mode_mask; r = ati_remote2_setup(ar2, ar2->channel_mask); if (r) - goto fail2; + goto fail3; usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); @@ -845,11 +868,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group); if (r) - goto fail2; + goto fail3; r = ati_remote2_input_init(ar2); if (r) - goto fail3; + goto fail4; usb_set_intfdata(interface, ar2); @@ -857,10 +880,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d return 0; - fail3: + fail4: sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group); - fail2: + fail3: ati_remote2_urb_cleanup(ar2); + fail2: usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); fail1: kfree(ar2); diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index 43d082530..f47851868 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -1663,6 +1663,8 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc pcu->ctrl_intf = usb_ifnum_to_if(pcu->udev, union_desc->bMasterInterface0); + if (!pcu->ctrl_intf) + return -EINVAL; alt = pcu->ctrl_intf->cur_altsetting; pcu->ep_ctrl = &alt->endpoint[0].desc; @@ -1670,6 +1672,8 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc pcu->data_intf = usb_ifnum_to_if(pcu->udev, union_desc->bSlaveInterface0); + if (!pcu->data_intf) + return -EINVAL; alt = pcu->data_intf->cur_altsetting; if (alt->desc.bNumEndpoints != 2) { diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index 63b539d3d..84909a12f 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -307,6 +307,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i int error = -ENOMEM; interface = intf->cur_altsetting; + if (interface->desc.bNumEndpoints < 1) + return -EINVAL; + endpoint = &interface->endpoint[0].desc; if (!usb_endpoint_is_int_in(endpoint)) return -EIO; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index e678212f1..a5c2eb291 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -862,8 +862,9 @@ static void synaptics_report_ext_buttons(struct psmouse *psmouse, if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) return; - /* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */ - if (SYN_ID_FULL(priv->identity) == 0x801 && + /* Bug in FW 8.1 & 8.2, buttons are reported only when ExtBit is 1 */ + if ((SYN_ID_FULL(priv->identity) == 0x801 || + SYN_ID_FULL(priv->identity) == 0x802) && !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02)) return; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 8d0ead98e..a296425a7 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1015,8 +1015,12 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c) */ atomic_set(&dc->count, 1); - if (bch_cached_dev_writeback_start(dc)) + /* Block writeback thread, but spawn it */ + down_write(&dc->writeback_lock); + if (bch_cached_dev_writeback_start(dc)) { + up_write(&dc->writeback_lock); return -ENOMEM; + } if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) { bch_sectors_dirty_init(dc); @@ -1028,6 +1032,9 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c) bch_cached_dev_run(dc); bcache_device_link(&dc->disk, c, "bdev"); + /* Allow the writeback thread to proceed */ + up_write(&dc->writeback_lock); + pr_info("Caching %s as %s on set %pU", bdevname(dc->bdev, buf), dc->disk.disk->disk_name, dc->disk.c->sb.set_uuid); @@ -1366,6 +1373,9 @@ static void cache_set_flush(struct closure *cl) struct btree *b; unsigned i; + if (!c) + closure_return(cl); + bch_cache_accounting_destroy(&c->accounting); kobject_put(&c->internal); @@ -1828,11 +1838,12 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca) return 0; } -static void register_cache(struct cache_sb *sb, struct page *sb_page, +static int register_cache(struct cache_sb *sb, struct page *sb_page, struct block_device *bdev, struct cache *ca) { char name[BDEVNAME_SIZE]; - const char *err = "cannot allocate memory"; + const char *err = NULL; + int ret = 0; memcpy(&ca->sb, sb, sizeof(struct cache_sb)); ca->bdev = bdev; @@ -1847,27 +1858,35 @@ static void register_cache(struct cache_sb *sb, struct page *sb_page, if (blk_queue_discard(bdev_get_queue(ca->bdev))) ca->discard = CACHE_DISCARD(&ca->sb); - if (cache_alloc(sb, ca) != 0) + ret = cache_alloc(sb, ca); + if (ret != 0) goto err; - err = "error creating kobject"; - if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) - goto err; + if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) { + err = "error calling kobject_add"; + ret = -ENOMEM; + goto out; + } mutex_lock(&bch_register_lock); err = register_cache_set(ca); mutex_unlock(&bch_register_lock); - if (err) - goto err; + if (err) { + ret = -ENODEV; + goto out; + } pr_info("registered cache device %s", bdevname(bdev, name)); + out: kobject_put(&ca->kobj); - return; + err: - pr_notice("error opening %s: %s", bdevname(bdev, name), err); - goto out; + if (err) + pr_notice("error opening %s: %s", bdevname(bdev, name), err); + + return ret; } /* Global interfaces/init */ @@ -1965,7 +1984,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, if (!ca) goto err_close; - register_cache(sb, sb_page, bdev, ca); + if (register_cache(sb, sb_page, bdev, ca) != 0) + goto err_close; } out: if (sb_page) diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index f6543f3a9..27f2ef300 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c @@ -867,19 +867,40 @@ static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd, return 0; } -#define WRITE_LOCK(cmd) \ - if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \ +#define WRITE_LOCK(cmd) \ + down_write(&cmd->root_lock); \ + if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ + up_write(&cmd->root_lock); \ return -EINVAL; \ - down_write(&cmd->root_lock) + } #define WRITE_LOCK_VOID(cmd) \ - if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \ + down_write(&cmd->root_lock); \ + if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ + up_write(&cmd->root_lock); \ return; \ - down_write(&cmd->root_lock) + } #define WRITE_UNLOCK(cmd) \ up_write(&cmd->root_lock) +#define READ_LOCK(cmd) \ + down_read(&cmd->root_lock); \ + if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ + up_read(&cmd->root_lock); \ + return -EINVAL; \ + } + +#define READ_LOCK_VOID(cmd) \ + down_read(&cmd->root_lock); \ + if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \ + up_read(&cmd->root_lock); \ + return; \ + } + +#define READ_UNLOCK(cmd) \ + up_read(&cmd->root_lock) + int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size) { int r; @@ -1015,22 +1036,20 @@ int dm_cache_load_discards(struct dm_cache_metadata *cmd, { int r; - down_read(&cmd->root_lock); + READ_LOCK(cmd); r = __load_discards(cmd, fn, context); - up_read(&cmd->root_lock); + READ_UNLOCK(cmd); return r; } -dm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd) +int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result) { - dm_cblock_t r; + READ_LOCK(cmd); + *result = cmd->cache_blocks; + READ_UNLOCK(cmd); - down_read(&cmd->root_lock); - r = cmd->cache_blocks; - up_read(&cmd->root_lock); - - return r; + return 0; } static int __remove(struct dm_cache_metadata *cmd, dm_cblock_t cblock) @@ -1188,9 +1207,9 @@ int dm_cache_load_mappings(struct dm_cache_metadata *cmd, { int r; - down_read(&cmd->root_lock); + READ_LOCK(cmd); r = __load_mappings(cmd, policy, fn, context); - up_read(&cmd->root_lock); + READ_UNLOCK(cmd); return r; } @@ -1215,18 +1234,18 @@ static int __dump_mappings(struct dm_cache_metadata *cmd) void dm_cache_dump(struct dm_cache_metadata *cmd) { - down_read(&cmd->root_lock); + READ_LOCK_VOID(cmd); __dump_mappings(cmd); - up_read(&cmd->root_lock); + READ_UNLOCK(cmd); } int dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd) { int r; - down_read(&cmd->root_lock); + READ_LOCK(cmd); r = cmd->changed; - up_read(&cmd->root_lock); + READ_UNLOCK(cmd); return r; } @@ -1276,9 +1295,9 @@ int dm_cache_set_dirty(struct dm_cache_metadata *cmd, void dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd, struct dm_cache_statistics *stats) { - down_read(&cmd->root_lock); + READ_LOCK_VOID(cmd); *stats = cmd->stats; - up_read(&cmd->root_lock); + READ_UNLOCK(cmd); } void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd, @@ -1312,9 +1331,9 @@ int dm_cache_get_free_metadata_block_count(struct dm_cache_metadata *cmd, { int r = -EINVAL; - down_read(&cmd->root_lock); + READ_LOCK(cmd); r = dm_sm_get_nr_free(cmd->metadata_sm, result); - up_read(&cmd->root_lock); + READ_UNLOCK(cmd); return r; } @@ -1324,9 +1343,9 @@ int dm_cache_get_metadata_dev_size(struct dm_cache_metadata *cmd, { int r = -EINVAL; - down_read(&cmd->root_lock); + READ_LOCK(cmd); r = dm_sm_get_nr_blocks(cmd->metadata_sm, result); - up_read(&cmd->root_lock); + READ_UNLOCK(cmd); return r; } @@ -1417,7 +1436,13 @@ int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy * int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result) { - return blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result); + int r; + + READ_LOCK(cmd); + r = blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result); + READ_UNLOCK(cmd); + + return r; } void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd) @@ -1440,10 +1465,7 @@ int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd) struct dm_block *sblock; struct cache_disk_superblock *disk_super; - /* - * We ignore fail_io for this function. - */ - down_write(&cmd->root_lock); + WRITE_LOCK(cmd); set_bit(NEEDS_CHECK, &cmd->flags); r = superblock_lock(cmd, &sblock); @@ -1458,19 +1480,17 @@ int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd) dm_bm_unlock(sblock); out: - up_write(&cmd->root_lock); + WRITE_UNLOCK(cmd); return r; } -bool dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd) +int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result) { - bool needs_check; + READ_LOCK(cmd); + *result = !!test_bit(NEEDS_CHECK, &cmd->flags); + READ_UNLOCK(cmd); - down_read(&cmd->root_lock); - needs_check = !!test_bit(NEEDS_CHECK, &cmd->flags); - up_read(&cmd->root_lock); - - return needs_check; + return 0; } int dm_cache_metadata_abort(struct dm_cache_metadata *cmd) diff --git a/drivers/md/dm-cache-metadata.h b/drivers/md/dm-cache-metadata.h index 2ffee21f3..852874419 100644 --- a/drivers/md/dm-cache-metadata.h +++ b/drivers/md/dm-cache-metadata.h @@ -66,7 +66,7 @@ void dm_cache_metadata_close(struct dm_cache_metadata *cmd); * origin blocks to map to. */ int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size); -dm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd); +int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result); int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd, sector_t discard_block_size, @@ -137,7 +137,7 @@ int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy * */ int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result); -bool dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd); +int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result); int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd); void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd); void dm_cache_metadata_set_read_write(struct dm_cache_metadata *cmd); diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 5780accff..bb9b92ebb 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -984,9 +984,14 @@ static void notify_mode_switch(struct cache *cache, enum cache_metadata_mode mod static void set_cache_mode(struct cache *cache, enum cache_metadata_mode new_mode) { - bool needs_check = dm_cache_metadata_needs_check(cache->cmd); + bool needs_check; enum cache_metadata_mode old_mode = get_cache_mode(cache); + if (dm_cache_metadata_needs_check(cache->cmd, &needs_check)) { + DMERR("unable to read needs_check flag, setting failure mode"); + new_mode = CM_FAIL; + } + if (new_mode == CM_WRITE && needs_check) { DMERR("%s: unable to switch cache to write mode until repaired.", cache_device_name(cache)); @@ -3510,6 +3515,7 @@ static void cache_status(struct dm_target *ti, status_type_t type, char buf[BDEVNAME_SIZE]; struct cache *cache = ti->private; dm_cblock_t residency; + bool needs_check; switch (type) { case STATUSTYPE_INFO: @@ -3583,7 +3589,9 @@ static void cache_status(struct dm_target *ti, status_type_t type, else DMEMIT("rw "); - if (dm_cache_metadata_needs_check(cache->cmd)) + r = dm_cache_metadata_needs_check(cache->cmd, &needs_check); + + if (r || needs_check) DMEMIT("needs_check "); else DMEMIT("- "); diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 376638608..e4d1bafe7 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1105,6 +1105,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) int i; int r = -EINVAL; char *origin_path, *cow_path; + dev_t origin_dev, cow_dev; unsigned args_used, num_flush_bios = 1; fmode_t origin_mode = FMODE_READ; @@ -1135,11 +1136,19 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->error = "Cannot get origin device"; goto bad_origin; } + origin_dev = s->origin->bdev->bd_dev; cow_path = argv[0]; argv++; argc--; + cow_dev = dm_get_dev_t(cow_path); + if (cow_dev && cow_dev == origin_dev) { + ti->error = "COW device cannot be the same as origin device"; + r = -EINVAL; + goto bad_cow; + } + r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow); if (r) { ti->error = "Cannot get COW device"; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 061152a43..cb5d0daf5 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -364,6 +364,26 @@ static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode, return 0; } +/* + * Convert the path to a device + */ +dev_t dm_get_dev_t(const char *path) +{ + dev_t uninitialized_var(dev); + struct block_device *bdev; + + bdev = lookup_bdev(path); + if (IS_ERR(bdev)) + dev = name_to_dev_t(path); + else { + dev = bdev->bd_dev; + bdput(bdev); + } + + return dev; +} +EXPORT_SYMBOL_GPL(dm_get_dev_t); + /* * Add a device to the list, or just increment the usage count if * it's already present. @@ -372,23 +392,15 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode, struct dm_dev **result) { int r; - dev_t uninitialized_var(dev); + dev_t dev; struct dm_dev_internal *dd; struct dm_table *t = ti->table; - struct block_device *bdev; BUG_ON(!t); - /* convert the path to a device */ - bdev = lookup_bdev(path); - if (IS_ERR(bdev)) { - dev = name_to_dev_t(path); - if (!dev) - return -ENODEV; - } else { - dev = bdev->bd_dev; - bdput(bdev); - } + dev = dm_get_dev_t(path); + if (!dev) + return -ENODEV; dd = find_device(&t->devices, dev); if (!dd) { diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index f962d6453..185010d9c 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -1981,5 +1981,8 @@ bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd) void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd) { - dm_tm_issue_prefetches(pmd->tm); + down_read(&pmd->root_lock); + if (!pmd->fail_io) + dm_tm_issue_prefetches(pmd->tm); + up_read(&pmd->root_lock); } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index dd834927b..c338aebb4 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1109,12 +1109,8 @@ static void rq_completed(struct mapped_device *md, int rw, bool run_queue) * back into ->request_fn() could deadlock attempting to grab the * queue lock again. */ - if (run_queue) { - if (md->queue->mq_ops) - blk_mq_run_hw_queues(md->queue, true); - else - blk_run_queue_async(md->queue); - } + if (!md->queue->mq_ops && run_queue) + blk_run_queue_async(md->queue); /* * dm_put() must be at the end of this function. See the comment above @@ -1214,9 +1210,9 @@ static void dm_requeue_original_request(struct mapped_device *md, { int rw = rq_data_dir(rq); + rq_end_stats(md, rq); dm_unprep_request(rq); - rq_end_stats(md, rq); if (!rq->q->mq_ops) old_requeue_request(rq); else { @@ -1336,7 +1332,10 @@ static void dm_complete_request(struct request *rq, int error) struct dm_rq_target_io *tio = tio_from_request(rq); tio->error = error; - blk_complete_request(rq); + if (!rq->q->mq_ops) + blk_complete_request(rq); + else + blk_mq_complete_request(rq, error); } /* diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 0a72ab6e6..dd483bb2e 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -129,7 +129,9 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio) } multipath = conf->multipaths + mp_bh->path; - mp_bh->bio = *bio; + bio_init(&mp_bh->bio); + __bio_clone_fast(&mp_bh->bio, bio); + mp_bh->bio.bi_iter.bi_sector += multipath->rdev->data_offset; mp_bh->bio.bi_bdev = multipath->rdev->bdev; mp_bh->bio.bi_rw |= REQ_FAILFAST_TRANSPORT; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 4e3843f7d..bb5bce059 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2274,6 +2274,7 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio) if (fail) { spin_lock_irq(&conf->device_lock); list_add(&r1_bio->retry_list, &conf->bio_end_io_list); + conf->nr_queued++; spin_unlock_irq(&conf->device_lock); md_wakeup_thread(conf->mddev->thread); } else { @@ -2391,8 +2392,10 @@ static void raid1d(struct md_thread *thread) LIST_HEAD(tmp); spin_lock_irqsave(&conf->device_lock, flags); if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) { - list_add(&tmp, &conf->bio_end_io_list); - list_del_init(&conf->bio_end_io_list); + while (!list_empty(&conf->bio_end_io_list)) { + list_move(conf->bio_end_io_list.prev, &tmp); + conf->nr_queued--; + } } spin_unlock_irqrestore(&conf->device_lock, flags); while (!list_empty(&tmp)) { diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 1c1447dd3..e3fd725d5 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2664,6 +2664,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio) if (fail) { spin_lock_irq(&conf->device_lock); list_add(&r10_bio->retry_list, &conf->bio_end_io_list); + conf->nr_queued++; spin_unlock_irq(&conf->device_lock); md_wakeup_thread(conf->mddev->thread); } else { @@ -2691,8 +2692,10 @@ static void raid10d(struct md_thread *thread) LIST_HEAD(tmp); spin_lock_irqsave(&conf->device_lock, flags); if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) { - list_add(&tmp, &conf->bio_end_io_list); - list_del_init(&conf->bio_end_io_list); + while (!list_empty(&conf->bio_end_io_list)) { + list_move(conf->bio_end_io_list.prev, &tmp); + conf->nr_queued--; + } } spin_unlock_irqrestore(&conf->device_lock, flags); while (!list_empty(&tmp)) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index b4f02c995..32d52878f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -340,8 +340,7 @@ static void release_inactive_stripe_list(struct r5conf *conf, int hash) { int size; - unsigned long do_wakeup = 0; - int i = 0; + bool do_wakeup = false; unsigned long flags; if (hash == NR_STRIPE_HASH_LOCKS) { @@ -362,19 +361,15 @@ static void release_inactive_stripe_list(struct r5conf *conf, !list_empty(list)) atomic_dec(&conf->empty_inactive_list_nr); list_splice_tail_init(list, conf->inactive_list + hash); - do_wakeup |= 1 << hash; + do_wakeup = true; spin_unlock_irqrestore(conf->hash_locks + hash, flags); } size--; hash--; } - for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++) { - if (do_wakeup & (1 << i)) - wake_up(&conf->wait_for_stripe[i]); - } - if (do_wakeup) { + wake_up(&conf->wait_for_stripe); if (atomic_read(&conf->active_stripes) == 0) wake_up(&conf->wait_for_quiescent); if (conf->retry_read_aligned) @@ -687,15 +682,14 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector, if (!sh) { set_bit(R5_INACTIVE_BLOCKED, &conf->cache_state); - wait_event_exclusive_cmd( - conf->wait_for_stripe[hash], + wait_event_lock_irq( + conf->wait_for_stripe, !list_empty(conf->inactive_list + hash) && (atomic_read(&conf->active_stripes) < (conf->max_nr_stripes * 3 / 4) || !test_bit(R5_INACTIVE_BLOCKED, &conf->cache_state)), - spin_unlock_irq(conf->hash_locks + hash), - spin_lock_irq(conf->hash_locks + hash)); + *(conf->hash_locks + hash)); clear_bit(R5_INACTIVE_BLOCKED, &conf->cache_state); } else { @@ -720,9 +714,6 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector, } } while (sh == NULL); - if (!list_empty(conf->inactive_list + hash)) - wake_up(&conf->wait_for_stripe[hash]); - spin_unlock_irq(conf->hash_locks + hash); return sh; } @@ -2089,6 +2080,14 @@ static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors) unsigned long cpu; int err = 0; + /* + * Never shrink. And mddev_suspend() could deadlock if this is called + * from raid5d. In that case, scribble_disks and scribble_sectors + * should equal to new_disks and new_sectors + */ + if (conf->scribble_disks >= new_disks && + conf->scribble_sectors >= new_sectors) + return 0; mddev_suspend(conf->mddev); get_online_cpus(); for_each_present_cpu(cpu) { @@ -2110,6 +2109,10 @@ static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors) } put_online_cpus(); mddev_resume(conf->mddev); + if (!err) { + conf->scribble_disks = new_disks; + conf->scribble_sectors = new_sectors; + } return err; } @@ -2190,7 +2193,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) cnt = 0; list_for_each_entry(nsh, &newstripes, lru) { lock_device_hash_lock(conf, hash); - wait_event_exclusive_cmd(conf->wait_for_stripe[hash], + wait_event_cmd(conf->wait_for_stripe, !list_empty(conf->inactive_list + hash), unlock_device_hash_lock(conf, hash), lock_device_hash_lock(conf, hash)); @@ -4236,7 +4239,6 @@ static void break_stripe_batch_list(struct stripe_head *head_sh, WARN_ON_ONCE(sh->state & ((1 << STRIPE_ACTIVE) | (1 << STRIPE_SYNCING) | (1 << STRIPE_REPLACED) | - (1 << STRIPE_PREREAD_ACTIVE) | (1 << STRIPE_DELAYED) | (1 << STRIPE_BIT_DELAY) | (1 << STRIPE_FULL_WRITE) | @@ -4251,6 +4253,7 @@ static void break_stripe_batch_list(struct stripe_head *head_sh, (1 << STRIPE_REPLACED))); set_mask_bits(&sh->state, ~(STRIPE_EXPAND_SYNC_FLAGS | + (1 << STRIPE_PREREAD_ACTIVE) | (1 << STRIPE_DEGRADED)), head_sh->state & (1 << STRIPE_INSYNC)); @@ -6413,6 +6416,12 @@ static int raid5_alloc_percpu(struct r5conf *conf) } put_online_cpus(); + if (!err) { + conf->scribble_disks = max(conf->raid_disks, + conf->previous_raid_disks); + conf->scribble_sectors = max(conf->chunk_sectors, + conf->prev_chunk_sectors); + } return err; } @@ -6503,9 +6512,7 @@ static struct r5conf *setup_conf(struct mddev *mddev) seqcount_init(&conf->gen_lock); mutex_init(&conf->cache_size_mutex); init_waitqueue_head(&conf->wait_for_quiescent); - for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++) { - init_waitqueue_head(&conf->wait_for_stripe[i]); - } + init_waitqueue_head(&conf->wait_for_stripe); init_waitqueue_head(&conf->wait_for_overlap); INIT_LIST_HEAD(&conf->handle_list); INIT_LIST_HEAD(&conf->hold_list); @@ -7014,8 +7021,8 @@ static int raid5_run(struct mddev *mddev) } if (discard_supported && - mddev->queue->limits.max_discard_sectors >= stripe && - mddev->queue->limits.discard_granularity >= stripe) + mddev->queue->limits.max_discard_sectors >= (stripe >> 9) && + mddev->queue->limits.discard_granularity >= stripe) queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); else diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index a415e1cd3..517d4b68a 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -510,6 +510,8 @@ struct r5conf { * conversions */ } __percpu *percpu; + int scribble_disks; + int scribble_sectors; #ifdef CONFIG_HOTPLUG_CPU struct notifier_block cpu_notify; #endif @@ -522,7 +524,7 @@ struct r5conf { atomic_t empty_inactive_list_nr; struct llist_head released_stripes; wait_queue_head_t wait_for_quiescent; - wait_queue_head_t wait_for_stripe[NR_STRIPE_HASH_LOCKS]; + wait_queue_head_t wait_for_stripe; wait_queue_head_t wait_for_overlap; unsigned long cache_state; #define R5_INACTIVE_BLOCKED 1 /* release of inactive stripes blocked, diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index 471fd23b5..08d2c6bf7 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -1161,12 +1161,23 @@ static void adv7511_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd, in } } +static void adv7511_notify_no_edid(struct v4l2_subdev *sd) +{ + struct adv7511_state *state = get_adv7511_state(sd); + struct adv7511_edid_detect ed; + + /* We failed to read the EDID, so send an event for this. */ + ed.present = false; + ed.segment = adv7511_rd(sd, 0xc4); + v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); + v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0); +} + static void adv7511_edid_handler(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct adv7511_state *state = container_of(dwork, struct adv7511_state, edid_handler); struct v4l2_subdev *sd = &state->sd; - struct adv7511_edid_detect ed; v4l2_dbg(1, debug, sd, "%s:\n", __func__); @@ -1191,9 +1202,7 @@ static void adv7511_edid_handler(struct work_struct *work) } /* We failed to read the EDID, so send an event for this. */ - ed.present = false; - ed.segment = adv7511_rd(sd, 0xc4); - v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); + adv7511_notify_no_edid(sd); v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__); } @@ -1264,7 +1273,6 @@ static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd) /* update read only ctrls */ v4l2_ctrl_s_ctrl(state->hotplug_ctrl, adv7511_have_hotplug(sd) ? 0x1 : 0x0); v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, adv7511_have_rx_sense(sd) ? 0x1 : 0x0); - v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); if ((status & MASK_ADV7511_HPD_DETECT) && ((status & MASK_ADV7511_MSEN_DETECT) || state->edid.segments)) { v4l2_dbg(1, debug, sd, "%s: hotplug and (rx-sense or edid)\n", __func__); @@ -1294,6 +1302,7 @@ static void adv7511_check_monitor_present_status(struct v4l2_subdev *sd) } adv7511_s_power(sd, false); memset(&state->edid, 0, sizeof(struct adv7511_state_edid)); + adv7511_notify_no_edid(sd); } } @@ -1370,6 +1379,7 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd) } /* one more segment read ok */ state->edid.segments = segment + 1; + v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x1); if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) { /* Request next EDID segment */ v4l2_dbg(1, debug, sd, "%s: request segment %d\n", __func__, state->edid.segments); @@ -1389,7 +1399,6 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd) ed.present = true; ed.segment = 0; state->edid_detect_counter++; - v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0); v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); return ed.present; } diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 9400e9960..bedbd51fb 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -2334,6 +2334,19 @@ static int bttv_g_fmt_vid_overlay(struct file *file, void *priv, return 0; } +static void bttv_get_width_mask_vid_cap(const struct bttv_format *fmt, + unsigned int *width_mask, + unsigned int *width_bias) +{ + if (fmt->flags & FORMAT_FLAGS_PLANAR) { + *width_mask = ~15; /* width must be a multiple of 16 pixels */ + *width_bias = 8; /* nearest */ + } else { + *width_mask = ~3; /* width must be a multiple of 4 pixels */ + *width_bias = 2; /* nearest */ + } +} + static int bttv_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { @@ -2343,6 +2356,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv, enum v4l2_field field; __s32 width, height; __s32 height2; + unsigned int width_mask, width_bias; int rc; fmt = format_by_fourcc(f->fmt.pix.pixelformat); @@ -2375,9 +2389,9 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv, width = f->fmt.pix.width; height = f->fmt.pix.height; + bttv_get_width_mask_vid_cap(fmt, &width_mask, &width_bias); rc = limit_scaled_size_lock(fh, &width, &height, field, - /* width_mask: 4 pixels */ ~3, - /* width_bias: nearest */ 2, + width_mask, width_bias, /* adjust_size */ 1, /* adjust_crop */ 0); if (0 != rc) @@ -2410,6 +2424,7 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv, struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; __s32 width, height; + unsigned int width_mask, width_bias; enum v4l2_field field; retval = bttv_switch_type(fh, f->type); @@ -2424,9 +2439,10 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv, height = f->fmt.pix.height; field = f->fmt.pix.field; + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + bttv_get_width_mask_vid_cap(fmt, &width_mask, &width_bias); retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field, - /* width_mask: 4 pixels */ ~3, - /* width_bias: nearest */ 2, + width_mask, width_bias, /* adjust_size */ 1, /* adjust_crop */ 1); if (0 != retval) @@ -2434,8 +2450,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.field = field; - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - /* update our state informations */ fh->fmt = fmt; fh->cap.field = f->fmt.pix.field; diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index a63c1366a..1293563b7 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1219,10 +1219,13 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.height = dev->height; f->fmt.pix.field = dev->field; f->fmt.pix.pixelformat = dev->fmt->fourcc; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * dev->fmt->depth) >> 3; + if (dev->fmt->planar) + f->fmt.pix.bytesperline = f->fmt.pix.width; + else + f->fmt.pix.bytesperline = + (f->fmt.pix.width * dev->fmt->depth) / 8; f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; + (f->fmt.pix.height * f->fmt.pix.width * dev->fmt->depth) / 8; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; } @@ -1298,10 +1301,13 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, if (f->fmt.pix.height > maxh) f->fmt.pix.height = maxh; f->fmt.pix.width &= ~0x03; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fmt->depth) >> 3; + if (fmt->planar) + f->fmt.pix.bytesperline = f->fmt.pix.width; + else + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) / 8; f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; + (f->fmt.pix.height * f->fmt.pix.width * fmt->depth) / 8; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 7d28899f8..6efe9d002 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1342,7 +1342,7 @@ static void coda_finish_encode(struct coda_ctx *ctx) /* Calculate bytesused field */ if (dst_buf->sequence == 0) { - vb2_set_plane_payload(&dst_buf->vb2_buf, 0, + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr + ctx->vpu_header_size[0] + ctx->vpu_header_size[1] + ctx->vpu_header_size[2]); diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 086cf1c7b..18aed5dd3 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -91,6 +91,7 @@ static const struct usb_device_id pwc_device_table [] = { { USB_DEVICE(0x0471, 0x0312) }, { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */ + { USB_DEVICE(0x0471, 0x032C) }, /* Philips SPC 880NC PC Camera */ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ @@ -810,6 +811,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id name = "Philips SPC 900NC webcam"; type_id = 740; break; + case 0x032C: + PWC_INFO("Philips SPC 880NC USB webcam detected.\n"); + name = "Philips SPC 880NC webcam"; + type_id = 740; + break; default: return -ENODEV; break; diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 8fd84a674..019644ff6 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -415,7 +415,8 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user get_user(kp->index, &up->index) || get_user(kp->type, &up->type) || get_user(kp->flags, &up->flags) || - get_user(kp->memory, &up->memory)) + get_user(kp->memory, &up->memory) || + get_user(kp->length, &up->length)) return -EFAULT; if (V4L2_TYPE_IS_OUTPUT(kp->type)) @@ -427,9 +428,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { - if (get_user(kp->length, &up->length)) - return -EFAULT; - num_planes = kp->length; if (num_planes == 0) { kp->m.planes = NULL; @@ -462,16 +460,14 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: - if (get_user(kp->length, &up->length) || - get_user(kp->m.offset, &up->m.offset)) + if (get_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: { compat_long_t tmp; - if (get_user(kp->length, &up->length) || - get_user(tmp, &up->m.userptr)) + if (get_user(tmp, &up->m.userptr)) return -EFAULT; kp->m.userptr = (unsigned long)compat_ptr(tmp); @@ -513,7 +509,8 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || put_user(kp->sequence, &up->sequence) || put_user(kp->reserved2, &up->reserved2) || - put_user(kp->reserved, &up->reserved)) + put_user(kp->reserved, &up->reserved) || + put_user(kp->length, &up->length)) return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { @@ -536,13 +533,11 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: - if (put_user(kp->length, &up->length) || - put_user(kp->m.offset, &up->m.offset)) + if (put_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: - if (put_user(kp->length, &up->length) || - put_user(kp->m.userptr, &up->m.userptr)) + if (put_user(kp->m.userptr, &up->m.userptr)) return -EFAULT; break; case V4L2_MEMORY_OVERLAY: diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 0b05aa938..1a173d0af 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -53,6 +53,11 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bus = cl->dev; mutex_lock(&bus->device_lock); + if (bus->dev_state != MEI_DEV_ENABLED) { + rets = -ENODEV; + goto out; + } + if (!mei_cl_is_connected(cl)) { rets = -ENODEV; goto out; @@ -109,6 +114,10 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) bus = cl->dev; mutex_lock(&bus->device_lock); + if (bus->dev_state != MEI_DEV_ENABLED) { + rets = -ENODEV; + goto out; + } cb = mei_cl_read_cb(cl, NULL); if (cb) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index fe207e542..5fbffdb6b 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -589,6 +589,14 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, struct mmc_card *card; int err = 0, ioc_err = 0; + /* + * The caller must have CAP_SYS_RAWIO, and must be calling this on the + * whole block device, not on a partition. This prevents overspray + * between sibling partitions. + */ + if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains)) + return -EPERM; + idata = mmc_blk_ioctl_copy_from_user(ic_ptr); if (IS_ERR(idata)) return PTR_ERR(idata); @@ -631,6 +639,14 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev, int i, err = 0, ioc_err = 0; __u64 num_of_cmds; + /* + * The caller must have CAP_SYS_RAWIO, and must be calling this on the + * whole block device, not on a partition. This prevents overspray + * between sibling partitions. + */ + if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains)) + return -EPERM; + if (copy_from_user(&num_of_cmds, &user->num_of_cmds, sizeof(num_of_cmds))) return -EFAULT; @@ -688,14 +704,6 @@ cmd_err: static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { - /* - * The caller must have CAP_SYS_RAWIO, and must be calling this on the - * whole block device, not on a partition. This prevents overspray - * between sibling partitions. - */ - if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains)) - return -EPERM; - switch (cmd) { case MMC_IOC_CMD: return mmc_blk_ioctl_cmd(bdev, diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 851ccd9ac..25c179592 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -2443,7 +2443,7 @@ static int atmci_configure_dma(struct atmel_mci *host) struct mci_platform_data *pdata = host->pdev->dev.platform_data; dma_cap_mask_t mask; - if (!pdata->dma_filter) + if (!pdata || !pdata->dma_filter) return -ENODEV; dma_cap_zero(mask); diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 3446097a4..e77d79c8c 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1442,6 +1442,12 @@ static int mmc_spi_probe(struct spi_device *spi) host->pdata->cd_debounce); if (status != 0) goto fail_add_host; + + /* The platform has a CD GPIO signal that may support + * interrupts, so let mmc_gpiod_request_cd_irq() decide + * if polling is needed or not. + */ + mmc->caps &= ~MMC_CAP_NEEDS_POLL; mmc_gpiod_request_cd_irq(mmc); } diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index f5edf9d3a..c7f27fe48 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -137,6 +137,10 @@ static int armada_38x_quirks(struct platform_device *pdev, host->quirks &= ~SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN; host->quirks |= SDHCI_QUIRK_MISSING_CAPS; + + host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); + host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "conf-sdio3"); if (res) { @@ -150,7 +154,6 @@ static int armada_38x_quirks(struct platform_device *pdev, * Configuration register, if the adjustment is not done, * remove them from the capabilities. */ - host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); dev_warn(&pdev->dev, "conf-sdio3 register not found: disabling SDR50 and DDR50 modes.\nConsider updating your dtb\n"); @@ -161,7 +164,6 @@ static int armada_38x_quirks(struct platform_device *pdev, * controller has different capabilities than the ones shown * in its registers */ - host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); if (of_property_read_bool(np, "no-1-8-v")) { host->caps &= ~SDHCI_CAN_VDD_180; host->mmc->caps &= ~MMC_CAP_1_8V_DDR; diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 83c4bf7bc..0004721cd 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -147,10 +147,16 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) /* Advertise UHS modes as supported by host */ if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50) misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR50; + else + misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR50; if (soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50; + else + misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_DDR50; if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104) misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104; + else + misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR104; sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL); clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL); @@ -188,7 +194,7 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) unsigned long host_clk; if (!clock) - return; + return sdhci_set_clock(host, clock); host_clk = tegra_host->ddr_signaling ? clock * 2 : clock; clk_set_rate(pltfm_host->clk, host_clk); @@ -335,6 +341,10 @@ static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { static const struct sdhci_tegra_soc_data soc_data_tegra114 = { .pdata = &sdhci_tegra114_pdata, +}; + +static const struct sdhci_tegra_soc_data soc_data_tegra124 = { + .pdata = &sdhci_tegra114_pdata, .nvquirks = NVQUIRK_ENABLE_SDR50 | NVQUIRK_ENABLE_DDR50 | NVQUIRK_ENABLE_SDR104, @@ -357,7 +367,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = { static const struct of_device_id sdhci_tegra_dt_match[] = { { .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 }, - { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra114 }, + { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 }, { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index add9fdfd1..8059d7248 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -465,8 +465,6 @@ static void sdhci_adma_mark_end(void *desc) static int sdhci_adma_table_pre(struct sdhci_host *host, struct mmc_data *data) { - int direction; - void *desc; void *align; dma_addr_t addr; @@ -483,20 +481,9 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, * We currently guess that it is LE. */ - if (data->flags & MMC_DATA_READ) - direction = DMA_FROM_DEVICE; - else - direction = DMA_TO_DEVICE; - - host->align_addr = dma_map_single(mmc_dev(host->mmc), - host->align_buffer, host->align_buffer_sz, direction); - if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) - goto fail; - BUG_ON(host->align_addr & SDHCI_ADMA2_MASK); - host->sg_count = sdhci_pre_dma_transfer(host, data); if (host->sg_count < 0) - goto unmap_align; + return -EINVAL; desc = host->adma_table; align = host->align_buffer; @@ -570,22 +557,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, /* nop, end, valid */ sdhci_adma_write_desc(host, desc, 0, 0, ADMA2_NOP_END_VALID); } - - /* - * Resync align buffer as we might have changed it. - */ - if (data->flags & MMC_DATA_WRITE) { - dma_sync_single_for_device(mmc_dev(host->mmc), - host->align_addr, host->align_buffer_sz, direction); - } - return 0; - -unmap_align: - dma_unmap_single(mmc_dev(host->mmc), host->align_addr, - host->align_buffer_sz, direction); -fail: - return -EINVAL; } static void sdhci_adma_table_post(struct sdhci_host *host, @@ -605,9 +577,6 @@ static void sdhci_adma_table_post(struct sdhci_host *host, else direction = DMA_TO_DEVICE; - dma_unmap_single(mmc_dev(host->mmc), host->align_addr, - host->align_buffer_sz, direction); - /* Do a quick scan of the SG list for any unaligned mappings */ has_unaligned = false; for_each_sg(data->sg, sg, host->sg_count, i) @@ -666,9 +635,20 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) if (!data) target_timeout = cmd->busy_timeout * 1000; else { - target_timeout = data->timeout_ns / 1000; - if (host->clock) - target_timeout += data->timeout_clks / host->clock; + target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000); + if (host->clock && data->timeout_clks) { + unsigned long long val; + + /* + * data->timeout_clks is in units of clock cycles. + * host->clock is in Hz. target_timeout is in us. + * Hence, us = 1000000 * cycles / Hz. Round up. + */ + val = 1000000 * data->timeout_clks; + if (do_div(val, host->clock)) + target_timeout++; + target_timeout += val; + } } /* @@ -1003,6 +983,9 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) WARN_ON(host->cmd); + /* Initially, a command has no error */ + cmd->error = 0; + /* Wait max 10 ms */ timeout = 10; @@ -1097,8 +1080,6 @@ static void sdhci_finish_command(struct sdhci_host *host) } } - host->cmd->error = 0; - /* Finished CMD23, now send actual command. */ if (host->cmd == host->mrq->sbc) { host->cmd = NULL; @@ -2114,14 +2095,13 @@ static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, struct sdhci_host *host = mmc_priv(mmc); struct mmc_data *data = mrq->data; - if (host->flags & SDHCI_REQ_USE_DMA) { - if (data->host_cookie == COOKIE_GIVEN || - data->host_cookie == COOKIE_MAPPED) - dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, - data->flags & MMC_DATA_WRITE ? - DMA_TO_DEVICE : DMA_FROM_DEVICE); - data->host_cookie = COOKIE_UNMAPPED; - } + if (data->host_cookie == COOKIE_GIVEN || + data->host_cookie == COOKIE_MAPPED) + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + data->flags & MMC_DATA_WRITE ? + DMA_TO_DEVICE : DMA_FROM_DEVICE); + + data->host_cookie = COOKIE_UNMAPPED; } static int sdhci_pre_dma_transfer(struct sdhci_host *host, @@ -2237,6 +2217,22 @@ static void sdhci_tasklet_finish(unsigned long param) mrq = host->mrq; + /* + * Always unmap the data buffers if they were mapped by + * sdhci_prepare_data() whenever we finish with a request. + * This avoids leaking DMA mappings on error. + */ + if (host->flags & SDHCI_REQ_USE_DMA) { + struct mmc_data *data = mrq->data; + + if (data && data->host_cookie == COOKIE_MAPPED) { + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + (data->flags & MMC_DATA_READ) ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); + data->host_cookie = COOKIE_UNMAPPED; + } + } + /* * The controller needs a reset of internal state machines * upon error conditions. @@ -2322,13 +2318,30 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask) return; } - if (intmask & SDHCI_INT_TIMEOUT) - host->cmd->error = -ETIMEDOUT; - else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT | - SDHCI_INT_INDEX)) - host->cmd->error = -EILSEQ; + if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | + SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { + if (intmask & SDHCI_INT_TIMEOUT) + host->cmd->error = -ETIMEDOUT; + else + host->cmd->error = -EILSEQ; + + /* + * If this command initiates a data phase and a response + * CRC error is signalled, the card can start transferring + * data - the card may have received the command without + * error. We must not terminate the mmc_request early. + * + * If the card did not receive the command or returned an + * error which prevented it sending data, the data phase + * will time out. + */ + if (host->cmd->data && + (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == + SDHCI_INT_CRC) { + host->cmd = NULL; + return; + } - if (host->cmd->error) { tasklet_schedule(&host->finish_tasklet); return; } @@ -2967,14 +2980,21 @@ int sdhci_add_host(struct sdhci_host *host) &host->adma_addr, GFP_KERNEL); host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN; - host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL); + host->align_buffer = dma_alloc_coherent(mmc_dev(mmc), + host->align_buffer_sz, + &host->align_addr, + GFP_KERNEL); if (!host->adma_table || !host->align_buffer) { if (host->adma_table) dma_free_coherent(mmc_dev(mmc), host->adma_table_sz, host->adma_table, host->adma_addr); - kfree(host->align_buffer); + if (host->align_buffer) + dma_free_coherent(mmc_dev(mmc), + host->align_buffer_sz, + host->align_buffer, + host->align_addr); pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", mmc_hostname(mmc)); host->flags &= ~SDHCI_USE_ADMA; @@ -2986,10 +3006,14 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; dma_free_coherent(mmc_dev(mmc), host->adma_table_sz, host->adma_table, host->adma_addr); - kfree(host->align_buffer); + dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz, + host->align_buffer, host->align_addr); host->adma_table = NULL; host->align_buffer = NULL; } + + /* dma_alloc_coherent returns page aligned and sized buffers */ + BUG_ON(host->align_addr & SDHCI_ADMA2_MASK); } /* @@ -3072,14 +3096,14 @@ int sdhci_add_host(struct sdhci_host *host) if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) host->timeout_clk *= 1000; + if (override_timeout_clk) + host->timeout_clk = override_timeout_clk; + mmc->max_busy_timeout = host->ops->get_max_timeout_count ? host->ops->get_max_timeout_count(host) : 1 << 27; mmc->max_busy_timeout /= host->timeout_clk; } - if (override_timeout_clk) - host->timeout_clk = override_timeout_clk; - mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; @@ -3452,7 +3476,9 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) if (host->adma_table) dma_free_coherent(mmc_dev(mmc), host->adma_table_sz, host->adma_table, host->adma_addr); - kfree(host->align_buffer); + if (host->align_buffer) + dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz, + host->align_buffer, host->align_addr); host->adma_table = NULL; host->align_buffer = NULL; diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 43b3392ff..652d01832 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -2599,6 +2599,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) */ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) { + struct onenand_chip *this = mtd->priv; int ret; ret = onenand_block_isbad(mtd, ofs); @@ -2610,7 +2611,7 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) } onenand_get_device(mtd, FL_WRITING); - ret = mtd_block_markbad(mtd, ofs); + ret = this->block_markbad(mtd, ofs); onenand_release_device(mtd); return ret; } diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index b0ae69f84..acb1c5b2b 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3720,7 +3720,7 @@ static int mvneta_probe(struct platform_device *pdev) dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; dev->hw_features |= dev->features; dev->vlan_features |= dev->features; - dev->priv_flags |= IFF_UNICAST_FLT; + dev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE; dev->gso_max_segs = MVNETA_MAX_TSO_SEGS; err = register_netdev(dev); diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 696852eb2..7a3f990c1 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -430,16 +430,6 @@ static int irtty_open(struct tty_struct *tty) /* Module stuff handled via irda_ldisc.owner - Jean II */ - /* First make sure we're not already connected. */ - if (tty->disc_data != NULL) { - priv = tty->disc_data; - if (priv && priv->magic == IRTTY_MAGIC) { - ret = -EEXIST; - goto out; - } - tty->disc_data = NULL; /* ### */ - } - /* stop the underlying driver */ irtty_stop_receiver(tty, TRUE); if (tty->ops->stop) diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 01f08a775..e7034c55e 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -280,7 +280,7 @@ static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbo struct net_device *ndev = dev_id; struct rionet_private *rnet = netdev_priv(ndev); - spin_lock(&rnet->lock); + spin_lock(&rnet->tx_lock); if (netif_msg_intr(rnet)) printk(KERN_INFO @@ -299,7 +299,7 @@ static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbo if (rnet->tx_cnt < RIONET_TX_RING_SIZE) netif_wake_queue(ndev); - spin_unlock(&rnet->lock); + spin_unlock(&rnet->tx_lock); } static int rionet_open(struct net_device *ndev) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c index 2ca783fa5..7e269f9aa 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c @@ -32,7 +32,7 @@ #define BRCMF_FLOWRING_LOW (BRCMF_FLOWRING_HIGH - 256) #define BRCMF_FLOWRING_INVALID_IFIDX 0xff -#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] + fifo + ifidx * 16) +#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] * 2 + fifo + ifidx * 16) #define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16) static const u8 brcmf_flowring_prio2fifo[] = { @@ -68,7 +68,7 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], u8 prio, u8 ifidx) { struct brcmf_flowring_hash *hash; - u8 hash_idx; + u16 hash_idx; u32 i; bool found; bool sta; @@ -88,6 +88,7 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], } hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); found = false; hash = flow->hash; for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { @@ -98,6 +99,7 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], break; } hash_idx++; + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); } if (found) return hash[hash_idx].flowid; @@ -111,7 +113,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], { struct brcmf_flowring_ring *ring; struct brcmf_flowring_hash *hash; - u8 hash_idx; + u16 hash_idx; u32 i; bool found; u8 fifo; @@ -131,6 +133,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], } hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); found = false; hash = flow->hash; for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { @@ -140,6 +143,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], break; } hash_idx++; + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); } if (found) { for (i = 0; i < flow->nrofrings; i++) { @@ -169,7 +173,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], } -u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid) +u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; @@ -179,7 +183,7 @@ u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid) } -static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid, +static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid, bool blocked) { struct brcmf_flowring_ring *ring; @@ -228,10 +232,10 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid, } -void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid) +void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; - u8 hash_idx; + u16 hash_idx; struct sk_buff *skb; ring = flow->rings[flowid]; @@ -253,7 +257,7 @@ void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid) } -u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, +u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid, struct sk_buff *skb) { struct brcmf_flowring_ring *ring; @@ -279,7 +283,7 @@ u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, } -struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid) +struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; struct sk_buff *skb; @@ -300,7 +304,7 @@ struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid) } -void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, +void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid, struct sk_buff *skb) { struct brcmf_flowring_ring *ring; @@ -311,7 +315,7 @@ void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, } -u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid) +u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; @@ -326,7 +330,7 @@ u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid) } -void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid) +void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; @@ -340,10 +344,10 @@ void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid) } -u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid) +u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; - u8 hash_idx; + u16 hash_idx; ring = flow->rings[flowid]; hash_idx = ring->hash_id; @@ -384,7 +388,7 @@ void brcmf_flowring_detach(struct brcmf_flowring *flow) struct brcmf_pub *drvr = bus_if->drvr; struct brcmf_flowring_tdls_entry *search; struct brcmf_flowring_tdls_entry *remove; - u8 flowid; + u16 flowid; for (flowid = 0; flowid < flow->nrofrings; flowid++) { if (flow->rings[flowid]) @@ -408,7 +412,7 @@ void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx, struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev); struct brcmf_pub *drvr = bus_if->drvr; u32 i; - u8 flowid; + u16 flowid; if (flow->addr_mode[ifidx] != addr_mode) { for (i = 0; i < ARRAY_SIZE(flow->hash); i++) { @@ -434,7 +438,7 @@ void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx, struct brcmf_flowring_tdls_entry *prev; struct brcmf_flowring_tdls_entry *search; u32 i; - u8 flowid; + u16 flowid; bool sta; sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h index 95fd1c967..068e68d94 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h @@ -16,7 +16,7 @@ #define BRCMFMAC_FLOWRING_H -#define BRCMF_FLOWRING_HASHSIZE 256 +#define BRCMF_FLOWRING_HASHSIZE 512 /* has to be 2^x */ #define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF @@ -24,7 +24,7 @@ struct brcmf_flowring_hash { u8 mac[ETH_ALEN]; u8 fifo; u8 ifidx; - u8 flowid; + u16 flowid; }; enum ring_status { @@ -61,16 +61,16 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], u8 prio, u8 ifidx); u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], u8 prio, u8 ifidx); -void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid); -void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid); -u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid); -u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, +void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid); +void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid); +u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid); +u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid, struct sk_buff *skb); -struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid); -void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, +struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid); +void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid, struct sk_buff *skb); -u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid); -u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid); +u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid); +u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid); struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings); void brcmf_flowring_detach(struct brcmf_flowring *flow); void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index c2bdb9174..922966734 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -677,7 +677,7 @@ static u32 brcmf_msgbuf_flowring_create(struct brcmf_msgbuf *msgbuf, int ifidx, } -static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid) +static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid) { struct brcmf_flowring *flow = msgbuf->flow; struct brcmf_commonring *commonring; @@ -1310,7 +1310,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev) } -void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid) +void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid) { struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; struct msgbuf_tx_flowring_delete_req *delete; @@ -1415,6 +1415,13 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) u32 count; if_msgbuf = drvr->bus_if->msgbuf; + + if (if_msgbuf->nrof_flowrings >= BRCMF_FLOWRING_HASHSIZE) { + brcmf_err("driver not configured for this many flowrings %d\n", + if_msgbuf->nrof_flowrings); + if_msgbuf->nrof_flowrings = BRCMF_FLOWRING_HASHSIZE - 1; + } + msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL); if (!msgbuf) goto fail; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h index 3d513e407..ee6906a3c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h @@ -33,7 +33,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev); -void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid); +void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid); int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr); void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr); #else diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c index ee7d97482..e6a14a45f 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c @@ -1026,6 +1026,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0411, 0x01a2) }, { USB_DEVICE(0x0411, 0x01ee) }, { USB_DEVICE(0x0411, 0x01a8) }, + { USB_DEVICE(0x0411, 0x01fd) }, /* Corega */ { USB_DEVICE(0x07aa, 0x002f) }, { USB_DEVICE(0x07aa, 0x003c) }, diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 5d28e9405..576eb7013 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -513,10 +513,10 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, /* fail write commands (when read-only) */ if (read_only) - switch (ioctl_cmd) { - case ND_IOCTL_VENDOR: - case ND_IOCTL_SET_CONFIG_DATA: - case ND_IOCTL_ARS_START: + switch (cmd) { + case ND_CMD_VENDOR: + case ND_CMD_SET_CONFIG_DATA: + case ND_CMD_ARS_START: dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n", nvdimm ? nvdimm_cmd_name(cmd) : nvdimm_bus_cmd_name(cmd)); diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 8d0b54670..544b802a5 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -66,22 +66,25 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page, unsigned int len, unsigned int off, int rw, sector_t sector) { + int rc = 0; void *mem = kmap_atomic(page); phys_addr_t pmem_off = sector * 512 + pmem->data_offset; void __pmem *pmem_addr = pmem->virt_addr + pmem_off; if (rw == READ) { if (unlikely(is_bad_pmem(&pmem->bb, sector, len))) - return -EIO; - memcpy_from_pmem(mem + off, pmem_addr, len); - flush_dcache_page(page); + rc = -EIO; + else { + memcpy_from_pmem(mem + off, pmem_addr, len); + flush_dcache_page(page); + } } else { flush_dcache_page(page); memcpy_to_pmem(pmem_addr, mem + off, len); } kunmap_atomic(mem); - return 0; + return rc; } static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio) diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 1a3556a9e..ed01c0172 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -32,11 +32,13 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, phys_addr_t *res_base) { + phys_addr_t base; /* * We use __memblock_alloc_base() because memblock_alloc_base() * panic()s on allocation failure. */ - phys_addr_t base = __memblock_alloc_base(size, align, end); + end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end; + base = __memblock_alloc_base(size, align, end); if (!base) return -ENOMEM; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6d7ab9bb0..6b0056e9c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -179,6 +179,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, u16 orig_cmd; struct pci_bus_region region, inverted_region; + if (dev->non_compliant_bars) + return 0; + mask = type ? PCI_ROM_ADDRESS_MASK : ~0; /* No printks while decoding is disabled! */ @@ -1171,6 +1174,7 @@ static void pci_msi_setup_pci_dev(struct pci_dev *dev) int pci_setup_device(struct pci_dev *dev) { u32 class; + u16 cmd; u8 hdr_type; int pos = 0; struct pci_bus_region region; @@ -1214,6 +1218,16 @@ int pci_setup_device(struct pci_dev *dev) /* device class may be changed after fixup */ class = dev->class >> 8; + if (dev->non_compliant_bars) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { + dev_info(&dev->dev, "device has non-compliant BARs; disabling IO/MEM decoding\n"); + cmd &= ~PCI_COMMAND_IO; + cmd &= ~PCI_COMMAND_MEMORY; + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + } + switch (dev->hdr_type) { /* header type */ case PCI_HEADER_TYPE_NORMAL: /* standard header */ if (class == PCI_CLASS_BRIDGE_PCI) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 0f5997ceb..08b1d93da 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -779,7 +779,7 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, } if (num_pulls) { err = of_property_read_u32_index(np, "brcm,pull", - (num_funcs > 1) ? i : 0, &pull); + (num_pulls > 1) ? i : 0, &pull); if (err) goto out; err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin, diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index d78ee151c..be3bc2f4e 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -864,6 +864,20 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G50-30"), }, }, + { + .ident = "Lenovo ideapad Y700-15ISK", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-15ISK"), + }, + }, + { + .ident = "Lenovo ideapad Y700 Touch-15ISK", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700 Touch-15ISK"), + }, + }, { .ident = "Lenovo ideapad Y700-17ISK", .matches = { diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index d72867257..3eff2a69f 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -760,7 +760,7 @@ static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance) struct NCR5380_cmd *ncmd; struct scsi_cmnd *cmd; - if (list_empty(&hostdata->autosense)) { + if (hostdata->sensing || list_empty(&hostdata->autosense)) { list_for_each_entry(ncmd, &hostdata->unissued, list) { cmd = NCR5380_to_scmd(ncmd); dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n", @@ -793,7 +793,7 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) struct NCR5380_hostdata *hostdata = shost_priv(instance); struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - if (hostdata->sensing) { + if (hostdata->sensing == cmd) { scsi_eh_restore_cmnd(cmd, &hostdata->ses); list_add(&ncmd->list, &hostdata->autosense); hostdata->sensing = NULL; @@ -815,15 +815,17 @@ static void NCR5380_main(struct work_struct *work) struct NCR5380_hostdata *hostdata = container_of(work, struct NCR5380_hostdata, main_task); struct Scsi_Host *instance = hostdata->host; - struct scsi_cmnd *cmd; int done; do { done = 1; spin_lock_irq(&hostdata->lock); - while (!hostdata->connected && - (cmd = dequeue_next_cmd(instance))) { + while (!hostdata->connected && !hostdata->selecting) { + struct scsi_cmnd *cmd = dequeue_next_cmd(instance); + + if (!cmd) + break; dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd); @@ -840,8 +842,7 @@ static void NCR5380_main(struct work_struct *work) * entire unit. */ - cmd = NCR5380_select(instance, cmd); - if (!cmd) { + if (!NCR5380_select(instance, cmd)) { dsprintk(NDEBUG_MAIN, instance, "main: select complete\n"); } else { dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, @@ -1056,6 +1057,11 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, /* Reselection interrupt */ goto out; } + if (!hostdata->selecting) { + /* Command was aborted */ + NCR5380_write(MODE_REG, MR_BASE); + goto out; + } if (err < 0) { NCR5380_write(MODE_REG, MR_BASE); shost_printk(KERN_ERR, instance, @@ -1759,9 +1765,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) unsigned char msgout = NOP; int sink = 0; int len; -#if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) int transfersize; -#endif unsigned char *data; unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; struct scsi_cmnd *cmd; @@ -1798,6 +1802,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) do_abort(instance); cmd->result = DID_ERROR << 16; complete_cmd(instance, cmd); + hostdata->connected = NULL; return; #endif case PHASE_DATAIN: @@ -1847,20 +1852,23 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - complete_cmd(instance, cmd); /* XXX - need to source or sink data here, as appropriate */ } else cmd->SCp.this_residual -= transfersize - len; } else #endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */ { - spin_unlock_irq(&hostdata->lock); - NCR5380_transfer_pio(instance, &phase, - (int *)&cmd->SCp.this_residual, + /* Break up transfer into 3 ms chunks, + * presuming 6 accesses per handshake. + */ + transfersize = min((unsigned long)cmd->SCp.this_residual, + hostdata->accesses_per_ms / 2); + len = transfersize; + NCR5380_transfer_pio(instance, &phase, &len, (unsigned char **)&cmd->SCp.ptr); - spin_lock_irq(&hostdata->lock); + cmd->SCp.this_residual -= transfersize - len; } - break; + return; case PHASE_MSGIN: len = 1; data = &tmp; @@ -2292,14 +2300,17 @@ static bool list_del_cmd(struct list_head *haystack, * [disconnected -> connected ->]... * [autosense -> connected ->] done * - * If cmd is unissued then just remove it. - * If cmd is disconnected, try to select the target. - * If cmd is connected, try to send an abort message. - * If cmd is waiting for autosense, give it a chance to complete but check - * that it isn't left connected. * If cmd was not found at all then presumably it has already been completed, * in which case return SUCCESS to try to avoid further EH measures. + * * If the command has not completed yet, we must not fail to find it. + * We have no option but to forget the aborted command (even if it still + * lacks sense data). The mid-layer may re-issue a command that is in error + * recovery (see scsi_send_eh_cmnd), but the logic and data structures in + * this driver are such that a command can appear on one queue only. + * + * The lock protects driver data structures, but EH handlers also use it + * to serialize their own execution and prevent their own re-entry. */ static int NCR5380_abort(struct scsi_cmnd *cmd) @@ -2322,6 +2333,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) "abort: removed %p from issue queue\n", cmd); cmd->result = DID_ABORT << 16; cmd->scsi_done(cmd); /* No tag or busy flag to worry about */ + goto out; } if (hostdata->selecting == cmd) { @@ -2336,58 +2348,21 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) if (list_del_cmd(&hostdata->disconnected, cmd)) { dsprintk(NDEBUG_ABORT, instance, "abort: removed %p from disconnected list\n", cmd); - cmd->result = DID_ERROR << 16; - if (!hostdata->connected) - NCR5380_select(instance, cmd); - if (hostdata->connected != cmd) { - complete_cmd(instance, cmd); - result = FAILED; - goto out; - } + /* Can't call NCR5380_select() and send ABORT because that + * means releasing the lock. Need a bus reset. + */ + set_host_byte(cmd, DID_ERROR); + complete_cmd(instance, cmd); + result = FAILED; + goto out; } if (hostdata->connected == cmd) { dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); hostdata->connected = NULL; - if (do_abort(instance)) { - set_host_byte(cmd, DID_ERROR); - complete_cmd(instance, cmd); - result = FAILED; - goto out; - } - set_host_byte(cmd, DID_ABORT); #ifdef REAL_DMA hostdata->dma_len = 0; #endif - if (cmd->cmnd[0] == REQUEST_SENSE) - complete_cmd(instance, cmd); - else { - struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - - /* Perform autosense for this command */ - list_add(&ncmd->list, &hostdata->autosense); - } - } - - if (list_find_cmd(&hostdata->autosense, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: found %p on sense queue\n", cmd); - spin_unlock_irqrestore(&hostdata->lock, flags); - queue_work(hostdata->work_q, &hostdata->main_task); - msleep(1000); - spin_lock_irqsave(&hostdata->lock, flags); - if (list_del_cmd(&hostdata->autosense, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: removed %p from sense queue\n", cmd); - set_host_byte(cmd, DID_ABORT); - complete_cmd(instance, cmd); - goto out; - } - } - - if (hostdata->connected == cmd) { - dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); - hostdata->connected = NULL; if (do_abort(instance)) { set_host_byte(cmd, DID_ERROR); complete_cmd(instance, cmd); @@ -2395,9 +2370,14 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) goto out; } set_host_byte(cmd, DID_ABORT); -#ifdef REAL_DMA - hostdata->dma_len = 0; -#endif + complete_cmd(instance, cmd); + goto out; + } + + if (list_del_cmd(&hostdata->autosense, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: removed %p from sense queue\n", cmd); + set_host_byte(cmd, DID_ERROR); complete_cmd(instance, cmd); } @@ -2450,7 +2430,16 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) * commands! */ - hostdata->selecting = NULL; + if (list_del_cmd(&hostdata->unissued, cmd)) { + cmd->result = DID_RESET << 16; + cmd->scsi_done(cmd); + } + + if (hostdata->selecting) { + hostdata->selecting->result = DID_RESET << 16; + complete_cmd(instance, hostdata->selecting); + hostdata->selecting = NULL; + } list_for_each_entry(ncmd, &hostdata->disconnected, list) { struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); @@ -2458,6 +2447,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) set_host_byte(cmd, DID_RESET); cmd->scsi_done(cmd); } + INIT_LIST_HEAD(&hostdata->disconnected); list_for_each_entry(ncmd, &hostdata->autosense, list) { struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); @@ -2465,6 +2455,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) set_host_byte(cmd, DID_RESET); cmd->scsi_done(cmd); } + INIT_LIST_HEAD(&hostdata->autosense); if (hostdata->connected) { set_host_byte(hostdata->connected, DID_RESET); @@ -2472,12 +2463,6 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) hostdata->connected = NULL; } - if (hostdata->sensing) { - set_host_byte(hostdata->connected, DID_RESET); - complete_cmd(instance, hostdata->sensing); - hostdata->sensing = NULL; - } - for (i = 0; i < 8; ++i) hostdata->busy[i] = 0; #ifdef REAL_DMA diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 074878b55..d044f3f27 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -944,6 +944,7 @@ struct fib { */ struct list_head fiblink; void *data; + u32 vector_no; struct hw_fib *hw_fib_va; /* Actual shared object */ dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ }; @@ -2113,6 +2114,7 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor) int aac_acquire_irq(struct aac_dev *dev); void aac_free_irq(struct aac_dev *dev); const char *aac_driverinfo(struct Scsi_Host *); +void aac_fib_vector_assign(struct aac_dev *dev); struct fib *aac_fib_alloc(struct aac_dev *dev); int aac_fib_setup(struct aac_dev *dev); void aac_fib_map_free(struct aac_dev *dev); diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index a1f90fe84..4cbf54928 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -83,13 +83,38 @@ static int fib_map_alloc(struct aac_dev *dev) void aac_fib_map_free(struct aac_dev *dev) { - pci_free_consistent(dev->pdev, - dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), - dev->hw_fib_va, dev->hw_fib_pa); + if (dev->hw_fib_va && dev->max_fib_size) { + pci_free_consistent(dev->pdev, + (dev->max_fib_size * + (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)), + dev->hw_fib_va, dev->hw_fib_pa); + } dev->hw_fib_va = NULL; dev->hw_fib_pa = 0; } +void aac_fib_vector_assign(struct aac_dev *dev) +{ + u32 i = 0; + u32 vector = 1; + struct fib *fibptr = NULL; + + for (i = 0, fibptr = &dev->fibs[i]; + i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); + i++, fibptr++) { + if ((dev->max_msix == 1) || + (i > ((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1) + - dev->vector_cap))) { + fibptr->vector_no = 0; + } else { + fibptr->vector_no = vector; + vector++; + if (vector == dev->max_msix) + vector = 1; + } + } +} + /** * aac_fib_setup - setup the fibs * @dev: Adapter to set up @@ -151,6 +176,12 @@ int aac_fib_setup(struct aac_dev * dev) hw_fib_pa = hw_fib_pa + dev->max_fib_size + sizeof(struct aac_fib_xporthdr); } + + /* + *Assign vector numbers to fibs + */ + aac_fib_vector_assign(dev); + /* * Add the fib chain to the free list */ diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 76eaa38ff..8a8e84548 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1404,8 +1404,18 @@ static int aac_acquire_resources(struct aac_dev *dev) aac_adapter_enable_int(dev); - if (!dev->sync_mode) + /*max msix may change after EEH + * Re-assign vectors to fibs + */ + aac_fib_vector_assign(dev); + + if (!dev->sync_mode) { + /* After EEH recovery or suspend resume, max_msix count + * may change, therfore updating in init as well. + */ aac_adapter_start(dev); + dev->init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix); + } return 0; error_iounmap: diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 2aa34ea8c..bc0203f3d 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -156,8 +156,8 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) break; if (dev->msi_enabled && dev->max_msix > 1) atomic_dec(&dev->rrq_outstanding[vector_no]); - aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL); dev->host_rrq[index++] = 0; + aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL); if (index == (vector_no + 1) * dev->vector_cap) index = vector_no * dev->vector_cap; dev->host_rrq_idx[vector_no] = index; @@ -452,36 +452,20 @@ static int aac_src_deliver_message(struct fib *fib) #endif u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size); + u16 vector_no; atomic_inc(&q->numpending); if (dev->msi_enabled && fib->hw_fib_va->header.Command != AifRequest && dev->max_msix > 1) { - u_int16_t vector_no, first_choice = 0xffff; - - vector_no = dev->fibs_pushed_no % dev->max_msix; - do { - vector_no += 1; - if (vector_no == dev->max_msix) - vector_no = 1; - if (atomic_read(&dev->rrq_outstanding[vector_no]) < - dev->vector_cap) - break; - if (0xffff == first_choice) - first_choice = vector_no; - else if (vector_no == first_choice) - break; - } while (1); - if (vector_no == first_choice) - vector_no = 0; - atomic_inc(&dev->rrq_outstanding[vector_no]); - if (dev->fibs_pushed_no == 0xffffffff) - dev->fibs_pushed_no = 0; - else - dev->fibs_pushed_no++; + vector_no = fib->vector_no; fib->hw_fib_va->header.Handle += (vector_no << 16); + } else { + vector_no = 0; } + atomic_inc(&dev->rrq_outstanding[vector_no]); + if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { /* Calculate the amount to the fibsize bits */ fibsize = (hdr_size + 127) / 128 - 1; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index b846a4683..fc6a83188 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1336,6 +1336,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev, case AHC_DEV_Q_TAGGED: scsi_change_queue_depth(sdev, dev->openings + dev->active); + break; default: /* * We allow the OS to queue 2 untagged transactions to diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index e65478651..389825ba5 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -862,7 +862,7 @@ static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance) struct NCR5380_cmd *ncmd; struct scsi_cmnd *cmd; - if (list_empty(&hostdata->autosense)) { + if (hostdata->sensing || list_empty(&hostdata->autosense)) { list_for_each_entry(ncmd, &hostdata->unissued, list) { cmd = NCR5380_to_scmd(ncmd); dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n", @@ -901,7 +901,7 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) struct NCR5380_hostdata *hostdata = shost_priv(instance); struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - if (hostdata->sensing) { + if (hostdata->sensing == cmd) { scsi_eh_restore_cmnd(cmd, &hostdata->ses); list_add(&ncmd->list, &hostdata->autosense); hostdata->sensing = NULL; @@ -923,7 +923,6 @@ static void NCR5380_main(struct work_struct *work) struct NCR5380_hostdata *hostdata = container_of(work, struct NCR5380_hostdata, main_task); struct Scsi_Host *instance = hostdata->host; - struct scsi_cmnd *cmd; int done; /* @@ -936,8 +935,11 @@ static void NCR5380_main(struct work_struct *work) done = 1; spin_lock_irq(&hostdata->lock); - while (!hostdata->connected && - (cmd = dequeue_next_cmd(instance))) { + while (!hostdata->connected && !hostdata->selecting) { + struct scsi_cmnd *cmd = dequeue_next_cmd(instance); + + if (!cmd) + break; dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd); @@ -960,8 +962,7 @@ static void NCR5380_main(struct work_struct *work) #ifdef SUPPORT_TAGS cmd_get_tag(cmd, cmd->cmnd[0] != REQUEST_SENSE); #endif - cmd = NCR5380_select(instance, cmd); - if (!cmd) { + if (!NCR5380_select(instance, cmd)) { dsprintk(NDEBUG_MAIN, instance, "main: select complete\n"); maybe_release_dma_irq(instance); } else { @@ -1257,6 +1258,11 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, /* Reselection interrupt */ goto out; } + if (!hostdata->selecting) { + /* Command was aborted */ + NCR5380_write(MODE_REG, MR_BASE); + goto out; + } if (err < 0) { NCR5380_write(MODE_REG, MR_BASE); shost_printk(KERN_ERR, instance, @@ -1838,9 +1844,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) unsigned char msgout = NOP; int sink = 0; int len; -#if defined(REAL_DMA) int transfersize; -#endif unsigned char *data; unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; struct scsi_cmnd *cmd; @@ -1909,6 +1913,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) do_abort(instance); cmd->result = DID_ERROR << 16; complete_cmd(instance, cmd); + hostdata->connected = NULL; return; #endif case PHASE_DATAIN: @@ -1966,7 +1971,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - complete_cmd(instance, cmd); /* XXX - need to source or sink data here, as appropriate */ } else { #ifdef REAL_DMA @@ -1983,18 +1987,22 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) } else #endif /* defined(REAL_DMA) */ { - spin_unlock_irq(&hostdata->lock); - NCR5380_transfer_pio(instance, &phase, - (int *)&cmd->SCp.this_residual, + /* Break up transfer into 3 ms chunks, + * presuming 6 accesses per handshake. + */ + transfersize = min((unsigned long)cmd->SCp.this_residual, + hostdata->accesses_per_ms / 2); + len = transfersize; + NCR5380_transfer_pio(instance, &phase, &len, (unsigned char **)&cmd->SCp.ptr); - spin_lock_irq(&hostdata->lock); + cmd->SCp.this_residual -= transfersize - len; } #if defined(CONFIG_SUN3) && defined(REAL_DMA) /* if we had intended to dma that command clear it */ if (sun3_dma_setup_done == cmd) sun3_dma_setup_done = NULL; #endif - break; + return; case PHASE_MSGIN: len = 1; data = &tmp; @@ -2487,14 +2495,17 @@ static bool list_del_cmd(struct list_head *haystack, * [disconnected -> connected ->]... * [autosense -> connected ->] done * - * If cmd is unissued then just remove it. - * If cmd is disconnected, try to select the target. - * If cmd is connected, try to send an abort message. - * If cmd is waiting for autosense, give it a chance to complete but check - * that it isn't left connected. * If cmd was not found at all then presumably it has already been completed, * in which case return SUCCESS to try to avoid further EH measures. + * * If the command has not completed yet, we must not fail to find it. + * We have no option but to forget the aborted command (even if it still + * lacks sense data). The mid-layer may re-issue a command that is in error + * recovery (see scsi_send_eh_cmnd), but the logic and data structures in + * this driver are such that a command can appear on one queue only. + * + * The lock protects driver data structures, but EH handlers also use it + * to serialize their own execution and prevent their own re-entry. */ static int NCR5380_abort(struct scsi_cmnd *cmd) @@ -2517,6 +2528,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) "abort: removed %p from issue queue\n", cmd); cmd->result = DID_ABORT << 16; cmd->scsi_done(cmd); /* No tag or busy flag to worry about */ + goto out; } if (hostdata->selecting == cmd) { @@ -2531,58 +2543,21 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) if (list_del_cmd(&hostdata->disconnected, cmd)) { dsprintk(NDEBUG_ABORT, instance, "abort: removed %p from disconnected list\n", cmd); - cmd->result = DID_ERROR << 16; - if (!hostdata->connected) - NCR5380_select(instance, cmd); - if (hostdata->connected != cmd) { - complete_cmd(instance, cmd); - result = FAILED; - goto out; - } + /* Can't call NCR5380_select() and send ABORT because that + * means releasing the lock. Need a bus reset. + */ + set_host_byte(cmd, DID_ERROR); + complete_cmd(instance, cmd); + result = FAILED; + goto out; } if (hostdata->connected == cmd) { dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); hostdata->connected = NULL; - if (do_abort(instance)) { - set_host_byte(cmd, DID_ERROR); - complete_cmd(instance, cmd); - result = FAILED; - goto out; - } - set_host_byte(cmd, DID_ABORT); #ifdef REAL_DMA hostdata->dma_len = 0; #endif - if (cmd->cmnd[0] == REQUEST_SENSE) - complete_cmd(instance, cmd); - else { - struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); - - /* Perform autosense for this command */ - list_add(&ncmd->list, &hostdata->autosense); - } - } - - if (list_find_cmd(&hostdata->autosense, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: found %p on sense queue\n", cmd); - spin_unlock_irqrestore(&hostdata->lock, flags); - queue_work(hostdata->work_q, &hostdata->main_task); - msleep(1000); - spin_lock_irqsave(&hostdata->lock, flags); - if (list_del_cmd(&hostdata->autosense, cmd)) { - dsprintk(NDEBUG_ABORT, instance, - "abort: removed %p from sense queue\n", cmd); - set_host_byte(cmd, DID_ABORT); - complete_cmd(instance, cmd); - goto out; - } - } - - if (hostdata->connected == cmd) { - dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); - hostdata->connected = NULL; if (do_abort(instance)) { set_host_byte(cmd, DID_ERROR); complete_cmd(instance, cmd); @@ -2590,9 +2565,14 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) goto out; } set_host_byte(cmd, DID_ABORT); -#ifdef REAL_DMA - hostdata->dma_len = 0; -#endif + complete_cmd(instance, cmd); + goto out; + } + + if (list_del_cmd(&hostdata->autosense, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: removed %p from sense queue\n", cmd); + set_host_byte(cmd, DID_ERROR); complete_cmd(instance, cmd); } @@ -2646,7 +2626,16 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) * commands! */ - hostdata->selecting = NULL; + if (list_del_cmd(&hostdata->unissued, cmd)) { + cmd->result = DID_RESET << 16; + cmd->scsi_done(cmd); + } + + if (hostdata->selecting) { + hostdata->selecting->result = DID_RESET << 16; + complete_cmd(instance, hostdata->selecting); + hostdata->selecting = NULL; + } list_for_each_entry(ncmd, &hostdata->disconnected, list) { struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); @@ -2654,6 +2643,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) set_host_byte(cmd, DID_RESET); cmd->scsi_done(cmd); } + INIT_LIST_HEAD(&hostdata->disconnected); list_for_each_entry(ncmd, &hostdata->autosense, list) { struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); @@ -2661,6 +2651,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) set_host_byte(cmd, DID_RESET); cmd->scsi_done(cmd); } + INIT_LIST_HEAD(&hostdata->autosense); if (hostdata->connected) { set_host_byte(hostdata->connected, DID_RESET); @@ -2668,12 +2659,6 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) hostdata->connected = NULL; } - if (hostdata->sensing) { - set_host_byte(hostdata->connected, DID_RESET); - complete_cmd(instance, hostdata->sensing); - hostdata->sensing = NULL; - } - #ifdef SUPPORT_TAGS free_all_tags(hostdata); #endif diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index cb9072a84..069e5c50a 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -4468,6 +4468,7 @@ put_shost: scsi_host_put(phba->shost); free_kset: iscsi_boot_destroy_kset(phba->boot_kset); + phba->boot_kset = NULL; return -ENOMEM; } diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index c12696613..ce79de822 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c @@ -278,8 +278,16 @@ int scsi_set_sense_information(u8 *buf, int buf_len, u64 info) ucp[3] = 0; put_unaligned_be64(info, &ucp[4]); } else if ((buf[0] & 0x7f) == 0x70) { - buf[0] |= 0x80; - put_unaligned_be64(info, &buf[3]); + /* + * Only set the 'VALID' bit if we can represent the value + * correctly; otherwise just fill out the lower bytes and + * clear the 'VALID' flag. + */ + if (info <= 0xffffffffUL) + buf[0] |= 0x80; + else + buf[0] &= 0x7f; + put_unaligned_be32((u32)info, &buf[3]); } return 0; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d749da765..5a5457ac9 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -648,7 +648,7 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) */ if (sdkp->lbprz) { q->limits.discard_alignment = 0; - q->limits.discard_granularity = 1; + q->limits.discard_granularity = logical_block_size; } else { q->limits.discard_alignment = sdkp->unmap_alignment * logical_block_size; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 5e8206744..ae7d9bdf4 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -652,7 +652,8 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) else hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV : SG_DXFER_NONE; hp->dxfer_len = mxsize; - if (hp->dxfer_direction == SG_DXFER_TO_DEV) + if ((hp->dxfer_direction == SG_DXFER_TO_DEV) || + (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV)) hp->dxferp = (char __user *)buf + cmd_size; else hp->dxferp = NULL; diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 292c04eec..3ddcabb79 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -914,8 +914,9 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, do_work = true; process_err_fn = storvsc_remove_lun; break; - case (SRB_STATUS_ABORTED | SRB_STATUS_AUTOSENSE_VALID): - if ((asc == 0x2a) && (ascq == 0x9)) { + case SRB_STATUS_ABORTED: + if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID && + (asc == 0x2a) && (ascq == 0x9)) { do_work = true; process_err_fn = storvsc_device_scan; /* diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c index b8dcf5a26..58d46893e 100644 --- a/drivers/staging/android/ion/ion_test.c +++ b/drivers/staging/android/ion/ion_test.c @@ -285,8 +285,8 @@ static int __init ion_test_init(void) { ion_test_pdev = platform_device_register_simple("ion-test", -1, NULL, 0); - if (!ion_test_pdev) - return -ENODEV; + if (IS_ERR(ion_test_pdev)) + return PTR_ERR(ion_test_pdev); return platform_driver_probe(&ion_test_platform_driver, ion_test_probe); } diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 5e8130a7d..0e9f77924 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -246,24 +246,24 @@ static void ni_writel(struct comedi_device *dev, uint32_t data, int reg) { if (dev->mmio) writel(data, dev->mmio + reg); - - outl(data, dev->iobase + reg); + else + outl(data, dev->iobase + reg); } static void ni_writew(struct comedi_device *dev, uint16_t data, int reg) { if (dev->mmio) writew(data, dev->mmio + reg); - - outw(data, dev->iobase + reg); + else + outw(data, dev->iobase + reg); } static void ni_writeb(struct comedi_device *dev, uint8_t data, int reg) { if (dev->mmio) writeb(data, dev->mmio + reg); - - outb(data, dev->iobase + reg); + else + outb(data, dev->iobase + reg); } static uint32_t ni_readl(struct comedi_device *dev, int reg) diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 437f723bb..823e47910 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -92,7 +92,7 @@ static int ni_tio_input_inttrig(struct comedi_device *dev, unsigned long flags; int ret = 0; - if (trig_num != cmd->start_src) + if (trig_num != cmd->start_arg) return -EINVAL; spin_lock_irqsave(&counter->lock, flags); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 867bc6d0a..43d8b42c0 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2596,8 +2596,6 @@ void target_wait_for_sess_cmds(struct se_session *se_sess) list_for_each_entry_safe(se_cmd, tmp_cmd, &se_sess->sess_wait_list, 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)); diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index a0a8fd123..d4b54653e 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -454,6 +454,10 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) { enum thermal_trip_type type; + /* Ignore disabled trip points */ + if (test_bit(trip, &tz->trips_disabled)) + return; + tz->ops->get_trip_type(tz, trip, &type); if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) @@ -1800,6 +1804,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, { struct thermal_zone_device *tz; enum thermal_trip_type trip_type; + int trip_temp; int result; int count; int passive = 0; @@ -1871,9 +1876,15 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, goto unregister; for (count = 0; count < trips; count++) { - tz->ops->get_trip_type(tz, count, &trip_type); + if (tz->ops->get_trip_type(tz, count, &trip_type)) + set_bit(count, &tz->trips_disabled); if (trip_type == THERMAL_TRIP_PASSIVE) passive = 1; + if (tz->ops->get_trip_temp(tz, count, &trip_temp)) + set_bit(count, &tz->trips_disabled); + /* Check for bogus trip points */ + if (trip_temp == 0) + set_bit(count, &tz->trips_disabled); } if (!passive) { diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 83aed6193..b1a6ba3c3 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -731,22 +731,16 @@ static int size_fifo(struct uart_8250_port *up) */ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p) { - unsigned char old_dll, old_dlm, old_lcr; - unsigned int id; + unsigned char old_lcr; + unsigned int id, old_dl; old_lcr = serial_in(p, UART_LCR); serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A); + old_dl = serial_dl_read(p); + serial_dl_write(p, 0); + id = serial_dl_read(p); + serial_dl_write(p, old_dl); - old_dll = serial_in(p, UART_DLL); - old_dlm = serial_in(p, UART_DLM); - - serial_out(p, UART_DLL, 0); - serial_out(p, UART_DLM, 0); - - id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8; - - serial_out(p, UART_DLL, old_dll); - serial_out(p, UART_DLM, old_dlm); serial_out(p, UART_LCR, old_lcr); return id; diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index fa4e23930..d37fdcc31 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1114,6 +1114,9 @@ static int acm_probe(struct usb_interface *intf, if (quirks == NO_UNION_NORMAL) { data_interface = usb_ifnum_to_if(usb_dev, 1); control_interface = usb_ifnum_to_if(usb_dev, 0); + /* we would crash */ + if (!data_interface || !control_interface) + return -ENODEV; goto skip_normal_probe; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 56593a9a8..2057d91d8 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -502,11 +502,15 @@ static int usb_unbind_interface(struct device *dev) int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv) { - struct device *dev = &iface->dev; + struct device *dev; struct usb_device *udev; int retval = 0; int lpm_disable_error; + if (!iface) + return -ENODEV; + + dev = &iface->dev; if (dev->driver) return -EBUSY; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 51b436918..84f65743f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4292,7 +4292,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, { struct usb_device *hdev = hub->hdev; struct usb_hcd *hcd = bus_to_hcd(hdev->bus); - int i, j, retval; + int retries, operations, retval, i; unsigned delay = HUB_SHORT_RESET_TIME; enum usb_device_speed oldspeed = udev->speed; const char *speed; @@ -4394,7 +4394,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * first 8 bytes of the device descriptor to get the ep0 maxpacket * value. */ - for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { + for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) { bool did_new_scheme = false; if (use_new_scheme(udev, retry_counter)) { @@ -4421,7 +4421,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * 255 is for WUSB devices, we actually need to use * 512 (WUSB1.0[4.8.1]). */ - for (j = 0; j < 3; ++j) { + for (operations = 0; operations < 3; ++operations) { buf->bMaxPacketSize0 = 0; r = usb_control_msg(udev, usb_rcvaddr0pipe(), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, @@ -4441,7 +4441,13 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, r = -EPROTO; break; } - if (r == 0) + /* + * Some devices time out if they are powered on + * when already connected. They need a second + * reset. But only on the first attempt, + * lest we get into a time out/reset loop + */ + if (r == 0 || (r == -ETIMEDOUT && retries == 0)) break; } udev->descriptor.bMaxPacketSize0 = @@ -4473,7 +4479,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * authorization will assign the final address. */ if (udev->wusb == 0) { - for (j = 0; j < SET_ADDRESS_TRIES; ++j) { + for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) { retval = hub_set_address(udev, devnum); if (retval >= 0) break; diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index c6bfd13f6..1950e87b4 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -787,6 +787,12 @@ static int iowarrior_probe(struct usb_interface *interface, iface_desc = interface->cur_altsetting; dev->product_id = le16_to_cpu(udev->descriptor.idProduct); + if (iface_desc->desc.bNumEndpoints < 1) { + dev_err(&interface->dev, "Invalid number of endpoints\n"); + retval = -EINVAL; + goto error; + } + /* set up the endpoint information */ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 73a366de5..9bc0e090b 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -165,6 +165,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(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 01bf53392..244acb129 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -447,6 +447,11 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) struct usb_serial *serial = port->serial; struct cypress_private *priv; + if (!port->interrupt_out_urb || !port->interrupt_in_urb) { + dev_err(&port->dev, "required endpoint is missing\n"); + return -ENODEV; + } + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -606,12 +611,6 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) cypress_set_termios(tty, port, &priv->tmp_termios); /* setup the port and start reading from the device */ - if (!port->interrupt_in_urb) { - dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n", - __func__); - return -1; - } - usb_fill_int_urb(port->interrupt_in_urb, serial->dev, usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), port->interrupt_in_urb->transfer_buffer, diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 12b0e6747..3df7b7ec1 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1251,8 +1251,27 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) static int digi_startup(struct usb_serial *serial) { + struct device *dev = &serial->interface->dev; struct digi_serial *serial_priv; int ret; + int i; + + /* check whether the device has the expected number of endpoints */ + if (serial->num_port_pointers < serial->type->num_ports + 1) { + dev_err(dev, "OOB endpoints missing\n"); + return -ENODEV; + } + + for (i = 0; i < serial->type->num_ports + 1 ; i++) { + if (!serial->port[i]->read_urb) { + dev_err(dev, "bulk-in endpoint missing\n"); + return -ENODEV; + } + if (!serial->port[i]->write_urb) { + dev_err(dev, "bulk-out endpoint missing\n"); + return -ENODEV; + } + } serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); if (!serial_priv) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8c660ae40..b61f12160 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1004,6 +1004,10 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) }, { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) }, { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) }, + /* ICP DAS I-756xU devices */ + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) }, + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) }, + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index a84df2513..c5d6c1e73 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -871,6 +871,14 @@ #define NOVITUS_VID 0x1a28 #define NOVITUS_BONO_E_PID 0x6010 +/* + * ICPDAS I-756*U devices + */ +#define ICPDAS_VID 0x1b5c +#define ICPDAS_I7560U_PID 0x0103 +#define ICPDAS_I7561U_PID 0x0104 +#define ICPDAS_I7563U_PID 0x0105 + /* * RT Systems programming cables for various ham radios */ diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index fd707d6a1..89726f702 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -376,14 +376,21 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port, static int mct_u232_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct mct_u232_private *priv; + /* check first to simplify error handling */ + if (!serial->port[1] || !serial->port[1]->interrupt_in_urb) { + dev_err(&port->dev, "expected endpoint missing\n"); + return -ENODEV; + } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; /* Use second interrupt-in endpoint for reading. */ - priv->read_urb = port->serial->port[1]->interrupt_in_urb; + priv->read_urb = serial->port[1]->interrupt_in_urb; priv->read_urb->context = port; spin_lock_init(&priv->lock); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 348e19834..c6f497f16 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1818,6 +1818,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) }, { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, + { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */ diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 9ff9404f9..c90a7e46c 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -812,7 +812,7 @@ static struct scsi_host_template uas_host_template = { .slave_configure = uas_slave_configure, .eh_abort_handler = uas_eh_abort_handler, .eh_bus_reset_handler = uas_eh_bus_reset_handler, - .can_queue = 65536, /* Is there a limit on the _host_ ? */ + .can_queue = MAX_CMNDS, .this_id = -1, .sg_tablesize = SG_NONE, .skip_settle_delay = 1, diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index 71e78ef4b..3a75f3b53 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -237,7 +237,7 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, return -EINVAL; /* Fall through */ case WDIOC_GETTIMEOUT: - return copy_to_user(argp, &timeout, sizeof(int)); + return copy_to_user(argp, &timeout, sizeof(int)) ? -EFAULT : 0; default: return -ENOTTY; } -- cgit v1.2.3