diff options
Diffstat (limited to 'drivers')
174 files changed, 1651 insertions, 977 deletions
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 00a783661d0..46f80e2c92f 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -590,6 +590,9 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && *access_bit_width < 32) *access_bit_width = 32; + else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 && + *access_bit_width < 64) + *access_bit_width = 64; if ((bit_width + bit_offset) > *access_bit_width) { pr_warning(FW_BUG APEI_PFX diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 95af6f674a6..35da1811321 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -297,7 +297,7 @@ static int acpi_platform_notify(struct device *dev) if (!ret) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer); + acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer); DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); kfree(buffer.pointer); } else diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f1a5da44591..ed9a1cc690b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -958,6 +958,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) return -EINVAL; } + if (!dev) + return -EINVAL; + dev->cpu = pr->id; if (max_cstate == 0) @@ -1149,6 +1152,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) } /* Populate Updated C-state information */ + acpi_processor_get_power_info(pr); acpi_processor_setup_cpuidle_states(pr); /* Enable all cpuidle devices */ diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 836bfe06904..53e7ac9403a 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -340,6 +340,13 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i) if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) || boot_cpu_data.x86 == 0x11) { rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); + /* + * MSR C001_0064+: + * Bit 63: PstateEn. Read-write. If set, the P-state is valid. + */ + if (!(hi & BIT(31))) + return; + fid = lo & 0x3f; did = (lo >> 6) & 7; if (boot_cpu_data.x86 == 0x10) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 7862d17976b..49791273256 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -53,6 +53,7 @@ enum { AHCI_PCI_BAR_STA2X11 = 0, + AHCI_PCI_BAR_ENMOTUS = 2, AHCI_PCI_BAR_STANDARD = 5, }; @@ -410,6 +411,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ + /* Enmotus */ + { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, + /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, @@ -1098,9 +1102,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "PDC42819 can only drive SATA devices with this driver\n"); - /* The Connext uses non-standard BAR */ + /* Both Connext and Enmotus devices use non-standard BARs */ if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) ahci_pci_bar = AHCI_PCI_BAR_STA2X11; + else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) + ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; /* acquire resources */ rc = pcim_enable_device(pdev); diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 320712a7b9e..6cd7805e47c 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1951,13 +1951,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) /* Use the nominal value 10 ms if the read MDAT is zero, * the nominal value of DETO is 20 ms. */ - if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] & + if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] & ATA_LOG_DEVSLP_VALID_MASK) { - mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] & + mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] & ATA_LOG_DEVSLP_MDAT_MASK; if (!mdat) mdat = 10; - deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO]; + deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO]; if (!deto) deto = 20; } else { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9e8b99af400..46cd3f4c6aa 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev) } } - /* check and mark DevSlp capability */ - if (ata_id_has_devslp(dev->id)) - dev->flags |= ATA_DFLAG_DEVSLP; - - /* Obtain SATA Settings page from Identify Device Data Log, - * which contains DevSlp timing variables etc. - * Exclude old devices with ata_id_has_ncq() + /* Check and mark DevSlp capability. Get DevSlp timing variables + * from SATA Settings page of Identify Device Data Log. */ - if (ata_id_has_ncq(dev->id)) { + if (ata_id_has_devslp(dev->id)) { + u8 sata_setting[ATA_SECT_SIZE]; + int i, j; + + dev->flags |= ATA_DFLAG_DEVSLP; err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA, ATA_LOG_SATA_SETTINGS, - dev->sata_settings, + sata_setting, 1); if (err_mask) ata_dev_dbg(dev, "failed to get Identify Device Data, Emask 0x%x\n", err_mask); + else + for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) { + j = ATA_LOG_DEVSLP_OFFSET + i; + dev->devslp_timing[i] = sata_setting[j]; + } } dev->cdb_len = 16; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index bf039b0e97b..bcf4437214f 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2094,7 +2094,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, */ static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc) { - if (qc->flags & AC_ERR_MEDIA) + if (qc->err_mask & AC_ERR_MEDIA) return 0; /* don't retry media errors */ if (qc->flags & ATA_QCFLAG_IO) return 1; /* otherwise retry anything from fs stack */ diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 63452943abd..fb10728f637 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -224,7 +224,7 @@ static void cpu_device_release(struct device *dev) * by the cpu device. * * Never copy this way of doing things, or you too will be made fun of - * on the linux-kerenl list, you have been warned. + * on the linux-kernel list, you have been warned. */ } diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index d8146030918..b392b353be3 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -305,7 +305,7 @@ static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf char *buf; size = fw_file_size(file); - if (size < 0) + if (size <= 0) return false; buf = vmalloc(size); if (!buf) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 07aad786f81..d9a6c94ce42 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -56,6 +56,19 @@ static const struct file_operations regmap_name_fops = { .llseek = default_llseek, }; +static void regmap_debugfs_free_dump_cache(struct regmap *map) +{ + struct regmap_debugfs_off_cache *c; + + while (!list_empty(&map->debugfs_off_cache)) { + c = list_first_entry(&map->debugfs_off_cache, + struct regmap_debugfs_off_cache, + list); + list_del(&c->list); + kfree(c); + } +} + /* * Work out where the start offset maps into register numbers, bearing * in mind that we suppress hidden registers. @@ -91,8 +104,10 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, /* No cache entry? Start a new one */ if (!c) { c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) - break; + if (!c) { + regmap_debugfs_free_dump_cache(map); + return base; + } c->min = p; c->base_reg = i; } @@ -101,14 +116,32 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, } } + /* Close the last entry off if we didn't scan beyond it */ + if (c) { + c->max = p - 1; + list_add_tail(&c->list, + &map->debugfs_off_cache); + } + + /* + * This should never happen; we return above if we fail to + * allocate and we should never be in this code if there are + * no registers at all. + */ + if (list_empty(&map->debugfs_off_cache)) { + WARN_ON(list_empty(&map->debugfs_off_cache)); + return base; + } + /* Find the relevant block */ list_for_each_entry(c, &map->debugfs_off_cache, list) { - if (*pos >= c->min && *pos <= c->max) { + if (from >= c->min && from <= c->max) { *pos = c->min; return c->base_reg; } - ret = c->max; + *pos = c->min; + ret = c->base_reg; } return ret; @@ -387,16 +420,8 @@ void regmap_debugfs_init(struct regmap *map, const char *name) void regmap_debugfs_exit(struct regmap *map) { - struct regmap_debugfs_off_cache *c; - debugfs_remove_recursive(map->debugfs); - while (!list_empty(&map->debugfs_off_cache)) { - c = list_first_entry(&map->debugfs_off_cache, - struct regmap_debugfs_off_cache, - list); - list_del(&c->list); - kfree(c); - } + regmap_debugfs_free_dump_cache(map); kfree(map->debugfs_name); } diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 42d5cb0f503..f00b059c057 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1106,7 +1106,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_write); * @val_count: Number of registers to write * * This function is intended to be used for writing a large block of - * data to be device either in single transfer or multiple transfer. + * data to the device either in single transfer or multiple transfer. * * A value of zero will be returned on success, a negative errno will * be returned in error cases. diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 9d8409c0208..8ad21a25bc0 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -889,6 +889,7 @@ static void virtblk_remove(struct virtio_device *vdev) { struct virtio_blk *vblk = vdev->priv; int index = vblk->index; + int refc; /* Prevent config work handler from accessing the device. */ mutex_lock(&vblk->config_lock); @@ -903,11 +904,15 @@ static void virtblk_remove(struct virtio_device *vdev) flush_work(&vblk->config_work); + refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount); put_disk(vblk->disk); mempool_destroy(vblk->pool); vdev->config->del_vqs(vdev); kfree(vblk); - ida_simple_remove(&vd_index_ida, index); + + /* Only free device id if we don't have any users */ + if (refc == 1) + ida_simple_remove(&vd_index_ida, index); } #ifdef CONFIG_PM diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c index ff004578a11..9dd2551a0a4 100644 --- a/drivers/clk/mvebu/clk-cpu.c +++ b/drivers/clk/mvebu/clk-cpu.c @@ -124,7 +124,7 @@ void __init of_cpu_clk_setup(struct device_node *node) clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL); if (WARN_ON(!clks)) - return; + goto clks_out; for_each_node_by_type(dn, "cpu") { struct clk_init_data init; @@ -134,11 +134,11 @@ void __init of_cpu_clk_setup(struct device_node *node) int cpu, err; if (WARN_ON(!clk_name)) - return; + goto bail_out; err = of_property_read_u32(dn, "reg", &cpu); if (WARN_ON(err)) - return; + goto bail_out; sprintf(clk_name, "cpu%d", cpu); parent_clk = of_clk_get(node, 0); @@ -167,6 +167,9 @@ void __init of_cpu_clk_setup(struct device_node *node) return; bail_out: kfree(clks); + while(ncpus--) + kfree(cpuclk[ncpus].clk_name); +clks_out: kfree(cpuclk); } diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 934854ae5eb..7227cd73404 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -106,7 +106,7 @@ config X86_POWERNOW_K7_ACPI config X86_POWERNOW_K8 tristate "AMD Opteron/Athlon64 PowerNow!" select CPU_FREQ_TABLE - depends on ACPI && ACPI_PROCESSOR + depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ help This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. Support for K10 and newer processors is now in acpi-cpufreq. diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 0d048f6a2b2..7b0d49d78c6 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -1030,4 +1030,11 @@ MODULE_PARM_DESC(acpi_pstate_strict, late_initcall(acpi_cpufreq_init); module_exit(acpi_cpufreq_exit); +static const struct x86_cpu_id acpi_cpufreq_ids[] = { + X86_FEATURE_MATCH(X86_FEATURE_ACPI), + X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE), + {} +}; +MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids); + MODULE_ALIAS("acpi"); diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 52bf36d599f..debc5a7c8db 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -71,12 +71,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy, } if (cpu_reg) { + rcu_read_lock(); opp = opp_find_freq_ceil(cpu_dev, &freq_Hz); if (IS_ERR(opp)) { + rcu_read_unlock(); pr_err("failed to find OPP for %ld\n", freq_Hz); return PTR_ERR(opp); } volt = opp_get_voltage(opp); + rcu_read_unlock(); tol = volt * voltage_tolerance / 100; volt_old = regulator_get_voltage(cpu_reg); } @@ -236,12 +239,14 @@ static int cpu0_cpufreq_driver_init(void) */ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) ; + rcu_read_lock(); opp = opp_find_freq_exact(cpu_dev, freq_table[0].frequency * 1000, true); min_uV = opp_get_voltage(opp); opp = opp_find_freq_exact(cpu_dev, freq_table[i-1].frequency * 1000, true); max_uV = opp_get_voltage(opp); + rcu_read_unlock(); ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); if (ret > 0) transition_latency += ret * 1000; diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 1f3417a8322..97102b05843 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -110,13 +110,16 @@ static int omap_target(struct cpufreq_policy *policy, freq = ret; if (mpu_reg) { + rcu_read_lock(); opp = opp_find_freq_ceil(mpu_dev, &freq); if (IS_ERR(opp)) { + rcu_read_unlock(); dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", __func__, freqs.new); return -EINVAL; } volt = opp_get_voltage(opp); + rcu_read_unlock(); tol = volt * OPP_TOLERANCE / 100; volt_old = regulator_get_voltage(mpu_reg); } diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fb4a7dd57f9..e1f6860e069 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -69,24 +69,15 @@ int cpuidle_play_dead(void) { struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); - int i, dead_state = -1; - int power_usage = INT_MAX; + int i; if (!drv) return -ENODEV; /* Find lowest-power state that supports long-term idle */ - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { - struct cpuidle_state *s = &drv->states[i]; - - if (s->power_usage < power_usage && s->enter_dead) { - power_usage = s->power_usage; - dead_state = i; - } - } - - if (dead_state != -1) - return drv->states[dead_state].enter_dead(dev, dead_state); + for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--) + if (drv->states[i].enter_dead) + return drv->states[i].enter_dead(dev, i); return -ENODEV; } diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index c2b281afe0e..422c7b69ba7 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -19,34 +19,9 @@ DEFINE_SPINLOCK(cpuidle_driver_lock); static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); -static void set_power_states(struct cpuidle_driver *drv) -{ - int i; - - /* - * cpuidle driver should set the drv->power_specified bit - * before registering if the driver provides - * power_usage numbers. - * - * If power_specified is not set, - * we fill in power_usage with decreasing values as the - * cpuidle code has an implicit assumption that state Cn - * uses less power than C(n-1). - * - * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned - * an power value of -1. So we use -2, -3, etc, for other - * c-states. - */ - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) - drv->states[i].power_usage = -1 - i; -} - static void __cpuidle_driver_init(struct cpuidle_driver *drv) { drv->refcnt = 0; - - if (!drv->power_specified) - set_power_states(drv); } static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 20ea33afdda..fe343a06b7d 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -312,7 +312,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = &__get_cpu_var(menu_devices); int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); - int power_usage = INT_MAX; int i; int multiplier; struct timespec t; @@ -383,11 +382,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) if (s->exit_latency * multiplier > data->predicted_us) continue; - if (s->power_usage < power_usage) { - power_usage = s->power_usage; - data->last_state_idx = i; - data->exit_us = s->exit_latency; - } + data->last_state_idx = i; + data->exit_us = s->exit_latency; } /* not deepest C-state chosen for low predicted residency */ diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 34094294610..428754af623 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -374,7 +374,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); /* state statistics */ - for (i = 0; i < drv->state_count; i++) { + for (i = 0; i < device->state_count; i++) { kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); if (!kobj) goto error_state; diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 53766f39aad..3b367973a80 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -994,6 +994,11 @@ module_exit(devfreq_exit); * @freq: The frequency given to target function * @flags: Flags handed from devfreq framework. * + * Locking: This function must be called under rcu_read_lock(). opp is a rcu + * protected pointer. The reason for the same is that the opp pointer which is + * returned will remain valid for use with opp_get_{voltage, freq} only while + * under the locked area. The pointer returned must be used prior to unlocking + * with rcu_read_unlock() to maintain the integrity of the pointer. */ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, u32 flags) diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c index 80c745e8308..46d94e9e95b 100644 --- a/drivers/devfreq/exynos4_bus.c +++ b/drivers/devfreq/exynos4_bus.c @@ -73,6 +73,16 @@ enum busclk_level_idx { #define EX4210_LV_NUM (LV_2 + 1) #define EX4x12_LV_NUM (LV_4 + 1) +/** + * struct busfreq_opp_info - opp information for bus + * @rate: Frequency in hertz + * @volt: Voltage in microvolts corresponding to this OPP + */ +struct busfreq_opp_info { + unsigned long rate; + unsigned long volt; +}; + struct busfreq_data { enum exynos4_busf_type type; struct device *dev; @@ -80,7 +90,7 @@ struct busfreq_data { bool disabled; struct regulator *vdd_int; struct regulator *vdd_mif; /* Exynos4412/4212 only */ - struct opp *curr_opp; + struct busfreq_opp_info curr_oppinfo; struct exynos4_ppmu dmc[2]; struct notifier_block pm_notifier; @@ -296,13 +306,14 @@ static unsigned int exynos4x12_clkdiv_sclkip[][3] = { }; -static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) +static int exynos4210_set_busclk(struct busfreq_data *data, + struct busfreq_opp_info *oppi) { unsigned int index; unsigned int tmp; for (index = LV_0; index < EX4210_LV_NUM; index++) - if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk) + if (oppi->rate == exynos4210_busclk_table[index].clk) break; if (index == EX4210_LV_NUM) @@ -361,13 +372,14 @@ static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) return 0; } -static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp) +static int exynos4x12_set_busclk(struct busfreq_data *data, + struct busfreq_opp_info *oppi) { unsigned int index; unsigned int tmp; for (index = LV_0; index < EX4x12_LV_NUM; index++) - if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk) + if (oppi->rate == exynos4x12_mifclk_table[index].clk) break; if (index == EX4x12_LV_NUM) @@ -576,11 +588,12 @@ static int exynos4x12_get_intspec(unsigned long mifclk) return -EINVAL; } -static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, - struct opp *oldopp) +static int exynos4_bus_setvolt(struct busfreq_data *data, + struct busfreq_opp_info *oppi, + struct busfreq_opp_info *oldoppi) { int err = 0, tmp; - unsigned long volt = opp_get_voltage(opp); + unsigned long volt = oppi->volt; switch (data->type) { case TYPE_BUSF_EXYNOS4210: @@ -595,11 +608,11 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, if (err) break; - tmp = exynos4x12_get_intspec(opp_get_freq(opp)); + tmp = exynos4x12_get_intspec(oppi->rate); if (tmp < 0) { err = tmp; regulator_set_voltage(data->vdd_mif, - opp_get_voltage(oldopp), + oldoppi->volt, MAX_SAFEVOLT); break; } @@ -609,7 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, /* Try to recover */ if (err) regulator_set_voltage(data->vdd_mif, - opp_get_voltage(oldopp), + oldoppi->volt, MAX_SAFEVOLT); break; default: @@ -626,17 +639,26 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, struct platform_device *pdev = container_of(dev, struct platform_device, dev); struct busfreq_data *data = platform_get_drvdata(pdev); - struct opp *opp = devfreq_recommended_opp(dev, _freq, flags); - unsigned long freq = opp_get_freq(opp); - unsigned long old_freq = opp_get_freq(data->curr_opp); + struct opp *opp; + unsigned long freq; + unsigned long old_freq = data->curr_oppinfo.rate; + struct busfreq_opp_info new_oppinfo; - if (IS_ERR(opp)) + rcu_read_lock(); + opp = devfreq_recommended_opp(dev, _freq, flags); + if (IS_ERR(opp)) { + rcu_read_unlock(); return PTR_ERR(opp); + } + new_oppinfo.rate = opp_get_freq(opp); + new_oppinfo.volt = opp_get_voltage(opp); + rcu_read_unlock(); + freq = new_oppinfo.rate; if (old_freq == freq) return 0; - dev_dbg(dev, "targetting %lukHz %luuV\n", freq, opp_get_voltage(opp)); + dev_dbg(dev, "targetting %lukHz %luuV\n", freq, new_oppinfo.volt); mutex_lock(&data->lock); @@ -644,17 +666,18 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, goto out; if (old_freq < freq) - err = exynos4_bus_setvolt(data, opp, data->curr_opp); + err = exynos4_bus_setvolt(data, &new_oppinfo, + &data->curr_oppinfo); if (err) goto out; if (old_freq != freq) { switch (data->type) { case TYPE_BUSF_EXYNOS4210: - err = exynos4210_set_busclk(data, opp); + err = exynos4210_set_busclk(data, &new_oppinfo); break; case TYPE_BUSF_EXYNOS4x12: - err = exynos4x12_set_busclk(data, opp); + err = exynos4x12_set_busclk(data, &new_oppinfo); break; default: err = -EINVAL; @@ -664,11 +687,12 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, goto out; if (old_freq > freq) - err = exynos4_bus_setvolt(data, opp, data->curr_opp); + err = exynos4_bus_setvolt(data, &new_oppinfo, + &data->curr_oppinfo); if (err) goto out; - data->curr_opp = opp; + data->curr_oppinfo = new_oppinfo; out: mutex_unlock(&data->lock); return err; @@ -702,7 +726,7 @@ static int exynos4_bus_get_dev_status(struct device *dev, exynos4_read_ppmu(data); busier_dmc = exynos4_get_busier_dmc(data); - stat->current_frequency = opp_get_freq(data->curr_opp); + stat->current_frequency = data->curr_oppinfo.rate; if (busier_dmc) addr = S5P_VA_DMC1; @@ -933,6 +957,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, struct busfreq_data *data = container_of(this, struct busfreq_data, pm_notifier); struct opp *opp; + struct busfreq_opp_info new_oppinfo; unsigned long maxfreq = ULONG_MAX; int err = 0; @@ -943,18 +968,29 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, data->disabled = true; + rcu_read_lock(); opp = opp_find_freq_floor(data->dev, &maxfreq); + if (IS_ERR(opp)) { + rcu_read_unlock(); + dev_err(data->dev, "%s: unable to find a min freq\n", + __func__); + return PTR_ERR(opp); + } + new_oppinfo.rate = opp_get_freq(opp); + new_oppinfo.volt = opp_get_voltage(opp); + rcu_read_unlock(); - err = exynos4_bus_setvolt(data, opp, data->curr_opp); + err = exynos4_bus_setvolt(data, &new_oppinfo, + &data->curr_oppinfo); if (err) goto unlock; switch (data->type) { case TYPE_BUSF_EXYNOS4210: - err = exynos4210_set_busclk(data, opp); + err = exynos4210_set_busclk(data, &new_oppinfo); break; case TYPE_BUSF_EXYNOS4x12: - err = exynos4x12_set_busclk(data, opp); + err = exynos4x12_set_busclk(data, &new_oppinfo); break; default: err = -EINVAL; @@ -962,7 +998,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, if (err) goto unlock; - data->curr_opp = opp; + data->curr_oppinfo = new_oppinfo; unlock: mutex_unlock(&data->lock); if (err) @@ -1027,13 +1063,17 @@ static int exynos4_busfreq_probe(struct platform_device *pdev) } } + rcu_read_lock(); opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); if (IS_ERR(opp)) { + rcu_read_unlock(); dev_err(dev, "Invalid initial frequency %lu kHz.\n", exynos4_devfreq_profile.initial_freq); return PTR_ERR(opp); } - data->curr_opp = opp; + data->curr_oppinfo.rate = opp_get_freq(opp); + data->curr_oppinfo.volt = opp_get_voltage(opp); + rcu_read_unlock(); platform_set_drvdata(pdev, data); diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index dbf0e6f8de8..a7dcf78b1ff 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -684,9 +684,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, break; } - imxdmac->hw_chaining = 1; - if (!imxdma_hw_chain(imxdmac)) - return -EINVAL; + imxdmac->hw_chaining = 0; + imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) | ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) | CCR_REN; diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index e5fc944de1f..3e9d66920eb 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -951,7 +951,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) goto free_resources; } } - dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE); + dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); /* skip validate if the capability is not present */ if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index c39e61bc817..3cad856fe67 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -266,6 +266,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get( if (async_tx_test_ack(&dma_desc->txd)) { list_del(&dma_desc->node); spin_unlock_irqrestore(&tdc->lock, flags); + dma_desc->txd.flags = 0; return dma_desc; } } @@ -1050,7 +1051,9 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT; ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; - csr |= TEGRA_APBDMA_CSR_FLOW | TEGRA_APBDMA_CSR_IE_EOC; + csr |= TEGRA_APBDMA_CSR_FLOW; + if (flags & DMA_PREP_INTERRUPT) + csr |= TEGRA_APBDMA_CSR_IE_EOC; csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; @@ -1095,7 +1098,8 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( mem += len; } sg_req->last_sg = true; - dma_desc->txd.flags = 0; + if (flags & DMA_CTRL_ACK) + dma_desc->txd.flags = DMA_CTRL_ACK; /* * Make sure that mode should not be conflicting with currently diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7d9bd94be8d..6819d63cb16 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -547,7 +547,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); if (! mvchip->membase) { dev_err(&pdev->dev, "Cannot ioremap\n"); - kfree(mvchip->chip.label); return -ENOMEM; } @@ -557,14 +556,12 @@ static int mvebu_gpio_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (! res) { dev_err(&pdev->dev, "Cannot get memory resource\n"); - kfree(mvchip->chip.label); return -ENODEV; } mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res); if (! mvchip->percpu_membase) { dev_err(&pdev->dev, "Cannot ioremap\n"); - kfree(mvchip->chip.label); return -ENOMEM; } } @@ -625,7 +622,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); if (mvchip->irqbase < 0) { dev_err(&pdev->dev, "no irqs\n"); - kfree(mvchip->chip.label); return -ENOMEM; } @@ -633,7 +629,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->membase, handle_level_irq); if (! gc) { dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); - kfree(mvchip->chip.label); return -ENOMEM; } @@ -668,7 +663,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); kfree(gc); - kfree(mvchip->chip.label); return -ENODEV; } diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 01f7fe95559..76be7eed79d 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -32,7 +32,6 @@ #include <mach/hardware.h> #include <mach/map.h> -#include <mach/regs-clock.h> #include <mach/regs-gpio.h> #include <plat/cpu.h> @@ -446,7 +445,7 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = { }; #endif -#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5) +#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_SOC_EXYNOS5250) static struct samsung_gpio_cfg exynos_gpio_cfg = { .set_pull = exynos_gpio_setpull, .get_pull = exynos_gpio_getpull, @@ -2446,7 +2445,7 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { }; #endif -#ifdef CONFIG_ARCH_EXYNOS5 +#ifdef CONFIG_SOC_EXYNOS5250 static struct samsung_gpio_chip exynos5_gpios_1[] = { { .chip = { @@ -2614,7 +2613,7 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = { }; #endif -#ifdef CONFIG_ARCH_EXYNOS5 +#ifdef CONFIG_SOC_EXYNOS5250 static struct samsung_gpio_chip exynos5_gpios_2[] = { { .chip = { @@ -2675,7 +2674,7 @@ static struct samsung_gpio_chip exynos5_gpios_2[] = { }; #endif -#ifdef CONFIG_ARCH_EXYNOS5 +#ifdef CONFIG_SOC_EXYNOS5250 static struct samsung_gpio_chip exynos5_gpios_3[] = { { .chip = { @@ -2711,7 +2710,7 @@ static struct samsung_gpio_chip exynos5_gpios_3[] = { }; #endif -#ifdef CONFIG_ARCH_EXYNOS5 +#ifdef CONFIG_SOC_EXYNOS5250 static struct samsung_gpio_chip exynos5_gpios_4[] = { { .chip = { @@ -3010,7 +3009,7 @@ static __init int samsung_gpiolib_init(void) int i, nr_chips; int group = 0; -#ifdef CONFIG_PINCTRL_SAMSUNG +#if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440) /* * This gpio driver includes support for device tree support and there * are platforms using it. In order to maintain compatibility with those @@ -3026,6 +3025,7 @@ static __init int samsung_gpiolib_init(void) static const struct of_device_id exynos_pinctrl_ids[] = { { .compatible = "samsung,pinctrl-exynos4210", }, { .compatible = "samsung,pinctrl-exynos4x12", }, + { .compatible = "samsung,pinctrl-exynos5440", }, }; for_each_matching_node(pctrl_np, exynos_pinctrl_ids) if (pctrl_np && of_device_is_available(pctrl_np)) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e6a11ca85ea..7944d301518 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -641,6 +641,7 @@ static void i915_ring_error_state(struct seq_file *m, seq_printf(m, "%s command stream:\n", ring_str(ring)); seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]); seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); + seq_printf(m, " CTL: 0x%08x\n", error->ctl[ring]); seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]); seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); @@ -693,6 +694,8 @@ static int i915_error_state(struct seq_file *m, void *unused) seq_printf(m, "EIR: 0x%08x\n", error->eir); seq_printf(m, "IER: 0x%08x\n", error->ier); seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); + seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); + seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr); seq_printf(m, "CCID: 0x%08x\n", error->ccid); for (i = 0; i < dev_priv->num_fence_regs; i++) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ed305957557..12ab3bdea54 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -188,10 +188,13 @@ struct drm_i915_error_state { u32 pgtbl_er; u32 ier; u32 ccid; + u32 derrmr; + u32 forcewake; bool waiting[I915_NUM_RINGS]; u32 pipestat[I915_MAX_PIPES]; u32 tail[I915_NUM_RINGS]; u32 head[I915_NUM_RINGS]; + u32 ctl[I915_NUM_RINGS]; u32 ipeir[I915_NUM_RINGS]; u32 ipehr[I915_NUM_RINGS]; u32 instdone[I915_NUM_RINGS]; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d6a994a0739..26d08bb5821 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, total = 0; for (i = 0; i < count; i++) { struct drm_i915_gem_relocation_entry __user *user_relocs; + u64 invalid_offset = (u64)-1; + int j; user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; @@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, goto err; } + /* As we do not update the known relocation offsets after + * relocating (due to the complexities in lock handling), + * we need to mark them as invalid now so that we force the + * relocation processing next time. Just in case the target + * object is evicted and then rebound into its old + * presumed_offset before the next execbuffer - if that + * happened we would make the mistake of assuming that the + * relocations were valid. + */ + for (j = 0; j < exec[i].relocation_count; j++) { + if (copy_to_user(&user_relocs[j].presumed_offset, + &invalid_offset, + sizeof(invalid_offset))) { + ret = -EFAULT; + mutex_lock(&dev->struct_mutex); + goto err; + } + } + reloc_offset[i] = total; total += exec[i].relocation_count; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2220dec3e5d..fe843389c7b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1157,6 +1157,7 @@ static void i915_record_ring_state(struct drm_device *dev, error->acthd[ring->id] = intel_ring_get_active_head(ring); error->head[ring->id] = I915_READ_HEAD(ring); error->tail[ring->id] = I915_READ_TAIL(ring); + error->ctl[ring->id] = I915_READ_CTL(ring); error->cpu_ring_head[ring->id] = ring->head; error->cpu_ring_tail[ring->id] = ring->tail; @@ -1251,6 +1252,16 @@ static void i915_capture_error_state(struct drm_device *dev) else error->ier = I915_READ(IER); + if (INTEL_INFO(dev)->gen >= 6) + error->derrmr = I915_READ(DERRMR); + + if (IS_VALLEYVIEW(dev)) + error->forcewake = I915_READ(FORCEWAKE_VLV); + else if (INTEL_INFO(dev)->gen >= 7) + error->forcewake = I915_READ(FORCEWAKE_MT); + else if (INTEL_INFO(dev)->gen == 6) + error->forcewake = I915_READ(FORCEWAKE); + for_each_pipe(pipe) error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 186ee5c85b5..b401788e179 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -512,6 +512,8 @@ #define GEN7_ERR_INT 0x44040 #define ERR_INT_MMIO_UNCLAIMED (1<<13) +#define DERRMR 0x44050 + /* GM45+ chicken bits -- debug workaround bits that may be required * for various sorts of correct behavior. The top 16 bits of each are * the enables for writing to the corresponding low bit. diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b63d55318a..fb3715b4b09 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2579,7 +2579,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect static void intel_dp_init_panel_power_sequencer(struct drm_device *dev, - struct intel_dp *intel_dp) + struct intel_dp *intel_dp, + struct edp_power_seq *out) { struct drm_i915_private *dev_priv = dev->dev_private; struct edp_power_seq cur, vbt, spec, final; @@ -2650,16 +2651,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, intel_dp->panel_power_cycle_delay = get_delay(t11_t12); #undef get_delay + DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", + intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, + intel_dp->panel_power_cycle_delay); + + DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", + intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); + + if (out) + *out = final; +} + +static void +intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, + struct intel_dp *intel_dp, + struct edp_power_seq *seq) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 pp_on, pp_off, pp_div; + /* And finally store the new values in the power sequencer. */ - pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | - (final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT); - pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | - (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT); + pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | + (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT); + pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | + (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); /* Compute the divisor for the pp clock, simply match the Bspec * formula. */ pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT; - pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000) + pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT); /* Haswell doesn't have any port selection bits for the panel @@ -2675,14 +2695,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, I915_WRITE(PCH_PP_OFF_DELAYS, pp_off); I915_WRITE(PCH_PP_DIVISOR, pp_div); - - DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", - intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, - intel_dp->panel_power_cycle_delay); - - DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", - intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); - DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", I915_READ(PCH_PP_ON_DELAYS), I915_READ(PCH_PP_OFF_DELAYS), @@ -2699,6 +2711,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_display_mode *fixed_mode = NULL; + struct edp_power_seq power_seq = { 0 }; enum port port = intel_dig_port->port; const char *name = NULL; int type; @@ -2771,7 +2784,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, } if (is_edp(intel_dp)) - intel_dp_init_panel_power_sequencer(dev, intel_dp); + intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); intel_dp_i2c_init(intel_dp, intel_connector, name); @@ -2798,6 +2811,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, return; } + /* We now know it's not a ghost, init power sequence regs. */ + intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, + &power_seq); + ironlake_edp_panel_vdd_on(intel_dp); edid = drm_get_edid(connector, &intel_dp->adapter); if (edid) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e83a1179417..3280cffe50f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4250,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); - POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ + /* something from same cacheline, but !FORCEWAKE_MT */ + POSTING_READ(ECOBUS); } static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) @@ -4267,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); - POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ + /* something from same cacheline, but !FORCEWAKE_MT */ + POSTING_READ(ECOBUS); if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), FORCEWAKE_ACK_TIMEOUT_MS)) @@ -4304,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); - /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ + /* something from same cacheline, but !FORCEWAKE */ + POSTING_READ(ECOBUS); gen6_gt_check_fifodbg(dev_priv); } static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); - /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ + /* something from same cacheline, but !FORCEWAKE_MT */ + POSTING_READ(ECOBUS); gen6_gt_check_fifodbg(dev_priv); } @@ -4351,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); + /* something from same cacheline, but !FORCEWAKE_VLV */ + POSTING_READ(FORCEWAKE_ACK_VLV); } static void vlv_force_wake_get(struct drm_i915_private *dev_priv) @@ -4371,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv) static void vlv_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); - /* The below doubles as a POSTING_READ */ + /* something from same cacheline, but !FORCEWAKE_VLV */ + POSTING_READ(FORCEWAKE_ACK_VLV); gen6_gt_check_fifodbg(dev_priv); } diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 061fa0a2890..4d0e60adbc6 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2401,6 +2401,12 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct evergreen_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 896f1cbc58a..59acabb45c9 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1409,6 +1409,12 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct evergreen_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 537e259b383..3cb9d608937 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1378,6 +1378,12 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct rv515_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 34e52304a52..a08f657329a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -324,7 +324,6 @@ struct radeon_bo { struct list_head list; /* Protected by tbo.reserved */ u32 placements[3]; - u32 busy_placements[3]; struct ttm_placement placement; struct ttm_buffer_object tbo; struct ttm_bo_kmap_obj kmap; @@ -654,6 +653,8 @@ struct radeon_ring { u32 ptr_reg_mask; u32 nop; u32 idx; + u64 last_semaphore_signal_addr; + u64 last_semaphore_wait_addr; }; /* diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dff6cf77f95..d9bf96ee299 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -69,9 +69,10 @@ * 2.26.0 - r600-eg: fix htile size computation * 2.27.0 - r600-SI: Add CS ioctl support for async DMA * 2.28.0 - r600-eg: Add MEM_WRITE packet support + * 2.29.0 - R500 FP16 color clear registers */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 28 +#define KMS_DRIVER_MINOR 29 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 883c95d8d90..d3aface2d12 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -84,6 +84,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) rbo->placement.fpfn = 0; rbo->placement.lpfn = 0; rbo->placement.placement = rbo->placements; + rbo->placement.busy_placement = rbo->placements; if (domain & RADEON_GEM_DOMAIN_VRAM) rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; @@ -104,14 +105,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) if (!c) rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; rbo->placement.num_placement = c; - - c = 0; - rbo->placement.busy_placement = rbo->busy_placements; - if (rbo->rdev->flags & RADEON_IS_AGP) { - rbo->busy_placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT; - } else { - rbo->busy_placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; - } rbo->placement.num_busy_placement = c; } @@ -357,6 +350,7 @@ int radeon_bo_list_validate(struct list_head *head) { struct radeon_bo_list *lobj; struct radeon_bo *bo; + u32 domain; int r; r = ttm_eu_reserve_buffers(head); @@ -366,9 +360,17 @@ int radeon_bo_list_validate(struct list_head *head) list_for_each_entry(lobj, head, tv.head) { bo = lobj->bo; if (!bo->pin_count) { + domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; + + retry: + radeon_ttm_placement_from_domain(bo, domain); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); if (unlikely(r)) { + if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) { + domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } return r; } } diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 141f2b6a9cf..2430d80b187 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -784,6 +784,8 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) } seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr); + seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr); + seq_printf(m, "last semaphore wait addr : 0x%016llx\n", ring->last_semaphore_wait_addr); seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); seq_printf(m, "%u dwords in ring\n", count); /* print 8 dw before current rptr as often it's the last executed diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 97f3ece81cd..8dcc20f53d7 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -95,6 +95,10 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, /* we assume caller has already allocated space on waiters ring */ radeon_semaphore_emit_wait(rdev, waiter, semaphore); + /* for debugging lockup only, used by sysfs debug files */ + rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr; + rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr; + return 0; } diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515 index 911a8fbd32b..78d5e99d759 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rv515 +++ b/drivers/gpu/drm/radeon/reg_srcs/rv515 @@ -324,6 +324,8 @@ rv515 0x6d40 0x46AC US_OUT_FMT_2 0x46B0 US_OUT_FMT_3 0x46B4 US_W_FMT +0x46C0 RB3D_COLOR_CLEAR_VALUE_AR +0x46C4 RB3D_COLOR_CLEAR_VALUE_GB 0x4BC0 FG_FOG_BLEND 0x4BC4 FG_FOG_FACTOR 0x4BC8 FG_FOG_COLOR_R diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 3240a3d64f3..ae8b48205a6 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2215,6 +2215,12 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) { struct evergreen_mc_save save; + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); + + if (RREG32(DMA_STATUS_REG) & DMA_IDLE) + reset_mask &= ~RADEON_RESET_DMA; + if (reset_mask == 0) return 0; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 33d20be87db..52b20b12c83 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -434,6 +434,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, bo->mem = tmp_mem; bdev->driver->move_notify(bo, mem); bo->mem = *mem; + *mem = tmp_mem; } goto out_err; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index d73d6e3e17b..44420fca7df 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -344,8 +344,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (ttm->state == tt_unpopulated) { ret = ttm->bdev->driver->ttm_tt_populate(ttm); - if (ret) + if (ret) { + /* if we fail here don't nuke the mm node + * as the bo still owns it */ + old_copy.mm_node = NULL; goto out1; + } } add = 0; @@ -371,8 +375,11 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, prot); } else ret = ttm_copy_io_page(new_iomap, old_iomap, page); - if (ret) + if (ret) { + /* failing here, means keep old copy as-is */ + old_copy.mm_node = NULL; goto out1; + } } mb(); out2: diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index f6c0011a033..dd289fd179c 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -403,7 +403,7 @@ struct dm_info_header { */ struct dm_info_msg { - struct dm_info_header header; + struct dm_header hdr; __u32 reserved; __u32 info_size; __u8 info[]; @@ -503,13 +503,17 @@ static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg) static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) { - switch (msg->header.type) { + struct dm_info_header *info_hdr; + + info_hdr = (struct dm_info_header *)msg->info; + + switch (info_hdr->type) { case INFO_TYPE_MAX_PAGE_CNT: pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n"); - pr_info("Data Size is %d\n", msg->header.data_size); + pr_info("Data Size is %d\n", info_hdr->data_size); break; default: - pr_info("Received Unknown type: %d\n", msg->header.type); + pr_info("Received Unknown type: %d\n", info_hdr->type); } } @@ -879,7 +883,7 @@ static int balloon_probe(struct hv_device *dev, balloon_onchannelcallback, dev); if (ret) - return ret; + goto probe_error0; dm_device.dev = dev; dm_device.state = DM_INITIALIZING; @@ -891,7 +895,7 @@ static int balloon_probe(struct hv_device *dev, kthread_run(dm_thread_func, &dm_device, "hv_balloon"); if (IS_ERR(dm_device.thread)) { ret = PTR_ERR(dm_device.thread); - goto probe_error0; + goto probe_error1; } hv_set_drvdata(dev, &dm_device); @@ -914,12 +918,12 @@ static int balloon_probe(struct hv_device *dev, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret) - goto probe_error1; + goto probe_error2; t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); if (t == 0) { ret = -ETIMEDOUT; - goto probe_error1; + goto probe_error2; } /* @@ -928,7 +932,7 @@ static int balloon_probe(struct hv_device *dev, */ if (dm_device.state == DM_INIT_ERROR) { ret = -ETIMEDOUT; - goto probe_error1; + goto probe_error2; } /* * Now submit our capabilities to the host. @@ -961,12 +965,12 @@ static int balloon_probe(struct hv_device *dev, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret) - goto probe_error1; + goto probe_error2; t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); if (t == 0) { ret = -ETIMEDOUT; - goto probe_error1; + goto probe_error2; } /* @@ -975,18 +979,20 @@ static int balloon_probe(struct hv_device *dev, */ if (dm_device.state == DM_INIT_ERROR) { ret = -ETIMEDOUT; - goto probe_error1; + goto probe_error2; } dm_device.state = DM_INITIALIZED; return 0; -probe_error1: +probe_error2: kthread_stop(dm_device.thread); -probe_error0: +probe_error1: vmbus_close(dev->channel); +probe_error0: + kfree(send_buffer); return ret; } @@ -999,6 +1005,7 @@ static int balloon_remove(struct hv_device *dev) vmbus_close(dev->channel); kthread_stop(dm->thread); + kfree(send_buffer); return 0; } diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index cbba7db9ad5..f5258c205de 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -34,6 +34,7 @@ #include <linux/io.h> #include <linux/pm_runtime.h> #include <linux/delay.h> +#include <linux/module.h> #include "i2c-designware-core.h" /* @@ -725,3 +726,6 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) return dw_readl(dev, DW_IC_COMP_PARAM_1); } EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); + +MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1b1a936eccc..d6abaf2cf2e 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -127,7 +127,7 @@ struct mxs_i2c_dev { struct device *dev; void __iomem *regs; struct completion cmd_complete; - u32 cmd_err; + int cmd_err; struct i2c_adapter adapter; const struct mxs_i2c_speed_config *speed; @@ -316,7 +316,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, if (msg->len == 0) return -EINVAL; - init_completion(&i2c->cmd_complete); + INIT_COMPLETION(i2c->cmd_complete); i2c->cmd_err = 0; ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); @@ -473,6 +473,8 @@ static int mxs_i2c_probe(struct platform_device *pdev) i2c->dev = dev; i2c->speed = &mxs_i2c_95kHz_config; + init_completion(&i2c->cmd_complete); + if (dev->of_node) { err = mxs_i2c_get_ofdata(i2c); if (err) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 20d41bfa7c1..4cc2f0528c8 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -803,7 +803,7 @@ static int errata_omap3_i462(struct omap_i2c_dev *dev) if (stat & OMAP_I2C_STAT_AL) { dev_err(dev->dev, "Arbitration lost\n"); dev->cmd_err |= OMAP_I2C_STAT_AL; - omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK); + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL); } return -EIO; @@ -963,7 +963,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) i2c_omap_errata_i207(dev, stat); omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); - break; + continue; } if (stat & OMAP_I2C_STAT_RRDY) { @@ -989,7 +989,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) break; omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR); - break; + continue; } if (stat & OMAP_I2C_STAT_XRDY) { diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 3f1818b8797..e03381aee34 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/i2c.h> +#include <linux/of_i2c.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> @@ -328,6 +329,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) adap->algo = &i2c_sirfsoc_algo; adap->algo_data = siic; + adap->dev.of_node = pdev->dev.of_node; adap->dev.parent = &pdev->dev; adap->nr = pdev->id; @@ -371,6 +373,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) clk_disable(clk); + of_i2c_register_devices(adap); + dev_info(&pdev->dev, " I2C adapter ready to operate\n"); return 0; diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 1e44d04d1b2..a43c0ce5e3d 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -167,7 +167,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) } mux->busses = devm_kzalloc(&pdev->dev, - sizeof(mux->busses) * mux->pdata->bus_count, + sizeof(*mux->busses) * mux->pdata->bus_count, GFP_KERNEL); if (!mux->busses) { dev_err(&pdev->dev, "Cannot allocate busses\n"); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4ba384f1ab5..2df9414a72f 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -448,8 +448,6 @@ static int intel_idle_probe(void) else on_each_cpu(__setup_broadcast_timer, (void *)true, 1); - register_cpu_notifier(&cpu_hotplug_notifier); - pr_debug(PREFIX "v" INTEL_IDLE_VERSION " model 0x%X\n", boot_cpu_data.x86_model); @@ -612,6 +610,7 @@ static int __init intel_idle_init(void) return retval; } } + register_cpu_notifier(&cpu_hotplug_notifier); return 0; } diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 81837b0710a..faf10ba1ed9 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -975,6 +975,38 @@ static void __init free_iommu_all(void) } /* + * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations) + * Workaround: + * BIOS should disable L2B micellaneous clock gating by setting + * L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b + */ +static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) +{ + u32 value; + + if ((boot_cpu_data.x86 != 0x15) || + (boot_cpu_data.x86_model < 0x10) || + (boot_cpu_data.x86_model > 0x1f)) + return; + + pci_write_config_dword(iommu->dev, 0xf0, 0x90); + pci_read_config_dword(iommu->dev, 0xf4, &value); + + if (value & BIT(2)) + return; + + /* Select NB indirect register 0x90 and enable writing */ + pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8)); + + pci_write_config_dword(iommu->dev, 0xf4, value | 0x4); + pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n", + dev_name(&iommu->dev->dev)); + + /* Clear the enable writing bit */ + pci_write_config_dword(iommu->dev, 0xf0, 0x90); +} + +/* * This function clues the initialization function for one IOMMU * together and also allocates the command buffer and programs the * hardware. It does NOT enable the IOMMU. This is done afterwards. @@ -1172,6 +1204,8 @@ static int iommu_init_pci(struct amd_iommu *iommu) iommu->stored_l2[i] = iommu_read_l2(iommu, i); } + amd_iommu_erratum_746_workaround(iommu); + return pci_enable_device(iommu->dev); } diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 68452b768da..03a0a01a405 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -248,6 +248,8 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, CAPIMSG_CONTROL(data)); l -= 12; + if (l <= 0) + return; dbgline = kmalloc(3 * l, GFP_ATOMIC); if (!dbgline) return; diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 3d8984edeff..9e58dbd8d8c 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -340,24 +340,22 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size) } /* - * validate_rebuild_devices + * validate_raid_redundancy * @rs * - * Determine if the devices specified for rebuild can result in a valid - * usable array that is capable of rebuilding the given devices. + * Determine if there are enough devices in the array that haven't + * failed (or are being rebuilt) to form a usable array. * * Returns: 0 on success, -EINVAL on failure. */ -static int validate_rebuild_devices(struct raid_set *rs) +static int validate_raid_redundancy(struct raid_set *rs) { unsigned i, rebuild_cnt = 0; unsigned rebuilds_per_group, copies, d; - if (!(rs->print_flags & DMPF_REBUILD)) - return 0; - for (i = 0; i < rs->md.raid_disks; i++) - if (!test_bit(In_sync, &rs->dev[i].rdev.flags)) + if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || + !rs->dev[i].rdev.sb_page) rebuild_cnt++; switch (rs->raid_type->level) { @@ -393,27 +391,24 @@ static int validate_rebuild_devices(struct raid_set *rs) * A A B B C * C D D E E */ - rebuilds_per_group = 0; for (i = 0; i < rs->md.raid_disks * copies; i++) { + if (!(i % copies)) + rebuilds_per_group = 0; d = i % rs->md.raid_disks; - if (!test_bit(In_sync, &rs->dev[d].rdev.flags) && + if ((!rs->dev[d].rdev.sb_page || + !test_bit(In_sync, &rs->dev[d].rdev.flags)) && (++rebuilds_per_group >= copies)) goto too_many; - if (!((i + 1) % copies)) - rebuilds_per_group = 0; } break; default: - DMERR("The rebuild parameter is not supported for %s", - rs->raid_type->name); - rs->ti->error = "Rebuild not supported for this RAID type"; - return -EINVAL; + if (rebuild_cnt) + return -EINVAL; } return 0; too_many: - rs->ti->error = "Too many rebuild devices specified"; return -EINVAL; } @@ -664,9 +659,6 @@ static int parse_raid_params(struct raid_set *rs, char **argv, } rs->md.dev_sectors = sectors_per_dev; - if (validate_rebuild_devices(rs)) - return -EINVAL; - /* Assume there are no metadata devices until the drives are parsed */ rs->md.persistent = 0; rs->md.external = 1; @@ -995,28 +987,10 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev) static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) { int ret; - unsigned redundancy = 0; struct raid_dev *dev; struct md_rdev *rdev, *tmp, *freshest; struct mddev *mddev = &rs->md; - switch (rs->raid_type->level) { - case 1: - redundancy = rs->md.raid_disks - 1; - break; - case 4: - case 5: - case 6: - redundancy = rs->raid_type->parity_devs; - break; - case 10: - redundancy = raid10_md_layout_to_copies(mddev->layout) - 1; - break; - default: - ti->error = "Unknown RAID type"; - return -EINVAL; - } - freshest = NULL; rdev_for_each_safe(rdev, tmp, mddev) { /* @@ -1045,44 +1019,43 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) break; default: dev = container_of(rdev, struct raid_dev, rdev); - if (redundancy--) { - if (dev->meta_dev) - dm_put_device(ti, dev->meta_dev); - - dev->meta_dev = NULL; - rdev->meta_bdev = NULL; + if (dev->meta_dev) + dm_put_device(ti, dev->meta_dev); - if (rdev->sb_page) - put_page(rdev->sb_page); + dev->meta_dev = NULL; + rdev->meta_bdev = NULL; - rdev->sb_page = NULL; + if (rdev->sb_page) + put_page(rdev->sb_page); - rdev->sb_loaded = 0; + rdev->sb_page = NULL; - /* - * We might be able to salvage the data device - * even though the meta device has failed. For - * now, we behave as though '- -' had been - * set for this device in the table. - */ - if (dev->data_dev) - dm_put_device(ti, dev->data_dev); + rdev->sb_loaded = 0; - dev->data_dev = NULL; - rdev->bdev = NULL; + /* + * We might be able to salvage the data device + * even though the meta device has failed. For + * now, we behave as though '- -' had been + * set for this device in the table. + */ + if (dev->data_dev) + dm_put_device(ti, dev->data_dev); - list_del(&rdev->same_set); + dev->data_dev = NULL; + rdev->bdev = NULL; - continue; - } - ti->error = "Failed to load superblock"; - return ret; + list_del(&rdev->same_set); } } if (!freshest) return 0; + if (validate_raid_redundancy(rs)) { + rs->ti->error = "Insufficient redundancy to activate array"; + return -EINVAL; + } + /* * Validation of the freshest device provides the source of * validation for the remaining devices. @@ -1432,7 +1405,7 @@ static void raid_resume(struct dm_target *ti) static struct target_type raid_target = { .name = "raid", - .version = {1, 4, 0}, + .version = {1, 4, 1}, .module = THIS_MODULE, .ctr = raid_ctr, .dtr = raid_dtr, diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 8a8d42fe263..d4e7567b367 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -556,7 +556,7 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, mutex_lock(&info->lock); format = __find_format(info, fh, fmt->which, info->res_type); - if (!format) + if (format) fmt->format = *format; else ret = -EINVAL; diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 1cf8293c0fb..4a980e029ca 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -23,8 +23,8 @@ #include <linux/slab.h> #include <linux/videodev2.h> #include <linux/of.h> +#include <linux/platform_data/imx-iram.h> -#include <mach/iram.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index e0d73a64218..8dac17511e6 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -35,9 +35,6 @@ #include <linux/vmalloc.h> #include <media/v4l2-dev.h> #include <media/v4l2-ioctl.h> -#include <plat/iommu.h> -#include <plat/iovmm.h> -#include <plat/omap-pm.h> #include "ispvideo.h" #include "isp.h" diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c index 4ab99f3a7b0..b4a68ecf0ca 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c @@ -593,7 +593,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) { struct media_entity *source, *sink; unsigned int flags = MEDIA_LNK_FL_ENABLED; - int i, ret; + int i, ret = 0; for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { struct fimc_lite *fimc = fmd->fimc_lite[i]; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 379f5743371..681bc6ba149 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -412,62 +412,48 @@ leave_handle_frame: } /* Error handling for interrupt */ -static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx, - unsigned int reason, unsigned int err) +static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, + struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) { - struct s5p_mfc_dev *dev; unsigned long flags; - /* If no context is available then all necessary - * processing has been done. */ - if (ctx == NULL) - return; - - dev = ctx->dev; mfc_err("Interrupt Error: %08x\n", err); - s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); - wake_up_dev(dev, reason, err); - /* Error recovery is dependent on the state of context */ - switch (ctx->state) { - case MFCINST_INIT: - /* This error had to happen while acquireing instance */ - case MFCINST_GOT_INST: - /* This error had to happen while parsing the header */ - case MFCINST_HEAD_PARSED: - /* This error had to happen while setting dst buffers */ - case MFCINST_RETURN_INST: - /* This error had to happen while releasing instance */ - clear_work_bit(ctx); - wake_up_ctx(ctx, reason, err); - if (test_and_clear_bit(0, &dev->hw_lock) == 0) - BUG(); - s5p_mfc_clock_off(); - ctx->state = MFCINST_ERROR; - break; - case MFCINST_FINISHING: - case MFCINST_FINISHED: - case MFCINST_RUNNING: - /* It is higly probable that an error occured - * while decoding a frame */ - clear_work_bit(ctx); - ctx->state = MFCINST_ERROR; - /* Mark all dst buffers as having an error */ - spin_lock_irqsave(&dev->irqlock, flags); - s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, - &ctx->vq_dst); - /* Mark all src buffers as having an error */ - s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, - &ctx->vq_src); - spin_unlock_irqrestore(&dev->irqlock, flags); - if (test_and_clear_bit(0, &dev->hw_lock) == 0) - BUG(); - s5p_mfc_clock_off(); - break; - default: - mfc_err("Encountered an error interrupt which had not been handled\n"); - break; + if (ctx != NULL) { + /* Error recovery is dependent on the state of context */ + switch (ctx->state) { + case MFCINST_RES_CHANGE_INIT: + case MFCINST_RES_CHANGE_FLUSH: + case MFCINST_RES_CHANGE_END: + case MFCINST_FINISHING: + case MFCINST_FINISHED: + case MFCINST_RUNNING: + /* It is higly probable that an error occured + * while decoding a frame */ + clear_work_bit(ctx); + ctx->state = MFCINST_ERROR; + /* Mark all dst buffers as having an error */ + spin_lock_irqsave(&dev->irqlock, flags); + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, + &ctx->dst_queue, &ctx->vq_dst); + /* Mark all src buffers as having an error */ + s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, + &ctx->src_queue, &ctx->vq_src); + spin_unlock_irqrestore(&dev->irqlock, flags); + wake_up_ctx(ctx, reason, err); + break; + default: + clear_work_bit(ctx); + ctx->state = MFCINST_ERROR; + wake_up_ctx(ctx, reason, err); + break; + } } + if (test_and_clear_bit(0, &dev->hw_lock) == 0) + BUG(); + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); + s5p_mfc_clock_off(); + wake_up_dev(dev, reason, err); return; } @@ -632,7 +618,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) dev->warn_start) s5p_mfc_handle_frame(ctx, reason, err); else - s5p_mfc_handle_error(ctx, reason, err); + s5p_mfc_handle_error(dev, ctx, reason, err); clear_bit(0, &dev->enter_suspend); break; diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c index 40ad6687ee5..3773a8a745d 100644 --- a/drivers/media/usb/gspca/kinect.c +++ b/drivers/media/usb/gspca/kinect.c @@ -381,6 +381,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x045e, 0x02ae)}, + {USB_DEVICE(0x045e, 0x02bf)}, {} }; diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c index 70511d5f953..1220340e760 100644 --- a/drivers/media/usb/gspca/sonixb.c +++ b/drivers/media/usb/gspca/sonixb.c @@ -496,7 +496,7 @@ static void reg_w(struct gspca_dev *gspca_dev, } } -static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) +static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf) { int retry = 60; @@ -504,16 +504,19 @@ static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) return; /* is i2c ready */ - reg_w(gspca_dev, 0x08, buffer, 8); + reg_w(gspca_dev, 0x08, buf, 8); while (retry--) { if (gspca_dev->usb_err < 0) return; - msleep(10); + msleep(1); reg_r(gspca_dev, 0x08); if (gspca_dev->usb_buf[0] & 0x04) { if (gspca_dev->usb_buf[0] & 0x08) { dev_err(gspca_dev->v4l2_dev.dev, - "i2c write error\n"); + "i2c error writing %02x %02x %02x %02x" + " %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); gspca_dev->usb_err = -EIO; } return; @@ -530,7 +533,7 @@ static void i2c_w_vector(struct gspca_dev *gspca_dev, for (;;) { if (gspca_dev->usb_err < 0) return; - reg_w(gspca_dev, 0x08, *buffer, 8); + i2c_w(gspca_dev, *buffer); len -= 8; if (len <= 0) break; diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c index 5a86047b846..36307a9028a 100644 --- a/drivers/media/usb/gspca/sonixj.c +++ b/drivers/media/usb/gspca/sonixj.c @@ -1550,6 +1550,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) 0, gspca_dev->usb_buf, 8, 500); + msleep(2); if (ret < 0) { pr_err("i2c_w1 err %d\n", ret); gspca_dev->usb_err = ret; diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 2bb7613ddeb..d5baab17a5e 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1431,8 +1431,10 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, int ret; ctrl = uvc_find_control(chain, xctrl->id, &mapping); - if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0) + if (ctrl == NULL) return -EINVAL; + if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) + return -EACCES; /* Clamp out of range values. */ switch (mapping->v4l2_type) { diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f2ee8c6b0d8..68d59b52749 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -657,8 +657,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ret = uvc_ctrl_get(chain, ctrl); if (ret < 0) { uvc_ctrl_rollback(handle); - ctrls->error_idx = ret == -ENOENT - ? ctrls->count : i; + ctrls->error_idx = i; return ret; } } @@ -686,8 +685,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ret = uvc_ctrl_set(chain, ctrl); if (ret < 0) { uvc_ctrl_rollback(handle); - ctrls->error_idx = (ret == -ENOENT && - cmd == VIDIOC_S_EXT_CTRLS) + ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS ? ctrls->count : i; return ret; } diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 9f81be23a81..e02c4797b1c 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -921,8 +921,10 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b * In videobuf we use our internal V4l2_planes struct for * single-planar buffers as well, for simplicity. */ - if (V4L2_TYPE_IS_OUTPUT(b->type)) + if (V4L2_TYPE_IS_OUTPUT(b->type)) { v4l2_planes[0].bytesused = b->bytesused; + v4l2_planes[0].data_offset = 0; + } if (b->memory == V4L2_MEMORY_USERPTR) { v4l2_planes[0].m.userptr = b->m.userptr; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4dfc4..ff553babf45 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -237,6 +237,7 @@ config MFD_TPS65910 depends on I2C=y && GPIOLIB select MFD_CORE select REGMAP_I2C + select REGMAP_IRQ select IRQ_DOMAIN help if you say yes here you get support for the TPS65910 series of @@ -292,6 +293,7 @@ config TWL4030_CORE bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" depends on I2C=y && GENERIC_HARDIRQS select IRQ_DOMAIN + select REGMAP_I2C help Say yes here if you have TWL4030 / TWL6030 family chip on your board. This core driver provides register access and IRQ handling diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index e1650badd10..4778bb124ef 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -19,6 +19,7 @@ #include <linux/mfd/core.h> #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ab8500.h> +#include <linux/mfd/abx500/ab8500-bm.h> #include <linux/mfd/dbx500-prcmu.h> #include <linux/regulator/ab8500.h> #include <linux/of.h> diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index bc8a3edb6bb..222c03a5ddc 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -239,7 +239,12 @@ static int arizona_runtime_resume(struct device *dev) return ret; } - regcache_sync(arizona->regmap); + ret = regcache_sync(arizona->regmap); + if (ret != 0) { + dev_err(arizona->dev, "Failed to restore register cache\n"); + regulator_disable(arizona->dcvdd); + return ret; + } return 0; } diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 74713bf5371..2bec5f0db3e 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -176,14 +176,7 @@ int arizona_irq_init(struct arizona *arizona) aod = &wm5102_aod; irq = &wm5102_irq; - switch (arizona->rev) { - case 0: - case 1: - ctrlif_error = false; - break; - default: - break; - } + ctrlif_error = false; break; #endif #ifdef CONFIG_MFD_WM5110 @@ -191,14 +184,7 @@ int arizona_irq_init(struct arizona *arizona) aod = &wm5110_aod; irq = &wm5110_irq; - switch (arizona->rev) { - case 0: - case 1: - ctrlif_error = false; - break; - default: - break; - } + ctrlif_error = false; break; #endif default: diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index ac74a4d1dae..885e5678035 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -27,6 +27,66 @@ #include <linux/of_device.h> #endif +/* I2C safe register check */ +static inline bool i2c_safe_reg(unsigned char reg) +{ + switch (reg) { + case DA9052_STATUS_A_REG: + case DA9052_STATUS_B_REG: + case DA9052_STATUS_C_REG: + case DA9052_STATUS_D_REG: + case DA9052_ADC_RES_L_REG: + case DA9052_ADC_RES_H_REG: + case DA9052_VDD_RES_REG: + case DA9052_ICHG_AV_REG: + case DA9052_TBAT_RES_REG: + case DA9052_ADCIN4_RES_REG: + case DA9052_ADCIN5_RES_REG: + case DA9052_ADCIN6_RES_REG: + case DA9052_TJUNC_RES_REG: + case DA9052_TSI_X_MSB_REG: + case DA9052_TSI_Y_MSB_REG: + case DA9052_TSI_LSB_REG: + case DA9052_TSI_Z_MSB_REG: + return true; + default: + return false; + } +} + +/* + * There is an issue with DA9052 and DA9053_AA/BA/BB PMIC where the PMIC + * gets lockup up or fails to respond following a system reset. + * This fix is to follow any read or write with a dummy read to a safe + * register. + */ +int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg) +{ + int val; + + switch (da9052->chip_id) { + case DA9052: + case DA9053_AA: + case DA9053_BA: + case DA9053_BB: + /* A dummy read to a safe register address. */ + if (!i2c_safe_reg(reg)) + return regmap_read(da9052->regmap, + DA9052_PARK_REGISTER, + &val); + break; + default: + /* + * For other chips parking of I2C register + * to a safe place is not required. + */ + break; + } + + return 0; +} +EXPORT_SYMBOL(da9052_i2c_fix); + static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) { int reg_val, ret; @@ -83,6 +143,7 @@ static int da9052_i2c_probe(struct i2c_client *client, da9052->dev = &client->dev; da9052->chip_irq = client->irq; + da9052->fix_io = da9052_i2c_fix; i2c_set_clientdata(client, da9052); diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index dc8826d8d69..268f45d4239 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -2524,7 +2524,7 @@ static bool read_mailbox_0(void) for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) { if (ev & prcmu_irq_bit[n]) - generic_handle_irq(IRQ_PRCMU_BASE + n); + generic_handle_irq(irq_find_mapping(db8500_irq_domain, n)); } r = true; break; @@ -2737,13 +2737,14 @@ static int db8500_irq_map(struct irq_domain *d, unsigned int virq, } static struct irq_domain_ops db8500_irq_ops = { - .map = db8500_irq_map, - .xlate = irq_domain_xlate_twocell, + .map = db8500_irq_map, + .xlate = irq_domain_xlate_twocell, }; static int db8500_irq_init(struct device_node *np) { - int irq_base = -1; + int irq_base = 0; + int i; /* In the device tree case, just take some IRQs */ if (!np) @@ -2758,6 +2759,10 @@ static int db8500_irq_init(struct device_node *np) return -ENOSYS; } + /* All wakeups will be used, so create mappings for all */ + for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) + irq_create_mapping(db8500_irq_domain, i); + return 0; } diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index f6878f8db57..4d73963cd8f 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -93,15 +93,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c, if (max77686 == NULL) return -ENOMEM; - max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config); - if (IS_ERR(max77686->regmap)) { - ret = PTR_ERR(max77686->regmap); - dev_err(max77686->dev, "Failed to allocate register map: %d\n", - ret); - kfree(max77686); - return ret; - } - i2c_set_clientdata(i2c, max77686); max77686->dev = &i2c->dev; max77686->i2c = i2c; @@ -111,6 +102,15 @@ static int max77686_i2c_probe(struct i2c_client *i2c, max77686->irq_gpio = pdata->irq_gpio; max77686->irq = i2c->irq; + max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config); + if (IS_ERR(max77686->regmap)) { + ret = PTR_ERR(max77686->regmap); + dev_err(max77686->dev, "Failed to allocate register map: %d\n", + ret); + kfree(max77686); + return ret; + } + if (regmap_read(max77686->regmap, MAX77686_REG_DEVICE_ID, &data) < 0) { dev_err(max77686->dev, diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index cc5155e2049..9e60fed5ff8 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -114,35 +114,37 @@ static int max77693_i2c_probe(struct i2c_client *i2c, u8 reg_data; int ret = 0; + if (!pdata) { + dev_err(&i2c->dev, "No platform data found.\n"); + return -EINVAL; + } + max77693 = devm_kzalloc(&i2c->dev, sizeof(struct max77693_dev), GFP_KERNEL); if (max77693 == NULL) return -ENOMEM; - max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config); - if (IS_ERR(max77693->regmap)) { - ret = PTR_ERR(max77693->regmap); - dev_err(max77693->dev,"failed to allocate register map: %d\n", - ret); - goto err_regmap; - } - i2c_set_clientdata(i2c, max77693); max77693->dev = &i2c->dev; max77693->i2c = i2c; max77693->irq = i2c->irq; max77693->type = id->driver_data; - if (!pdata) - goto err_regmap; + max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config); + if (IS_ERR(max77693->regmap)) { + ret = PTR_ERR(max77693->regmap); + dev_err(max77693->dev, "failed to allocate register map: %d\n", + ret); + return ret; + } max77693->wakeup = pdata->wakeup; - if (max77693_read_reg(max77693->regmap, - MAX77693_PMIC_REG_PMIC_ID2, ®_data) < 0) { + ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, + ®_data); + if (ret < 0) { dev_err(max77693->dev, "device not found on this channel\n"); - ret = -ENODEV; - goto err_regmap; + return ret; } else dev_info(max77693->dev, "device ID: 0x%x\n", reg_data); @@ -163,7 +165,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, ret = PTR_ERR(max77693->regmap_muic); dev_err(max77693->dev, "failed to allocate register map: %d\n", ret); - goto err_regmap; + goto err_regmap_muic; } ret = max77693_irq_init(max77693); @@ -184,9 +186,9 @@ static int max77693_i2c_probe(struct i2c_client *i2c, err_mfd: max77693_irq_exit(max77693); err_irq: +err_regmap_muic: i2c_unregister_device(max77693->muic); i2c_unregister_device(max77693->haptic); -err_regmap: return ret; } diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 64803f13bce..d11567307fb 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -208,6 +208,8 @@ static int pcf50633_probe(struct i2c_client *client, if (!pcf) return -ENOMEM; + i2c_set_clientdata(client, pcf); + pcf->dev = &client->dev; pcf->pdata = pdata; mutex_init(&pcf->lock); @@ -219,9 +221,6 @@ static int pcf50633_probe(struct i2c_client *client, return ret; } - i2c_set_clientdata(client, pcf); - pcf->dev = &client->dev; - version = pcf50633_reg_read(pcf, 0); variant = pcf50633_reg_read(pcf, 1); if (version < 0 || variant < 0) { diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 89f046ca9e4..3d3b4addf81 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -112,6 +112,21 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) BPP_LDO_POWB, BPP_LDO_SUSPEND); } +static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + u8 mask, val; + + mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK; + if (voltage == OUTPUT_3V3) + val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3; + else if (voltage == OUTPUT_1V8) + val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8; + else + return -EINVAL; + + return rtsx_pci_write_register(pcr, LDO_CTL, mask, val); +} + static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) { unsigned int card_exist; @@ -163,6 +178,18 @@ static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) return card_exist; } +static int rtl8411_conv_clk_and_div_n(int input, int dir) +{ + int output; + + if (dir == CLK_TO_DIV_N) + output = input * 4 / 5 - 2; + else + output = (input + 2) * 5 / 4; + + return output; +} + static const struct pcr_ops rtl8411_pcr_ops = { .extra_init_hw = rtl8411_extra_init_hw, .optimize_phy = NULL, @@ -172,7 +199,9 @@ static const struct pcr_ops rtl8411_pcr_ops = { .disable_auto_blink = rtl8411_disable_auto_blink, .card_power_on = rtl8411_card_power_on, .card_power_off = rtl8411_card_power_off, + .switch_output_voltage = rtl8411_switch_output_voltage, .cd_deglitch = rtl8411_cd_deglitch, + .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index 283a4f14808..98fe0f39463 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c @@ -144,6 +144,25 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) return rtsx_pci_send_cmd(pcr, 100); } +static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + int err; + + if (voltage == OUTPUT_3V3) { + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); + if (err < 0) + return err; + } else if (voltage == OUTPUT_1V8) { + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); + if (err < 0) + return err; + } else { + return -EINVAL; + } + + return 0; +} + static const struct pcr_ops rts5209_pcr_ops = { .extra_init_hw = rts5209_extra_init_hw, .optimize_phy = rts5209_optimize_phy, @@ -153,7 +172,9 @@ static const struct pcr_ops rts5209_pcr_ops = { .disable_auto_blink = rts5209_disable_auto_blink, .card_power_on = rts5209_card_power_on, .card_power_off = rts5209_card_power_off, + .switch_output_voltage = rts5209_switch_output_voltage, .cd_deglitch = NULL, + .conv_clk_and_div_n = NULL, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index b9dbab266fd..29d889cbb9c 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c @@ -114,6 +114,25 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card) return rtsx_pci_send_cmd(pcr, 100); } +static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + int err; + + if (voltage == OUTPUT_3V3) { + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); + if (err < 0) + return err; + } else if (voltage == OUTPUT_1V8) { + err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); + if (err < 0) + return err; + } else { + return -EINVAL; + } + + return 0; +} + static const struct pcr_ops rts5229_pcr_ops = { .extra_init_hw = rts5229_extra_init_hw, .optimize_phy = rts5229_optimize_phy, @@ -123,7 +142,9 @@ static const struct pcr_ops rts5229_pcr_ops = { .disable_auto_blink = rts5229_disable_auto_blink, .card_power_on = rts5229_card_power_on, .card_power_off = rts5229_card_power_off, + .switch_output_voltage = rts5229_switch_output_voltage, .cd_deglitch = NULL, + .conv_clk_and_div_n = NULL, }; /* SD Pull Control Enable: diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 7a7b0bda461..9fc57009e22 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -630,7 +630,10 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, if (clk == pcr->cur_clock) return 0; - N = (u8)(clk - 2); + if (pcr->ops->conv_clk_and_div_n) + N = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N); + else + N = (u8)(clk - 2); if ((clk <= 2) || (N > max_N)) return -EINVAL; @@ -641,7 +644,14 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, /* Make sure that the SSC clock div_n is equal or greater than min_N */ div = CLK_DIV_1; while ((N < min_N) && (div < max_div)) { - N = (N + 2) * 2 - 2; + if (pcr->ops->conv_clk_and_div_n) { + int dbl_clk = pcr->ops->conv_clk_and_div_n(N, + DIV_N_TO_CLK) * 2; + N = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk, + CLK_TO_DIV_N); + } else { + N = (N + 2) * 2 - 2; + } div++; } dev_dbg(&(pcr->pci->dev), "N = %d, div = %d\n", N, div); @@ -703,6 +713,15 @@ int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card) } EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); +int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) +{ + if (pcr->ops->switch_output_voltage) + return pcr->ops->switch_output_voltage(pcr, voltage); + + return 0; +} +EXPORT_SYMBOL_GPL(rtsx_pci_switch_output_voltage); + unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr) { unsigned int val; @@ -767,10 +786,10 @@ static void rtsx_pci_card_detect(struct work_struct *work) spin_unlock_irqrestore(&pcr->lock, flags); - if (card_detect & SD_EXIST) + if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event) pcr->slots[RTSX_SD_CARD].card_event( pcr->slots[RTSX_SD_CARD].p_dev); - if (card_detect & MS_EXIST) + if ((card_detect & MS_EXIST) && pcr->slots[RTSX_MS_CARD].card_event) pcr->slots[RTSX_MS_CARD].card_event( pcr->slots[RTSX_MS_CARD].p_dev); } diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index a06d66b929b..ecc092c7f74 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -219,25 +219,18 @@ static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq) } static struct irq_domain_ops tc3589x_irq_ops = { - .map = tc3589x_irq_map, + .map = tc3589x_irq_map, .unmap = tc3589x_irq_unmap, - .xlate = irq_domain_xlate_twocell, + .xlate = irq_domain_xlate_twocell, }; static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np) { int base = tc3589x->irq_base; - if (base) { - tc3589x->domain = irq_domain_add_legacy( - NULL, TC3589x_NR_INTERNAL_IRQS, base, - 0, &tc3589x_irq_ops, tc3589x); - } - else { - tc3589x->domain = irq_domain_add_linear( - np, TC3589x_NR_INTERNAL_IRQS, - &tc3589x_irq_ops, tc3589x); - } + tc3589x->domain = irq_domain_add_simple( + np, TC3589x_NR_INTERNAL_IRQS, base, + &tc3589x_irq_ops, tc3589x); if (!tc3589x->domain) { dev_err(tc3589x->dev, "Failed to create irqdomain\n"); diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 4dae241e501..dd362c1078e 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -159,7 +159,7 @@ out: static int twl4030_write_script(u8 address, struct twl4030_ins *script, int len) { - int err; + int err = -EINVAL; for (; len; len--, address++, script++) { if (len == 1) { diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c index fae15d88075..3c1723aa622 100644 --- a/drivers/mfd/vexpress-config.c +++ b/drivers/mfd/vexpress-config.c @@ -67,6 +67,7 @@ struct vexpress_config_bridge *vexpress_config_bridge_register( return bridge; } +EXPORT_SYMBOL(vexpress_config_bridge_register); void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge) { @@ -83,6 +84,7 @@ void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge) while (!list_empty(&__bridge.transactions)) cpu_relax(); } +EXPORT_SYMBOL(vexpress_config_bridge_unregister); struct vexpress_config_func { @@ -142,6 +144,7 @@ struct vexpress_config_func *__vexpress_config_func_get(struct device *dev, return func; } +EXPORT_SYMBOL(__vexpress_config_func_get); void vexpress_config_func_put(struct vexpress_config_func *func) { @@ -149,7 +152,7 @@ void vexpress_config_func_put(struct vexpress_config_func *func) of_node_put(func->bridge->node); kfree(func); } - +EXPORT_SYMBOL(vexpress_config_func_put); struct vexpress_config_trans { struct vexpress_config_func *func; @@ -229,6 +232,7 @@ void vexpress_config_complete(struct vexpress_config_bridge *bridge, complete(&trans->completion); } +EXPORT_SYMBOL(vexpress_config_complete); int vexpress_config_wait(struct vexpress_config_trans *trans) { @@ -236,7 +240,7 @@ int vexpress_config_wait(struct vexpress_config_trans *trans) return trans->status; } - +EXPORT_SYMBOL(vexpress_config_wait); int vexpress_config_read(struct vexpress_config_func *func, int offset, u32 *data) diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index e5d8f63b252..77048b18439 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -313,19 +313,11 @@ static void vexpress_sysreg_config_complete(unsigned long data) } -void __init vexpress_sysreg_early_init(void __iomem *base) +void __init vexpress_sysreg_setup(struct device_node *node) { - struct device_node *node = of_find_compatible_node(NULL, NULL, - "arm,vexpress-sysreg"); - - if (node) - base = of_iomap(node, 0); - - if (WARN_ON(!base)) + if (WARN_ON(!vexpress_sysreg_base)) return; - vexpress_sysreg_base = base; - if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) vexpress_master_site = VEXPRESS_SITE_DB2; else @@ -336,9 +328,23 @@ void __init vexpress_sysreg_early_init(void __iomem *base) WARN_ON(!vexpress_sysreg_config_bridge); } +void __init vexpress_sysreg_early_init(void __iomem *base) +{ + vexpress_sysreg_base = base; + vexpress_sysreg_setup(NULL); +} + void __init vexpress_sysreg_of_early_init(void) { - vexpress_sysreg_early_init(NULL); + struct device_node *node = of_find_compatible_node(NULL, NULL, + "arm,vexpress-sysreg"); + + if (node) { + vexpress_sysreg_base = of_iomap(node, 0); + vexpress_sysreg_setup(node); + } else { + pr_info("vexpress-sysreg: No Device Tree node found."); + } } @@ -426,9 +432,11 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) return -EBUSY; } - if (!vexpress_sysreg_base) + if (!vexpress_sysreg_base) { vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + vexpress_sysreg_setup(pdev->dev.of_node); + } if (!vexpress_sysreg_base) { dev_err(&pdev->dev, "Failed to obtain base address!\n"); diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index 088872ab633..1133a64c2dc 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c @@ -1882,7 +1882,7 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg) } } -#define WM5102_MAX_REGISTER 0x1a8fff +#define WM5102_MAX_REGISTER 0x1a9800 const struct regmap_config wm5102_spi_regmap = { .reg_bits = 32, diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 158da5a81a6..3c09cbb70b1 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/of.h> +#include <linux/pinctrl/consumer.h> /* Serialize access to ssc_list and user count */ static DEFINE_SPINLOCK(user_lock); @@ -131,6 +132,13 @@ static int ssc_probe(struct platform_device *pdev) struct resource *regs; struct ssc_device *ssc; const struct atmel_ssc_platform_data *plat_dat; + struct pinctrl *pinctrl; + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + dev_err(&pdev->dev, "Failed to request pinctrl\n"); + return PTR_ERR(pinctrl); + } ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); if (!ssc) { diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 9ff942a346e..83269f1d16e 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -468,6 +468,11 @@ long st_kim_start(void *kim_data) if (pdata->chip_enable) pdata->chip_enable(kim_gdata); + /* Configure BT nShutdown to HIGH state */ + gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); + mdelay(5); /* FIXME: a proper toggle */ + gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); + mdelay(100); /* re-initialize the completion */ INIT_COMPLETION(kim_gdata->ldisc_installed); /* send notification to UIM */ @@ -509,7 +514,8 @@ long st_kim_start(void *kim_data) * (b) upon failure to either install ldisc or download firmware. * The function is responsible to (a) notify UIM about un-installation, * (b) flush UART if the ldisc was installed. - * (c) invoke platform's chip disabling routine. + * (c) reset BT_EN - pull down nshutdown at the end. + * (d) invoke platform's chip disabling routine. */ long st_kim_stop(void *kim_data) { @@ -541,6 +547,13 @@ long st_kim_stop(void *kim_data) err = -ETIMEDOUT; } + /* By default configure BT nShutdown to LOW state */ + gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); + mdelay(1); + gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); + mdelay(1); + gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); + /* platform specific disable */ if (pdata->chip_disable) pdata->chip_disable(kim_gdata); @@ -733,6 +746,20 @@ static int kim_probe(struct platform_device *pdev) /* refer to itself */ kim_gdata->core_data->kim_data = kim_gdata; + /* Claim the chip enable nShutdown gpio from the system */ + kim_gdata->nshutdown = pdata->nshutdown_gpio; + err = gpio_request(kim_gdata->nshutdown, "kim"); + if (unlikely(err)) { + pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); + return err; + } + + /* Configure nShutdown GPIO as output=0 */ + err = gpio_direction_output(kim_gdata->nshutdown, 0); + if (unlikely(err)) { + pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); + return err; + } /* get reference of pdev for request_firmware */ kim_gdata->kim_pdev = pdev; @@ -779,10 +806,18 @@ err_core_init: static int kim_remove(struct platform_device *pdev) { + /* free the GPIOs requested */ + struct ti_st_plat_data *pdata = pdev->dev.platform_data; struct kim_data_s *kim_gdata; kim_gdata = dev_get_drvdata(&pdev->dev); + /* Free the Bluetooth/FM/GPIO + * nShutdown gpio from the system + */ + gpio_free(pdata->nshutdown_gpio); + pr_info("nshutdown GPIO Freed"); + debugfs_remove_recursive(kim_debugfs_dir); sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); pr_info("sysfs entries removed"); diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index de4c20b3936..f8dd3610294 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -50,8 +50,6 @@ struct mvsd_host { struct timer_list timer; struct mmc_host *mmc; struct device *dev; - struct resource *res; - int irq; struct clk *clk; int gpio_card_detect; int gpio_write_protect; @@ -718,10 +716,6 @@ static int __init mvsd_probe(struct platform_device *pdev) if (!r || irq < 0 || !mvsd_data) return -ENXIO; - r = request_mem_region(r->start, SZ_1K, DRIVER_NAME); - if (!r) - return -EBUSY; - mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); if (!mmc) { ret = -ENOMEM; @@ -731,8 +725,8 @@ static int __init mvsd_probe(struct platform_device *pdev) host = mmc_priv(mmc); host->mmc = mmc; host->dev = &pdev->dev; - host->res = r; host->base_clock = mvsd_data->clock / 2; + host->clk = ERR_PTR(-EINVAL); mmc->ops = &mvsd_ops; @@ -752,7 +746,7 @@ static int __init mvsd_probe(struct platform_device *pdev) spin_lock_init(&host->lock); - host->base = ioremap(r->start, SZ_4K); + host->base = devm_request_and_ioremap(&pdev->dev, r); if (!host->base) { ret = -ENOMEM; goto out; @@ -765,44 +759,45 @@ static int __init mvsd_probe(struct platform_device *pdev) mvsd_power_down(host); - ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host); + ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); if (ret) { pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); goto out; - } else - host->irq = irq; + } /* Not all platforms can gate the clock, so it is not an error if the clock does not exists. */ - host->clk = clk_get(&pdev->dev, NULL); - if (!IS_ERR(host->clk)) { + host->clk = devm_clk_get(&pdev->dev, NULL); + if (!IS_ERR(host->clk)) clk_prepare_enable(host->clk); - } if (mvsd_data->gpio_card_detect) { - ret = gpio_request(mvsd_data->gpio_card_detect, - DRIVER_NAME " cd"); + ret = devm_gpio_request_one(&pdev->dev, + mvsd_data->gpio_card_detect, + GPIOF_IN, DRIVER_NAME " cd"); if (ret == 0) { - gpio_direction_input(mvsd_data->gpio_card_detect); irq = gpio_to_irq(mvsd_data->gpio_card_detect); - ret = request_irq(irq, mvsd_card_detect_irq, - IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING, - DRIVER_NAME " cd", host); + ret = devm_request_irq(&pdev->dev, irq, + mvsd_card_detect_irq, + IRQ_TYPE_EDGE_RISING | + IRQ_TYPE_EDGE_FALLING, + DRIVER_NAME " cd", host); if (ret == 0) host->gpio_card_detect = mvsd_data->gpio_card_detect; else - gpio_free(mvsd_data->gpio_card_detect); + devm_gpio_free(&pdev->dev, + mvsd_data->gpio_card_detect); } } if (!host->gpio_card_detect) mmc->caps |= MMC_CAP_NEEDS_POLL; if (mvsd_data->gpio_write_protect) { - ret = gpio_request(mvsd_data->gpio_write_protect, - DRIVER_NAME " wp"); + ret = devm_gpio_request_one(&pdev->dev, + mvsd_data->gpio_write_protect, + GPIOF_IN, DRIVER_NAME " wp"); if (ret == 0) { - gpio_direction_input(mvsd_data->gpio_write_protect); host->gpio_write_protect = mvsd_data->gpio_write_protect; } @@ -824,26 +819,11 @@ static int __init mvsd_probe(struct platform_device *pdev) return 0; out: - if (host) { - if (host->irq) - free_irq(host->irq, host); - if (host->gpio_card_detect) { - free_irq(gpio_to_irq(host->gpio_card_detect), host); - gpio_free(host->gpio_card_detect); - } - if (host->gpio_write_protect) - gpio_free(host->gpio_write_protect); - if (host->base) - iounmap(host->base); - } - if (r) - release_resource(r); - if (mmc) - if (!IS_ERR_OR_NULL(host->clk)) { + if (mmc) { + if (!IS_ERR(host->clk)) clk_disable_unprepare(host->clk); - clk_put(host->clk); - } mmc_free_host(mmc); + } return ret; } @@ -852,28 +832,16 @@ static int __exit mvsd_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); - if (mmc) { - struct mvsd_host *host = mmc_priv(mmc); + struct mvsd_host *host = mmc_priv(mmc); - if (host->gpio_card_detect) { - free_irq(gpio_to_irq(host->gpio_card_detect), host); - gpio_free(host->gpio_card_detect); - } - mmc_remove_host(mmc); - free_irq(host->irq, host); - if (host->gpio_write_protect) - gpio_free(host->gpio_write_protect); - del_timer_sync(&host->timer); - mvsd_power_down(host); - iounmap(host->base); - release_resource(host->res); + mmc_remove_host(mmc); + del_timer_sync(&host->timer); + mvsd_power_down(host); + + if (!IS_ERR(host->clk)) + clk_disable_unprepare(host->clk); + mmc_free_host(mmc); - if (!IS_ERR(host->clk)) { - clk_disable_unprepare(host->clk); - clk_put(host->clk); - } - mmc_free_host(mmc); - } platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 571915dfb21..f74b5adca64 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -1060,26 +1060,6 @@ static int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host) return 0; } -static int sd_change_bank_voltage(struct realtek_pci_sdmmc *host, u8 voltage) -{ - struct rtsx_pcr *pcr = host->pcr; - int err; - - if (voltage == SD_IO_3V3) { - err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); - if (err < 0) - return err; - } else if (voltage == SD_IO_1V8) { - err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); - if (err < 0) - return err; - } else { - return -EINVAL; - } - - return 0; -} - static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) { struct realtek_pci_sdmmc *host = mmc_priv(mmc); @@ -1098,11 +1078,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) rtsx_pci_start_run(pcr); if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) - voltage = SD_IO_3V3; + voltage = OUTPUT_3V3; else - voltage = SD_IO_1V8; + voltage = OUTPUT_1V8; - if (voltage == SD_IO_1V8) { + if (voltage == OUTPUT_1V8) { err = rtsx_pci_write_register(pcr, SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); if (err < 0) @@ -1113,11 +1093,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) goto out; } - err = sd_change_bank_voltage(host, voltage); + err = rtsx_pci_switch_output_voltage(pcr, voltage); if (err < 0) goto out; - if (voltage == SD_IO_1V8) { + if (voltage == OUTPUT_1V8) { err = sd_wait_voltage_stable_2(host); if (err < 0) goto out; diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 57eb1e77865..285f763e3cd 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -964,7 +964,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_ACK_ERROR: netdev_dbg(dev, "ack error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= (CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL); break; case LEC_BIT1_ERROR: @@ -977,7 +977,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_CRC_ERROR: netdev_dbg(dev, "CRC error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL); break; default: diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 7d1748575b1..5c314a96197 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -560,7 +560,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) stats->rx_errors++; break; case PCH_CRC_ERR: - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; priv->can.can_stats.bus_error++; stats->rx_errors++; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index f52a9755fb3..f21fc37ec57 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -748,12 +748,12 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, } if (err_status & HECC_CANES_CRCE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; } if (err_status & HECC_CANES_ACKE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); - cf->data[2] |= CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL; } } diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c index 66df9363808..ffd8de28a76 100644 --- a/drivers/net/ethernet/3com/3c574_cs.c +++ b/drivers/net/ethernet/3com/3c574_cs.c @@ -432,7 +432,7 @@ static int tc574_config(struct pcmcia_device *link) netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n", cardname, dev->base_addr, dev->irq, dev->dev_addr); netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n", - 8 << config & Ram_size, + 8 << (config & Ram_size), ram_split[(config & Ram_split) >> Ram_split_shift], config & Autoselect ? "autoselect " : ""); diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index a345e2454b8..a170065b597 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -548,6 +548,10 @@ static int desc_get_rx_status(struct xgmac_priv *priv, struct xgmac_dma_desc *p) return -1; } + /* All frames should fit into a single buffer */ + if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG)) + return -1; + /* Check if packet has checksum already */ if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) && !(ext_status & RXDESC_IP_PAYLOAD_MASK)) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 424f8ed67d3..c6c05bfef0e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -1994,9 +1994,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) { const struct port_info *pi = netdev_priv(dev); struct adapter *adap = pi->adapter; - - return set_rxq_intr_params(adap, &adap->sge.ethrxq[pi->first_qset].rspq, - c->rx_coalesce_usecs, c->rx_max_coalesced_frames); + struct sge_rspq *q; + int i; + int r = 0; + + for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) { + q = &adap->sge.ethrxq[i].rspq; + r = set_rxq_intr_params(adap, q, c->rx_coalesce_usecs, + c->rx_max_coalesced_frames); + if (r) { + dev_err(&dev->dev, "failed to set coalesce %d\n", r); + break; + } + } + return r; } static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 3c5ffd2f5c6..30724d81111 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -640,10 +640,15 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ring->tx_csum++; } - /* Copy dst mac address to wqe */ - ethh = (struct ethhdr *)skb->data; - tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); - tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) { + /* Copy dst mac address to wqe. This allows loopback in eSwitch, + * so that VFs and PF can communicate with each other + */ + ethh = (struct ethhdr *)skb->data; + tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); + tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + } + /* Handle LSO (TSO) packets */ if (lso_header_size) { /* Mark opcode as LSO */ diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 983fd3d62bc..f1ee52d1046 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1790,15 +1790,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) int i; if (msi_x) { - /* In multifunction mode each function gets 2 msi-X vectors - * one for data path completions anf the other for asynch events - * or command completions */ - if (mlx4_is_mfunc(dev)) { - nreq = 2; - } else { - nreq = min_t(int, dev->caps.num_eqs - - dev->caps.reserved_eqs, nreq); - } + nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, + nreq); entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); if (!entries) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index bc165f4d0f6..695667d471a 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) buffrag->length, PCI_DMA_TODEVICE); buffrag->dma = 0ULL; } - for (j = 0; j < cmd_buf->frag_count; j++) { + for (j = 1; j < cmd_buf->frag_count; j++) { buffrag++; if (buffrag->dma) { pci_unmap_page(adapter->pdev, buffrag->dma, diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 8e40ea09d7f..7a849fc55a6 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1962,10 +1962,12 @@ unwind: while (--i >= 0) { nf = &pbuf->frag_array[i+1]; pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); + nf->dma = 0ULL; } nf = &pbuf->frag_array[0]; pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + nf->dma = 0ULL; out_err: return -ENOMEM; diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 97fdbb1d641..4208f28d5d1 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1825,8 +1825,6 @@ static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) if (opts2 & RxVlanTag) __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); - - desc->opts2 = 0; } static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) @@ -6061,8 +6059,6 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget !(status & (RxRWT | RxFOVF)) && (dev->features & NETIF_F_RXALL)) goto process_pkt; - - rtl8169_mark_to_asic(desc, rx_buf_sz); } else { struct sk_buff *skb; dma_addr_t addr; @@ -6083,16 +6079,14 @@ process_pkt: if (unlikely(rtl8169_fragmented_frame(status))) { dev->stats.rx_dropped++; dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, rx_buf_sz); - continue; + goto release_descriptor; } skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], tp, pkt_size, addr); - rtl8169_mark_to_asic(desc, rx_buf_sz); if (!skb) { dev->stats.rx_dropped++; - continue; + goto release_descriptor; } rtl8169_rx_csum(skb, status); @@ -6108,13 +6102,10 @@ process_pkt: tp->rx_stats.bytes += pkt_size; u64_stats_update_end(&tp->rx_stats.syncp); } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } +release_descriptor: + desc->opts2 = 0; + wmb(); + rtl8169_mark_to_asic(desc, rx_buf_sz); } count = cur_rx - tp->cur_rx; diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 5fd6f467432..e6fe0d80d61 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -84,7 +84,7 @@ struct hv_netvsc_packet { }; struct netvsc_device_info { - unsigned char mac_adr[6]; + unsigned char mac_adr[ETH_ALEN]; bool link_state; /* 0 - link up, 1 - link down */ int ring_size; }; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index a9975c7e646..d5202a4b087 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -349,7 +349,7 @@ static int netvsc_set_mac_addr(struct net_device *ndev, void *p) struct net_device_context *ndevctx = netdev_priv(ndev); struct hv_device *hdev = ndevctx->device_ctx; struct sockaddr *addr = p; - char save_adr[14]; + char save_adr[ETH_ALEN]; unsigned char save_aatype; int err; diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 81f8f9e31db..fcbf680c3e6 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -77,6 +77,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, skb_orphan(skb); + /* Before queueing this packet to netif_rx(), + * make sure dst is refcounted. + */ + skb_dst_force(skb); + skb->protocol = eth_type_trans(skb, dev); /* it's OK to use per_cpu_ptr() because BHs are off */ diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 1047e587580..7b44ebd7770 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -828,7 +828,10 @@ static int macvlan_changelink(struct net_device *dev, static size_t macvlan_get_size(const struct net_device *dev) { - return nla_total_size(4); + return (0 + + nla_total_size(4) /* IFLA_MACVLAN_MODE */ + + nla_total_size(2) /* IFLA_MACVLAN_FLAGS */ + ); } static int macvlan_fill_info(struct sk_buff *skb, diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index d5199cb4cae..b5ddd5077a8 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c @@ -36,8 +36,9 @@ MODULE_LICENSE("GPL"); /* IP101A/G - IP1001 */ #define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */ +#define IP1001_RXPHASE_SEL (1<<0) /* Add delay on RX_CLK */ +#define IP1001_TXPHASE_SEL (1<<1) /* Add delay on TX_CLK */ #define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */ -#define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */ #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ #define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */ #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ @@ -138,19 +139,24 @@ static int ip1001_config_init(struct phy_device *phydev) if (c < 0) return c; - /* INTR pin used: speed/link/duplex will cause an interrupt */ - c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT); - if (c < 0) - return c; + if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { - /* Additional delay (2ns) used to adjust RX clock phase - * at RGMII interface */ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); if (c < 0) return c; - c |= IP1001_PHASE_SEL_MASK; + c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); + + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); + else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) + c |= IP1001_RXPHASE_SEL; + else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) + c |= IP1001_TXPHASE_SEL; + c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); if (c < 0) return c; @@ -167,6 +173,11 @@ static int ip101a_g_config_init(struct phy_device *phydev) if (c < 0) return c; + /* INTR pin used: speed/link/duplex will cause an interrupt */ + c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT); + if (c < 0) + return c; + /* Enable Auto Power Saving mode */ c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); c |= IP101A_G_APS_ON; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 5d2a3f21588..22dec9c7ef0 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -353,15 +353,6 @@ static int m88e1111_config_init(struct phy_device *phydev) int err; int temp; - /* Enable Fiber/Copper auto selection */ - temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); - temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO; - phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); - - temp = phy_read(phydev, MII_BMCR); - temp |= BMCR_RESET; - phy_write(phydev, MII_BMCR, temp); - if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 293ce8dfc9e..8d208dd9296 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -109,11 +109,11 @@ struct tap_filter { unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; }; -/* 1024 is probably a high enough limit: modern hypervisors seem to support on - * the order of 100-200 CPUs so this leaves us some breathing space if we want - * to match a queue per guest CPU. - */ -#define MAX_TAP_QUEUES 1024 +/* DEFAULT_MAX_NUM_RSS_QUEUES were choosed to let the rx/tx queues allocated for + * the netdevice to be fit in one page. So we can make sure the success of + * memory allocation. TODO: increase the limit. */ +#define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES +#define MAX_TAP_FLOWS 4096 #define TUN_FLOW_EXPIRE (3 * HZ) @@ -186,6 +186,7 @@ struct tun_struct { unsigned int numdisabled; struct list_head disabled; void *security; + u32 flow_count; }; static inline u32 tun_hashfn(u32 rxhash) @@ -219,6 +220,7 @@ static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun, e->queue_index = queue_index; e->tun = tun; hlist_add_head_rcu(&e->hash_link, head); + ++tun->flow_count; } return e; } @@ -229,6 +231,7 @@ static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e) e->rxhash, e->queue_index); hlist_del_rcu(&e->hash_link); kfree_rcu(e, rcu); + --tun->flow_count; } static void tun_flow_flush(struct tun_struct *tun) @@ -318,7 +321,8 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash, e->updated = jiffies; } else { spin_lock_bh(&tun->lock); - if (!tun_flow_find(head, rxhash)) + if (!tun_flow_find(head, rxhash) && + tun->flow_count < MAX_TAP_FLOWS) tun_flow_create(tun, head, rxhash, queue_index); if (!timer_pending(&tun->flow_gc_timer)) @@ -1587,6 +1591,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) else { char *name; unsigned long flags = 0; + int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? + MAX_TAP_QUEUES : 1; if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) return -EPERM; @@ -1610,8 +1616,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) name = ifr->ifr_name; dev = alloc_netdev_mqs(sizeof(struct tun_struct), name, - tun_setup, - MAX_TAP_QUEUES, MAX_TAP_QUEUES); + tun_setup, queues, queues); + if (!dev) return -ENOMEM; diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 42f51c71ec1..248d2dc765a 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -374,6 +374,21 @@ static const struct driver_info cdc_mbim_info = { .tx_fixup = cdc_mbim_tx_fixup, }; +/* MBIM and NCM devices should not need a ZLP after NTBs with + * dwNtbOutMaxSize length. This driver_info is for the exceptional + * devices requiring it anyway, allowing them to be supported without + * forcing the performance penalty on all the sane devices. + */ +static const struct driver_info cdc_mbim_info_zlp = { + .description = "CDC MBIM", + .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP, + .bind = cdc_mbim_bind, + .unbind = cdc_mbim_unbind, + .manage_power = cdc_mbim_manage_power, + .rx_fixup = cdc_mbim_rx_fixup, + .tx_fixup = cdc_mbim_tx_fixup, +}; + static const struct usb_device_id mbim_devs[] = { /* This duplicate NCM entry is intentional. MBIM devices can * be disguised as NCM by default, and this is necessary to @@ -385,6 +400,10 @@ static const struct usb_device_id mbim_devs[] = { { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&cdc_mbim_info, }, + /* Sierra Wireless MC7710 need ZLPs */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68a2, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&cdc_mbim_info_zlp, + }, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&cdc_mbim_info, }, diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 016aa6fe6ac..b5ad7eadc4f 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -435,6 +435,13 @@ advance: len -= temp; } + /* some buggy devices have an IAD but no CDC Union */ + if (!ctx->union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) { + ctx->control = intf; + ctx->data = usb_ifnum_to_if(dev->udev, intf->cur_altsetting->desc.bInterfaceNumber + 1); + dev_dbg(&intf->dev, "CDC Union missing - got slave from IAD\n"); + } + /* check if we got everything */ if ((ctx->control == NULL) || (ctx->data == NULL) || ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf)))) @@ -497,7 +504,8 @@ advance: error2: usb_set_intfdata(ctx->control, NULL); usb_set_intfdata(ctx->data, NULL); - usb_driver_release_interface(driver, ctx->data); + if (ctx->data != ctx->control) + usb_driver_release_interface(driver, ctx->data); error: cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]); dev->data[0] = 0; @@ -1155,6 +1163,20 @@ static const struct driver_info wwan_info = { .tx_fixup = cdc_ncm_tx_fixup, }; +/* Same as wwan_info, but with FLAG_NOARP */ +static const struct driver_info wwan_noarp_info = { + .description = "Mobile Broadband Network Device (NO ARP)", + .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET + | FLAG_WWAN | FLAG_NOARP, + .bind = cdc_ncm_bind, + .unbind = cdc_ncm_unbind, + .check_connect = cdc_ncm_check_connect, + .manage_power = usbnet_manage_power, + .status = cdc_ncm_status, + .rx_fixup = cdc_ncm_rx_fixup, + .tx_fixup = cdc_ncm_tx_fixup, +}; + static const struct usb_device_id cdc_devs[] = { /* Ericsson MBM devices like F5521gw */ { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO @@ -1194,6 +1216,13 @@ static const struct usb_device_id cdc_devs[] = { .driver_info = (unsigned long)&wwan_info, }, + /* Infineon(now Intel) HSPA Modem platform */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_noarp_info, + }, + /* Generic CDC-NCM devices */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 0794004fd9d..174e5ecea4c 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -45,6 +45,12 @@ #define DM_MCAST_ADDR 0x16 /* 8 bytes */ #define DM_GPR_CTRL 0x1e #define DM_GPR_DATA 0x1f +#define DM_CHIP_ID 0x2c +#define DM_MODE_CTRL 0x91 /* only on dm9620 */ + +/* chip id values */ +#define ID_DM9601 0 +#define ID_DM9620 1 #define DM_MAX_MCAST 64 #define DM_MCAST_SIZE 8 @@ -53,7 +59,6 @@ #define DM_RX_OVERHEAD 7 /* 3 byte header + 4 byte crc tail */ #define DM_TIMEOUT 1000 - static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) { int err; @@ -84,32 +89,23 @@ static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data) static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) { - return usbnet_write_cmd(dev, DM_WRITE_REGS, + return usbnet_write_cmd(dev, DM_WRITE_REG, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, reg, NULL, 0); } -static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value, - u16 length, void *data) +static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) { usbnet_write_cmd_async(dev, DM_WRITE_REGS, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, reg, data, length); -} - -static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) -{ - netdev_dbg(dev->net, "dm_write_async() reg=0x%02x length=%d\n", reg, length); - - dm_write_async_helper(dev, reg, 0, length, data); + 0, reg, data, length); } static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) { - netdev_dbg(dev->net, "dm_write_reg_async() reg=0x%02x value=0x%02x\n", - reg, value); - - dm_write_async_helper(dev, reg, value, 0, NULL); + usbnet_write_cmd_async(dev, DM_WRITE_REG, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, reg, NULL, 0); } static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value) @@ -358,7 +354,7 @@ static const struct net_device_ops dm9601_netdev_ops = { static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) { int ret; - u8 mac[ETH_ALEN]; + u8 mac[ETH_ALEN], id; ret = usbnet_get_endpoints(dev, intf); if (ret) @@ -399,6 +395,24 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) __dm9601_set_mac_address(dev); } + if (dm_read_reg(dev, DM_CHIP_ID, &id) < 0) { + netdev_err(dev->net, "Error reading chip ID\n"); + ret = -ENODEV; + goto out; + } + + /* put dm9620 devices in dm9601 mode */ + if (id == ID_DM9620) { + u8 mode; + + if (dm_read_reg(dev, DM_MODE_CTRL, &mode) < 0) { + netdev_err(dev->net, "Error reading MODE_CTRL\n"); + ret = -ENODEV; + goto out; + } + dm_write_reg(dev, DM_MODE_CTRL, mode & 0x7f); + } + /* power up phy */ dm_write_reg(dev, DM_GPR_CTRL, 1); dm_write_reg(dev, DM_GPR_DATA, 0); @@ -581,6 +595,10 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0a46, 0x9000), /* DM9000E */ .driver_info = (unsigned long)&dm9601_info, }, + { + USB_DEVICE(0x0a46, 0x9620), /* DM9620 USB to Fast Ethernet Adapter */ + .driver_info = (unsigned long)&dm9601_info, + }, {}, // END }; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6a1ca500e61..575a5839ee3 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -433,6 +433,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ + {QMI_FIXED_INTF(0x19d2, 0x0265, 4)}, /* ONDA MT8205 4G LTE */ {QMI_FIXED_INTF(0x19d2, 0x0284, 4)}, /* ZTE MF880 */ {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ @@ -459,6 +460,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ + {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 3d4bf01641b..f34b2ebee81 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1448,6 +1448,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) if ((dev->driver_info->flags & FLAG_WWAN) != 0) strcpy(net->name, "wwan%d"); + /* devices that cannot do ARP */ + if ((dev->driver_info->flags & FLAG_NOARP) != 0) + net->flags |= IFF_NOARP; + /* maybe the remote can't receive an Ethernet MTU */ if (net->mtu > (dev->hard_mtu - net->hard_header_len)) net->mtu = dev->hard_mtu - net->hard_header_len; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 58914c8ea68..eda2042a646 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -26,6 +26,7 @@ #include <linux/scatterlist.h> #include <linux/if_vlan.h> #include <linux/slab.h> +#include <linux/cpu.h> static int napi_weight = 128; module_param(napi_weight, int, 0444); @@ -123,6 +124,12 @@ struct virtnet_info { /* Does the affinity hint is set for virtqueues? */ bool affinity_hint_set; + + /* Per-cpu variable to show the mapping from CPU to virtqueue */ + int __percpu *vq_index; + + /* CPU hot plug notifier */ + struct notifier_block nb; }; struct skb_vnet_hdr { @@ -1030,32 +1037,75 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) return 0; } -static void virtnet_set_affinity(struct virtnet_info *vi, bool set) +static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu) { int i; + int cpu; + + if (vi->affinity_hint_set) { + for (i = 0; i < vi->max_queue_pairs; i++) { + virtqueue_set_affinity(vi->rq[i].vq, -1); + virtqueue_set_affinity(vi->sq[i].vq, -1); + } + + vi->affinity_hint_set = false; + } + + i = 0; + for_each_online_cpu(cpu) { + if (cpu == hcpu) { + *per_cpu_ptr(vi->vq_index, cpu) = -1; + } else { + *per_cpu_ptr(vi->vq_index, cpu) = + ++i % vi->curr_queue_pairs; + } + } +} + +static void virtnet_set_affinity(struct virtnet_info *vi) +{ + int i; + int cpu; /* In multiqueue mode, when the number of cpu is equal to the number of * queue pairs, we let the queue pairs to be private to one cpu by * setting the affinity hint to eliminate the contention. */ - if ((vi->curr_queue_pairs == 1 || - vi->max_queue_pairs != num_online_cpus()) && set) { - if (vi->affinity_hint_set) - set = false; - else - return; + if (vi->curr_queue_pairs == 1 || + vi->max_queue_pairs != num_online_cpus()) { + virtnet_clean_affinity(vi, -1); + return; } - for (i = 0; i < vi->max_queue_pairs; i++) { - int cpu = set ? i : -1; + i = 0; + for_each_online_cpu(cpu) { virtqueue_set_affinity(vi->rq[i].vq, cpu); virtqueue_set_affinity(vi->sq[i].vq, cpu); + *per_cpu_ptr(vi->vq_index, cpu) = i; + i++; } - if (set) - vi->affinity_hint_set = true; - else - vi->affinity_hint_set = false; + vi->affinity_hint_set = true; +} + +static int virtnet_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); + + switch(action & ~CPU_TASKS_FROZEN) { + case CPU_ONLINE: + case CPU_DOWN_FAILED: + case CPU_DEAD: + virtnet_set_affinity(vi); + break; + case CPU_DOWN_PREPARE: + virtnet_clean_affinity(vi, (long)hcpu); + break; + default: + break; + } + return NOTIFY_OK; } static void virtnet_get_ringparam(struct net_device *dev, @@ -1099,13 +1149,15 @@ static int virtnet_set_channels(struct net_device *dev, if (queue_pairs > vi->max_queue_pairs) return -EINVAL; + get_online_cpus(); err = virtnet_set_queues(vi, queue_pairs); if (!err) { netif_set_real_num_tx_queues(dev, queue_pairs); netif_set_real_num_rx_queues(dev, queue_pairs); - virtnet_set_affinity(vi, true); + virtnet_set_affinity(vi); } + put_online_cpus(); return err; } @@ -1144,12 +1196,19 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu) /* To avoid contending a lock hold by a vcpu who would exit to host, select the * txq based on the processor id. - * TODO: handle cpu hotplug. */ static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb) { - int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : - smp_processor_id(); + int txq; + struct virtnet_info *vi = netdev_priv(dev); + + if (skb_rx_queue_recorded(skb)) { + txq = skb_get_rx_queue(skb); + } else { + txq = *__this_cpu_ptr(vi->vq_index); + if (txq == -1) + txq = 0; + } while (unlikely(txq >= dev->real_num_tx_queues)) txq -= dev->real_num_tx_queues; @@ -1265,7 +1324,7 @@ static void virtnet_del_vqs(struct virtnet_info *vi) { struct virtio_device *vdev = vi->vdev; - virtnet_set_affinity(vi, false); + virtnet_clean_affinity(vi, -1); vdev->config->del_vqs(vdev); @@ -1388,7 +1447,10 @@ static int init_vqs(struct virtnet_info *vi) if (ret) goto err_free; - virtnet_set_affinity(vi, true); + get_online_cpus(); + virtnet_set_affinity(vi); + put_online_cpus(); + return 0; err_free: @@ -1470,6 +1532,10 @@ static int virtnet_probe(struct virtio_device *vdev) if (vi->stats == NULL) goto free; + vi->vq_index = alloc_percpu(int); + if (vi->vq_index == NULL) + goto free_stats; + mutex_init(&vi->config_lock); vi->config_enable = true; INIT_WORK(&vi->config_work, virtnet_config_changed_work); @@ -1493,7 +1559,7 @@ static int virtnet_probe(struct virtio_device *vdev) /* Allocate/initialize the rx/tx queues, and invoke find_vqs */ err = init_vqs(vi); if (err) - goto free_stats; + goto free_index; netif_set_real_num_tx_queues(dev, 1); netif_set_real_num_rx_queues(dev, 1); @@ -1516,6 +1582,13 @@ static int virtnet_probe(struct virtio_device *vdev) } } + vi->nb.notifier_call = &virtnet_cpu_callback; + err = register_hotcpu_notifier(&vi->nb); + if (err) { + pr_debug("virtio_net: registering cpu notifier failed\n"); + goto free_recv_bufs; + } + /* Assume link up if device can't report link status, otherwise get link status from config. */ if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { @@ -1537,6 +1610,8 @@ free_recv_bufs: free_vqs: cancel_delayed_work_sync(&vi->refill); virtnet_del_vqs(vi); +free_index: + free_percpu(vi->vq_index); free_stats: free_percpu(vi->stats); free: @@ -1560,6 +1635,8 @@ static void virtnet_remove(struct virtio_device *vdev) { struct virtnet_info *vi = vdev->priv; + unregister_hotcpu_notifier(&vi->nb); + /* Prevent config work handler from accessing the device. */ mutex_lock(&vi->config_lock); vi->config_enable = false; @@ -1571,6 +1648,7 @@ static void virtnet_remove(struct virtio_device *vdev) flush_work(&vi->config_work); + free_percpu(vi->vq_index); free_percpu(vi->stats); free_netdev(vi->dev); } diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 26ffd3e3fb7..2c113de9432 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -44,7 +44,6 @@ extern bool pciehp_poll_mode; extern int pciehp_poll_time; extern bool pciehp_debug; extern bool pciehp_force; -extern struct workqueue_struct *pciehp_wq; #define dbg(format, arg...) \ do { \ @@ -78,6 +77,7 @@ struct slot { struct hotplug_slot *hotplug_slot; struct delayed_work work; /* work for button event */ struct mutex lock; + struct workqueue_struct *wq; }; struct event_info { diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 916bf4f53ab..939bd1d4b5b 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -42,7 +42,6 @@ bool pciehp_debug; bool pciehp_poll_mode; int pciehp_poll_time; bool pciehp_force; -struct workqueue_struct *pciehp_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" @@ -340,18 +339,13 @@ static int __init pcied_init(void) { int retval = 0; - pciehp_wq = alloc_workqueue("pciehp", 0, 0); - if (!pciehp_wq) - return -ENOMEM; - pciehp_firmware_init(); retval = pcie_port_service_register(&hpdriver_portdrv); dbg("pcie_port_service_register = %d\n", retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) { - destroy_workqueue(pciehp_wq); + if (retval) dbg("Failure to register service\n"); - } + return retval; } @@ -359,7 +353,6 @@ static void __exit pcied_cleanup(void) { dbg("unload_pciehpd()\n"); pcie_port_service_unregister(&hpdriver_portdrv); - destroy_workqueue(pciehp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 27f44295a65..38f01867917 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -49,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler); - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); return 0; } @@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); out: mutex_unlock(&p_slot->lock); } @@ -377,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot) if (ATTN_LED(ctrl)) pciehp_set_attention_status(p_slot, 0); - queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ); + queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); break; case BLINKINGOFF_STATE: case BLINKINGON_STATE: @@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot) else p_slot->state = POWERON_STATE; - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); } static void interrupt_event_handler(struct work_struct *work) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 13b2eaf7ba4..5127f3f4182 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -773,23 +773,32 @@ static void pcie_shutdown_notification(struct controller *ctrl) static int pcie_init_slot(struct controller *ctrl) { struct slot *slot; + char name[32]; slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; + snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl)); + slot->wq = alloc_workqueue(name, 0, 0); + if (!slot->wq) + goto abort; + slot->ctrl = ctrl; mutex_init(&slot->lock); INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); ctrl->slot = slot; return 0; +abort: + kfree(slot); + return -ENOMEM; } static void pcie_cleanup_slot(struct controller *ctrl) { struct slot *slot = ctrl->slot; cancel_delayed_work(&slot->work); - flush_workqueue(pciehp_wq); + destroy_workqueue(slot->wq); kfree(slot); } diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ca64932e658..b849f995075 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -46,8 +46,6 @@ extern bool shpchp_poll_mode; extern int shpchp_poll_time; extern bool shpchp_debug; -extern struct workqueue_struct *shpchp_wq; -extern struct workqueue_struct *shpchp_ordered_wq; #define dbg(format, arg...) \ do { \ @@ -91,6 +89,7 @@ struct slot { struct list_head slot_list; struct delayed_work work; /* work for button event */ struct mutex lock; + struct workqueue_struct *wq; u8 hp_slot; }; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index b6de307248e..3100c52c837 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -39,8 +39,6 @@ bool shpchp_debug; bool shpchp_poll_mode; int shpchp_poll_time; -struct workqueue_struct *shpchp_wq; -struct workqueue_struct *shpchp_ordered_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" @@ -129,6 +127,14 @@ static int init_slots(struct controller *ctrl) slot->device = ctrl->slot_device_offset + i; slot->hpc_ops = ctrl->hpc_ops; slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); + + snprintf(name, sizeof(name), "shpchp-%d", slot->number); + slot->wq = alloc_workqueue(name, 0, 0); + if (!slot->wq) { + retval = -ENOMEM; + goto error_info; + } + mutex_init(&slot->lock); INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); @@ -148,7 +154,7 @@ static int init_slots(struct controller *ctrl) if (retval) { ctrl_err(ctrl, "pci_hp_register failed with error %d\n", retval); - goto error_info; + goto error_slotwq; } get_power_status(hotplug_slot, &info->power_status); @@ -160,6 +166,8 @@ static int init_slots(struct controller *ctrl) } return 0; +error_slotwq: + destroy_workqueue(slot->wq); error_info: kfree(info); error_hpslot: @@ -180,8 +188,7 @@ void cleanup_slots(struct controller *ctrl) slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); cancel_delayed_work(&slot->work); - flush_workqueue(shpchp_wq); - flush_workqueue(shpchp_ordered_wq); + destroy_workqueue(slot->wq); pci_hp_deregister(slot->hotplug_slot); } } @@ -364,25 +371,12 @@ static struct pci_driver shpc_driver = { static int __init shpcd_init(void) { - int retval = 0; - - shpchp_wq = alloc_ordered_workqueue("shpchp", 0); - if (!shpchp_wq) - return -ENOMEM; - - shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0); - if (!shpchp_ordered_wq) { - destroy_workqueue(shpchp_wq); - return -ENOMEM; - } + int retval; retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __func__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) { - destroy_workqueue(shpchp_ordered_wq); - destroy_workqueue(shpchp_wq); - } + return retval; } @@ -390,8 +384,6 @@ static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); pci_unregister_driver(&shpc_driver); - destroy_workqueue(shpchp_ordered_wq); - destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index f9b5a52e411..58499277903 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -51,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler); - queue_work(shpchp_wq, &info->work); + queue_work(p_slot->wq, &info->work); return 0; } @@ -453,7 +453,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(shpchp_ordered_wq, &info->work); + queue_work(p_slot->wq, &info->work); out: mutex_unlock(&p_slot->lock); } @@ -501,7 +501,7 @@ static void handle_button_press_event(struct slot *p_slot) p_slot->hpc_ops->green_led_blink(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); + queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); break; case BLINKINGOFF_STATE: case BLINKINGON_STATE: diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 6c8bc580978..fde4a32a029 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -82,4 +82,4 @@ endchoice config PCIE_PME def_bool y - depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI + depends on PCIEPORTBUS && PM_RUNTIME && ACPI diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 421bbc5fee3..564d97f94b6 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -630,6 +630,7 @@ static void aer_recover_work_func(struct work_struct *work) continue; } do_recovery(pdev, entry.severity); + pci_dev_put(pdev); } } #endif diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b52630b8ead..8474b6a4fc9 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -771,6 +771,9 @@ void pcie_clear_aspm(struct pci_bus *bus) { struct pci_dev *child; + if (aspm_force) + return; + /* * Clear any ASPM setup that the firmware has carried out on this bus */ diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 0f65b246cc0..278584302f2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1885,9 +1885,15 @@ int regulator_can_change_voltage(struct regulator *regulator) struct regulator_dev *rdev = regulator->rdev; if (rdev->constraints && - rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE && - (rdev->desc->n_voltages - rdev->desc->linear_min_sel) > 1) - return 1; + (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { + if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) + return 1; + + if (rdev->desc->continuous_voltage_range && + rdev->constraints->min_uV && rdev->constraints->max_uV && + rdev->constraints->min_uV != rdev->constraints->max_uV) + return 1; + } return 0; } @@ -3315,7 +3321,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) * @config: runtime configuration for regulator * * Called by regulator drivers to register a regulator. - * Returns 0 on success. + * Returns a valid pointer to struct regulator_dev on success + * or an ERR_PTR() on error. */ struct regulator_dev * regulator_register(const struct regulator_desc *regulator_desc, diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index df0eafb0dc7..02be7fcae32 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -71,26 +71,26 @@ struct voltage_map_desc { int step; }; -/* Voltage maps in mV */ +/* Voltage maps in uV */ static const struct voltage_map_desc ldo_voltage_map_desc = { - .min = 800, .max = 3950, .step = 50, + .min = 800000, .max = 3950000, .step = 50000, }; /* LDO1 ~ 18, 21 all */ static const struct voltage_map_desc buck1245_voltage_map_desc = { - .min = 650, .max = 2225, .step = 25, + .min = 650000, .max = 2225000, .step = 25000, }; /* Buck1, 2, 4, 5 */ static const struct voltage_map_desc buck37_voltage_map_desc = { - .min = 750, .max = 3900, .step = 50, + .min = 750000, .max = 3900000, .step = 50000, }; /* Buck3, 7 */ -/* current map in mA */ +/* current map in uA */ static const struct voltage_map_desc charger_current_map_desc = { - .min = 200, .max = 950, .step = 50, + .min = 200000, .max = 950000, .step = 50000, }; static const struct voltage_map_desc topoff_current_map_desc = { - .min = 50, .max = 200, .step = 10, + .min = 50000, .max = 200000, .step = 10000, }; static const struct voltage_map_desc *reg_voltage_map[] = { @@ -194,7 +194,7 @@ static int max8997_list_voltage(struct regulator_dev *rdev, if (val > desc->max) return -EINVAL; - return val * 1000; + return val; } static int max8997_get_enable_register(struct regulator_dev *rdev, @@ -485,7 +485,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, { struct max8997_data *max8997 = rdev_get_drvdata(rdev); struct i2c_client *i2c = max8997->iodev->i2c; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; const struct voltage_map_desc *desc; int rid = rdev_get_id(rdev); int i, reg, shift, mask, ret; @@ -509,7 +508,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, desc = reg_voltage_map[rid]; - i = max8997_get_voltage_proper_val(desc, min_vol, max_vol); + i = max8997_get_voltage_proper_val(desc, min_uV, max_uV); if (i < 0) return i; @@ -557,7 +556,7 @@ static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev, case MAX8997_BUCK4: case MAX8997_BUCK5: return DIV_ROUND_UP(desc->step * (new_selector - old_selector), - max8997->ramp_delay); + max8997->ramp_delay * 1000); } return 0; @@ -656,7 +655,6 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, const struct voltage_map_desc *desc; int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; bool gpio_dvs_mode = false; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) return -EINVAL; @@ -681,7 +679,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, selector); desc = reg_voltage_map[rid]; - new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol); + new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV); if (new_val < 0) return new_val; @@ -1123,8 +1121,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) max8997->buck1_vol[i] = ret = max8997_get_voltage_proper_val( &buck1245_voltage_map_desc, - pdata->buck1_voltage[i] / 1000, - pdata->buck1_voltage[i] / 1000 + + pdata->buck1_voltage[i], + pdata->buck1_voltage[i] + buck1245_voltage_map_desc.step); if (ret < 0) goto err_out; @@ -1132,8 +1130,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) max8997->buck2_vol[i] = ret = max8997_get_voltage_proper_val( &buck1245_voltage_map_desc, - pdata->buck2_voltage[i] / 1000, - pdata->buck2_voltage[i] / 1000 + + pdata->buck2_voltage[i], + pdata->buck2_voltage[i] + buck1245_voltage_map_desc.step); if (ret < 0) goto err_out; @@ -1141,8 +1139,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) max8997->buck5_vol[i] = ret = max8997_get_voltage_proper_val( &buck1245_voltage_map_desc, - pdata->buck5_voltage[i] / 1000, - pdata->buck5_voltage[i] / 1000 + + pdata->buck5_voltage[i], + pdata->buck5_voltage[i] + buck1245_voltage_map_desc.step); if (ret < 0) goto err_out; diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index b821d08eb64..1f0df4046b8 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -51,39 +51,39 @@ struct voltage_map_desc { int step; }; -/* Voltage maps */ +/* Voltage maps in uV*/ static const struct voltage_map_desc ldo23_voltage_map_desc = { - .min = 800, .step = 50, .max = 1300, + .min = 800000, .step = 50000, .max = 1300000, }; static const struct voltage_map_desc ldo456711_voltage_map_desc = { - .min = 1600, .step = 100, .max = 3600, + .min = 1600000, .step = 100000, .max = 3600000, }; static const struct voltage_map_desc ldo8_voltage_map_desc = { - .min = 3000, .step = 100, .max = 3600, + .min = 3000000, .step = 100000, .max = 3600000, }; static const struct voltage_map_desc ldo9_voltage_map_desc = { - .min = 2800, .step = 100, .max = 3100, + .min = 2800000, .step = 100000, .max = 3100000, }; static const struct voltage_map_desc ldo10_voltage_map_desc = { - .min = 950, .step = 50, .max = 1300, + .min = 95000, .step = 50000, .max = 1300000, }; static const struct voltage_map_desc ldo1213_voltage_map_desc = { - .min = 800, .step = 100, .max = 3300, + .min = 800000, .step = 100000, .max = 3300000, }; static const struct voltage_map_desc ldo1415_voltage_map_desc = { - .min = 1200, .step = 100, .max = 3300, + .min = 1200000, .step = 100000, .max = 3300000, }; static const struct voltage_map_desc ldo1617_voltage_map_desc = { - .min = 1600, .step = 100, .max = 3600, + .min = 1600000, .step = 100000, .max = 3600000, }; static const struct voltage_map_desc buck12_voltage_map_desc = { - .min = 750, .step = 25, .max = 1525, + .min = 750000, .step = 25000, .max = 1525000, }; static const struct voltage_map_desc buck3_voltage_map_desc = { - .min = 1600, .step = 100, .max = 3600, + .min = 1600000, .step = 100000, .max = 3600000, }; static const struct voltage_map_desc buck4_voltage_map_desc = { - .min = 800, .step = 100, .max = 2300, + .min = 800000, .step = 100000, .max = 2300000, }; static const struct voltage_map_desc *ldo_voltage_map[] = { @@ -445,9 +445,9 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev, if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) return 0; - difference = (new_selector - old_selector) * desc->step; + difference = (new_selector - old_selector) * desc->step / 1000; if (difference > 0) - return difference / ((val & 0x0f) + 1); + return DIV_ROUND_UP(difference, (val & 0x0f) + 1); return 0; } @@ -702,7 +702,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck1_voltage1 / 1000)) + < pdata->buck1_voltage1) i++; max8998->buck1_vol[0] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); @@ -713,7 +713,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck1_voltage2 / 1000)) + < pdata->buck1_voltage2) i++; max8998->buck1_vol[1] = i; @@ -725,7 +725,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck1_voltage3 / 1000)) + < pdata->buck1_voltage3) i++; max8998->buck1_vol[2] = i; @@ -737,7 +737,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck1_voltage4 / 1000)) + < pdata->buck1_voltage4) i++; max8998->buck1_vol[3] = i; @@ -763,7 +763,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck2_voltage1 / 1000)) + < pdata->buck2_voltage1) i++; max8998->buck2_vol[0] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); @@ -774,7 +774,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) i = 0; while (buck12_voltage_map_desc.min + buck12_voltage_map_desc.step*i - < (pdata->buck2_voltage2 / 1000)) + < pdata->buck2_voltage2) i++; max8998->buck2_vol[1] = i; ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); @@ -792,8 +792,8 @@ static int max8998_pmic_probe(struct platform_device *pdev) int count = (desc->max - desc->min) / desc->step + 1; regulators[index].n_voltages = count; - regulators[index].min_uV = desc->min * 1000; - regulators[index].uV_step = desc->step * 1000; + regulators[index].min_uV = desc->min; + regulators[index].uV_step = desc->step; } config.dev = max8998->dev; diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 9f991f2c525..33b65c9ad5d 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -214,7 +214,7 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int ret, reg; int mask = 0xc0, enable_ctrl; - u8 val; + unsigned int val; ret = s5m8767_get_register(rdev, ®, &enable_ctrl); if (ret == -EINVAL) @@ -306,7 +306,7 @@ static int s5m8767_get_voltage_sel(struct regulator_dev *rdev) struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); int reg, mask, ret; int reg_id = rdev_get_id(rdev); - u8 val; + unsigned int val; ret = s5m8767_get_voltage_register(rdev, ®); if (ret) diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 68e80e2734a..10729bbcece 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -283,7 +283,7 @@ struct chsc_sei_nt2_area { u8 ccdf[PAGE_SIZE - 24 - 56]; /* content-code dependent field */ } __packed; -#define CHSC_SEI_NT0 0ULL +#define CHSC_SEI_NT0 (1ULL << 63) #define CHSC_SEI_NT2 (1ULL << 61) struct chsc_sei { @@ -291,7 +291,8 @@ struct chsc_sei { u32 reserved1; u64 ntsm; /* notification type mask */ struct chsc_header response; - u32 reserved2; + u32 :24; + u8 nt; union { struct chsc_sei_nt0_area nt0_area; struct chsc_sei_nt2_area nt2_area; @@ -496,17 +497,17 @@ static int __chsc_process_crw(struct chsc_sei *sei, u64 ntsm) css_schedule_eval_all(); } - switch (sei->ntsm) { - case CHSC_SEI_NT0: + switch (sei->nt) { + case 0: chsc_process_sei_nt0(&sei->u.nt0_area); - return 1; - case CHSC_SEI_NT2: + break; + case 2: chsc_process_sei_nt2(&sei->u.nt2_area); - return 1; + break; default: - CIO_CRW_EVENT(2, "chsc: unhandled nt (nt=%08Lx)\n", - sei->ntsm); - return 0; + CIO_CRW_EVENT(2, "chsc: unhandled nt=%d\n", + sei->nt); + break; } } else { CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", @@ -537,15 +538,7 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow) sei = sei_page; CIO_TRACE_EVENT(2, "prcss"); - - /* - * The ntsm does not allow to select NT0 and NT2 together. We need to - * first check for NT2, than additionally for NT0... - */ -#ifdef CONFIG_PCI - if (!__chsc_process_crw(sei, CHSC_SEI_NT2)) -#endif - __chsc_process_crw(sei, CHSC_SEI_NT0); + __chsc_process_crw(sei, CHSC_SEI_NT0 | CHSC_SEI_NT2); } void chsc_chp_online(struct chp_id chpid) diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 5aedcdf4ac5..1ebe67cd183 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -126,6 +126,12 @@ static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate) static int sh_clk_div_enable(struct clk *clk) { + if (clk->div_mask == SH_CLK_DIV6_MSK) { + int ret = sh_clk_div_set_rate(clk, clk->rate); + if (ret < 0) + return ret; + } + sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk); return 0; } diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index fb31b457a56..c5ceb9d90ea 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -239,7 +239,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) struct mxs_lradc *lradc = iio_priv(iio); const uint32_t chan_value = LRADC_CH_ACCUMULATE | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); - int i, j = 0; + unsigned int i, j = 0; for_each_set_bit(i, iio->active_scan_mask, iio->masklength) { lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index 3525a68d6a7..41d7350d030 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c @@ -69,7 +69,7 @@ static int adis16080_spi_read(struct iio_dev *indio_dev, ret = spi_read(st->us, st->buf, 2); if (ret == 0) - *val = ((st->buf[0] & 0xF) << 8) | st->buf[1]; + *val = sign_extend32(((st->buf[0] & 0xF) << 8) | st->buf[1], 11); mutex_unlock(&st->buf_lock); return ret; diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c index 131afd0c460..9464f387434 100644 --- a/drivers/staging/sb105x/sb_pci_mp.c +++ b/drivers/staging/sb105x/sb_pci_mp.c @@ -3054,7 +3054,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd) sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16); } break; -#ifdef CONFIG_PARPORT +#ifdef CONFIG_PARPORT_PC case PCI_DEVICE_ID_MP2S1P : sbdev->nr_ports = 2; diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h index 6b2ec390e77..806cbf72fb5 100644 --- a/drivers/staging/vt6656/bssdb.h +++ b/drivers/staging/vt6656/bssdb.h @@ -90,7 +90,6 @@ typedef struct tagSRSNCapObject { } SRSNCapObject, *PSRSNCapObject; // BSS info(AP) -#pragma pack(1) typedef struct tagKnownBSS { // BSS info BOOL bActive; diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index 5d8faf9f96e..e0d2b07ba60 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -34,7 +34,6 @@ #include "device.h" /*--------------------- Export Definitions -------------------------*/ -#pragma pack(1) typedef struct tagSINTData { BYTE byTSR0; BYTE byPkt0; diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h index 22710cef751..ae6e2d237b2 100644 --- a/drivers/staging/vt6656/iocmd.h +++ b/drivers/staging/vt6656/iocmd.h @@ -95,13 +95,12 @@ typedef enum tagWZONETYPE { // Ioctl interface structure // Command structure // -#pragma pack(1) typedef struct tagSCmdRequest { u8 name[16]; void *data; u16 wResult; u16 wCmdCode; -} SCmdRequest, *PSCmdRequest; +} __packed SCmdRequest, *PSCmdRequest; // // Scan @@ -111,7 +110,7 @@ typedef struct tagSCmdScan { u8 ssid[SSID_MAXLEN + 2]; -} SCmdScan, *PSCmdScan; +} __packed SCmdScan, *PSCmdScan; // // BSS Join @@ -126,7 +125,7 @@ typedef struct tagSCmdBSSJoin { BOOL bPSEnable; BOOL bShareKeyAuth; -} SCmdBSSJoin, *PSCmdBSSJoin; +} __packed SCmdBSSJoin, *PSCmdBSSJoin; // // Zonetype Setting @@ -137,7 +136,7 @@ typedef struct tagSCmdZoneTypeSet { BOOL bWrite; WZONETYPE ZoneType; -} SCmdZoneTypeSet, *PSCmdZoneTypeSet; +} __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet; typedef struct tagSWPAResult { char ifname[100]; @@ -145,7 +144,7 @@ typedef struct tagSWPAResult { u8 key_mgmt; u8 eap_type; BOOL authenticated; -} SWPAResult, *PSWPAResult; +} __packed SWPAResult, *PSWPAResult; typedef struct tagSCmdStartAP { @@ -157,7 +156,7 @@ typedef struct tagSCmdStartAP { BOOL bShareKeyAuth; u8 byBasicRate; -} SCmdStartAP, *PSCmdStartAP; +} __packed SCmdStartAP, *PSCmdStartAP; typedef struct tagSCmdSetWEP { @@ -167,7 +166,7 @@ typedef struct tagSCmdSetWEP { BOOL bWepKeyAvailable[WEP_NKEYS]; u32 auWepKeyLength[WEP_NKEYS]; -} SCmdSetWEP, *PSCmdSetWEP; +} __packed SCmdSetWEP, *PSCmdSetWEP; typedef struct tagSBSSIDItem { @@ -180,14 +179,14 @@ typedef struct tagSBSSIDItem { BOOL bWEPOn; u32 uRSSI; -} SBSSIDItem; +} __packed SBSSIDItem; typedef struct tagSBSSIDList { u32 uItem; SBSSIDItem sBSSIDList[0]; -} SBSSIDList, *PSBSSIDList; +} __packed SBSSIDList, *PSBSSIDList; typedef struct tagSNodeItem { @@ -208,7 +207,7 @@ typedef struct tagSNodeItem { u32 uTxAttempts; u16 wFailureRatio; -} SNodeItem; +} __packed SNodeItem; typedef struct tagSNodeList { @@ -216,7 +215,7 @@ typedef struct tagSNodeList { u32 uItem; SNodeItem sNodeList[0]; -} SNodeList, *PSNodeList; +} __packed SNodeList, *PSNodeList; typedef struct tagSCmdLinkStatus { @@ -229,7 +228,7 @@ typedef struct tagSCmdLinkStatus { u32 uChannel; u32 uLinkRate; -} SCmdLinkStatus, *PSCmdLinkStatus; +} __packed SCmdLinkStatus, *PSCmdLinkStatus; // // 802.11 counter @@ -247,7 +246,7 @@ typedef struct tagSDot11MIBCount { u32 ReceivedFragmentCount; u32 MulticastReceivedFrameCount; u32 FCSErrorCount; -} SDot11MIBCount, *PSDot11MIBCount; +} __packed SDot11MIBCount, *PSDot11MIBCount; @@ -355,13 +354,13 @@ typedef struct tagSStatMIBCount { u32 ullTxBroadcastBytes[2]; u32 ullTxMulticastBytes[2]; u32 ullTxDirectedBytes[2]; -} SStatMIBCount, *PSStatMIBCount; +} __packed SStatMIBCount, *PSStatMIBCount; typedef struct tagSCmdValue { u32 dwValue; -} SCmdValue, *PSCmdValue; +} __packed SCmdValue, *PSCmdValue; // // hostapd & viawget ioctl related @@ -431,7 +430,7 @@ struct viawget_hostapd_param { u8 ssid[32]; } scan_req; } u; -}; +} __packed; /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h index 959c8868f6e..2522ddec718 100644 --- a/drivers/staging/vt6656/iowpa.h +++ b/drivers/staging/vt6656/iowpa.h @@ -67,12 +67,11 @@ enum { -#pragma pack(1) typedef struct viawget_wpa_header { u8 type; u16 req_ie_len; u16 resp_ie_len; -} viawget_wpa_header; +} __packed viawget_wpa_header; struct viawget_wpa_param { u32 cmd; @@ -113,9 +112,8 @@ struct viawget_wpa_param { u8 *buf; } scan_results; } u; -}; +} __packed; -#pragma pack(1) struct viawget_scan_result { u8 bssid[6]; u8 ssid[32]; @@ -130,7 +128,7 @@ struct viawget_scan_result { int noise; int level; int maxrate; -}; +} __packed; /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 4efa9bc0fcf..89bfd858bb2 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -406,7 +406,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* SSID */ req->ssid.status = P80211ENUM_msgitem_status_data_ok; req->ssid.data.len = le16_to_cpu(item->ssid.len); - req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN); + req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN); memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); /* supported rates */ diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index 9ac4c151eae..ba6091bf93f 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c @@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) * made generic here. */ if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && - iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) { + iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) { list_del(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); iscsit_free_cmd(cmd); diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 85140f7dde1..7d4ec02e29a 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -212,7 +212,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; unsigned char *buf; unsigned char *ptr; - sense_reason_t rc; + sense_reason_t rc = TCM_NO_SENSE; u32 len = 4; /* Skip over RESERVED area in header */ int alua_access_state, primary = 0; u16 tg_pt_id, rtpi; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index e35dbf85841..8e0290b38e4 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2053,7 +2053,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, /* Used for APTPL metadata w/ UNREGISTER */ unsigned char *pr_aptpl_buf = NULL; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; - sense_reason_t ret; + sense_reason_t ret = TCM_NO_SENSE; int pr_holder = 0, type; if (!se_sess || !se_lun) { diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c23c76ccef6..bd587b70661 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -541,9 +541,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) { - if (!(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) - transport_lun_remove_cmd(cmd); - if (transport_cmd_check_stop_to_fabric(cmd)) return; if (remove) @@ -1396,6 +1393,8 @@ static void target_complete_tmr_failure(struct work_struct *work) se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; se_cmd->se_tfo->queue_tm_rsp(se_cmd); + + transport_cmd_check_stop_to_fabric(se_cmd); } /** @@ -1688,6 +1687,7 @@ void target_execute_cmd(struct se_cmd *cmd) } cmd->t_state = TRANSPORT_PROCESSING; + cmd->transport_state |= CMD_T_ACTIVE; spin_unlock_irq(&cmd->t_state_lock); if (!target_handle_task_attr(cmd)) @@ -2597,6 +2597,16 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, * SENSE KEY values from include/scsi/scsi.h */ switch (reason) { + case TCM_NO_SENSE: + /* CURRENT ERROR */ + buffer[0] = 0x70; + buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; + /* Not Ready */ + buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY; + /* NO ADDITIONAL SENSE INFORMATION */ + buffer[SPC_ASC_KEY_OFFSET] = 0; + buffer[SPC_ASCQ_KEY_OFFSET] = 0; + break; case TCM_NON_EXISTENT_LUN: /* CURRENT ERROR */ buffer[0] = 0x70; @@ -2743,7 +2753,7 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, /* ILLEGAL REQUEST */ buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; /* LOGICAL UNIT COMMUNICATION FAILURE */ - buffer[SPC_ASC_KEY_OFFSET] = 0x80; + buffer[SPC_ASC_KEY_OFFSET] = 0x08; break; } /* @@ -2804,6 +2814,8 @@ void transport_send_task_abort(struct se_cmd *cmd) } cmd->scsi_status = SAM_STAT_TASK_ABORTED; + transport_lun_remove_cmd(cmd); + pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x," " ITT: 0x%08x\n", cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 12d6fa21e5e..6659dd36e80 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -355,11 +355,11 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, tport = ft_tport_create(rdata->local_port); if (!tport) - return 0; /* not a target for this local port */ + goto not_target; /* not a target for this local port */ acl = ft_acl_get(tport->tpg, rdata); if (!acl) - return 0; + goto not_target; /* no target for this remote */ if (!rspp) goto fill; @@ -396,12 +396,18 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, /* * OR in our service parameters with other provider (initiator), if any. - * TBD XXX - indicate RETRY capability? */ fill: fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_RETRY; spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); return FC_SPP_RESP_ACK; + +not_target: + fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_TARG_FCN; + spp->spp_params = htonl(fcp_parm); + return 0; } /** diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index be6a373601b..79ff3a5e925 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -441,6 +441,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, return pty_get_pktmode(tty, (int __user *)arg); case TIOCSIG: /* Send signal to other side of pty */ return pty_signal(tty, (int) arg); + case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */ + return -EINVAL; } return -ENOIOCTLCMD; } diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index d085e3a8ec0..f9320437a64 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -300,6 +300,12 @@ static const struct serial8250_config uart_config[] = { UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, .flags = UART_CAP_FIFO, }, + [PORT_BRCM_TRUMANAGE] = { + .name = "TruManage", + .fifo_size = 1, + .tx_loadsz = 1024, + .flags = UART_CAP_HFIFO, + }, [PORT_8250_CIR] = { .name = "CIR port" } @@ -1490,6 +1496,11 @@ void serial8250_tx_chars(struct uart_8250_port *up) port->icount.tx++; if (uart_circ_empty(xmit)) break; + if (up->capabilities & UART_CAP_HFIFO) { + if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) != + BOTH_EMPTY) + break; + } } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 3b4ea84898c..12caa1292b7 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -40,6 +40,7 @@ struct serial8250_config { #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ +#define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */ #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 1d0dba2d562..096d2ef48b3 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -79,7 +79,7 @@ static int dw8250_handle_irq(struct uart_port *p) } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* Clear the USR and write the LCR again. */ (void)p->serial_in(p, UART_USR); - p->serial_out(p, d->last_lcr, UART_LCR); + p->serial_out(p, UART_LCR, d->last_lcr); return 1; } diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 26b9dc012ed..a27a98e1b06 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1085,6 +1085,18 @@ pci_omegapci_setup(struct serial_private *priv, return setup_port(priv, port, 2, idx * 8, 0); } +static int +pci_brcm_trumanage_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + int ret = pci_default_setup(priv, board, port, idx); + + port->port.type = PORT_BRCM_TRUMANAGE; + port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); + return ret; +} + static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -1301,9 +1313,10 @@ pci_wch_ch353_setup(struct serial_private *priv, #define PCI_VENDOR_ID_AGESTAR 0x5372 #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 #define PCI_VENDOR_ID_ASIX 0x9710 -#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019 #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 +#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 +#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ @@ -1954,6 +1967,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_xr17v35x_setup, }, /* + * Broadcom TruManage (NetXtreme) + */ + { + .vendor = PCI_VENDOR_ID_BROADCOM, + .device = PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_brcm_trumanage_setup, + }, + + /* * Default "match everything" terminator entry */ { @@ -2148,6 +2172,7 @@ enum pci_board_num_t { pbn_ce4100_1_115200, pbn_omegapci, pbn_NETMOS9900_2s_115200, + pbn_brcm_trumanage, }; /* @@ -2246,7 +2271,7 @@ static struct pciserial_board pci_boards[] = { [pbn_b0_8_1152000_200] = { .flags = FL_BASE0, - .num_ports = 2, + .num_ports = 8, .base_baud = 1152000, .uart_offset = 0x200, }, @@ -2892,6 +2917,12 @@ static struct pciserial_board pci_boards[] = { .num_ports = 2, .base_baud = 115200, }, + [pbn_brcm_trumanage] = { + .flags = FL_BASE0, + .num_ports = 1, + .reg_shift = 2, + .base_baud = 115200, + }, }; static const struct pci_device_id blacklist[] = { @@ -4471,6 +4502,13 @@ static struct pci_device_id serial_pci_tbl[] = { pbn_omegapci }, /* + * Broadcom TruManage + */ + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_brcm_trumanage }, + + /* * AgeStar as-prs2-009 */ { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375, diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 675d94ab0af..8cb6d8d66a1 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -637,6 +637,7 @@ static void ifx_port_shutdown(struct tty_port *port) clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); mrdy_set_low(ifx_dev); + del_timer(&ifx_dev->spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); tasklet_kill(&ifx_dev->io_work_tasklet); } @@ -810,7 +811,8 @@ static void ifx_spi_io(unsigned long data) ifx_dev->spi_xfer.cs_change = 0; ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; /* ifx_dev->spi_xfer.speed_hz = 390625; */ - ifx_dev->spi_xfer.bits_per_word = spi_bpw; + ifx_dev->spi_xfer.bits_per_word = + ifx_dev->spi_dev->bits_per_word; ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 6db23b035ef..e55615eb34a 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -253,7 +253,7 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s) struct circ_buf *xmit = &s->port.state->xmit; if (auart_dma_enabled(s)) { - int i = 0; + u32 i = 0; int size; void *buffer = s->tx_dma_buf; @@ -412,10 +412,12 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl) u32 ctrl = readl(u->membase + AUART_CTRL2); - ctrl &= ~AUART_CTRL2_RTSEN; + ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS); if (mctrl & TIOCM_RTS) { if (tty_port_cts_enabled(&u->state->port)) ctrl |= AUART_CTRL2_RTSEN; + else + ctrl |= AUART_CTRL2_RTS; } s->ctrl = mctrl; diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 12e5249d053..e514b3a4dc5 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1006,7 +1006,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port, ucon &= ucon_mask; wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); /* reset both fifos */ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 8fd181436a6..d5ed9f61300 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -604,7 +604,7 @@ static int vt8500_serial_probe(struct platform_device *pdev) vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0); - if (vt8500_port->clk) { + if (!IS_ERR(vt8500_port->clk)) { vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk); } else { /* use the default of 24Mhz if not specified and warn */ diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2e43b332aae..2fdd767f8fe 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1605,6 +1605,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) if (epnum == 0 || epnum == 1) { dep->endpoint.maxpacket = 512; + dep->endpoint.maxburst = 1; dep->endpoint.ops = &dwc3_gadget_ep0_ops; if (!epnum) dwc->gadget.ep0 = &dep->endpoint; diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 4a6961c517f..8c2f2512114 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1153,15 +1153,15 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts) pr_err("%s: unmapped value: %lu\n", opts, value); return -EINVAL; } - } - else if (!memcmp(opts, "gid", 3)) + } else if (!memcmp(opts, "gid", 3)) { data->perms.gid = make_kgid(current_user_ns(), value); if (!gid_valid(data->perms.gid)) { pr_err("%s: unmapped value: %lu\n", opts, value); return -EINVAL; } - else + } else { goto invalid; + } break; default: diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index 1b0f086426b..d3bd7b095ba 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c @@ -18,14 +18,13 @@ #include <linux/platform_device.h> #include <linux/io.h> -#include <mach/hardware.h> - static struct clk *mxc_ahb_clk; static struct clk *mxc_per_clk; static struct clk *mxc_ipg_clk; /* workaround ENGcm09152 for i.MX35 */ -#define USBPHYCTRL_OTGBASE_OFFSET 0x608 +#define MX35_USBPHYCTRL_OFFSET 0x600 +#define USBPHYCTRL_OTGBASE_OFFSET 0x8 #define USBPHYCTRL_EVDO (1 << 23) int fsl_udc_clk_init(struct platform_device *pdev) @@ -59,7 +58,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) clk_prepare_enable(mxc_per_clk); /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ - if (!cpu_is_mx51()) { + if (!strcmp(pdev->id_entry->name, "imx-udc-mx27")) { freq = clk_get_rate(mxc_per_clk); if (pdata->phy_mode != FSL_USB2_PHY_ULPI && (freq < 59999000 || freq > 60001000)) { @@ -79,27 +78,40 @@ eclkrate: return ret; } -void fsl_udc_clk_finalize(struct platform_device *pdev) +int fsl_udc_clk_finalize(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - if (cpu_is_mx35()) { - unsigned int v; + int ret = 0; - /* workaround ENGcm09152 for i.MX35 */ - if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { - v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + - USBPHYCTRL_OTGBASE_OFFSET)); - writel(v | USBPHYCTRL_EVDO, - MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + - USBPHYCTRL_OTGBASE_OFFSET)); + /* workaround ENGcm09152 for i.MX35 */ + if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { + unsigned int v; + struct resource *res = platform_get_resource + (pdev, IORESOURCE_MEM, 0); + void __iomem *phy_regs = ioremap(res->start + + MX35_USBPHYCTRL_OFFSET, 512); + if (!phy_regs) { + dev_err(&pdev->dev, "ioremap for phy address fails\n"); + ret = -EINVAL; + goto ioremap_err; } + + v = readl(phy_regs + USBPHYCTRL_OTGBASE_OFFSET); + writel(v | USBPHYCTRL_EVDO, + phy_regs + USBPHYCTRL_OTGBASE_OFFSET); + + iounmap(phy_regs); } + +ioremap_err: /* ULPI transceivers don't need usbpll */ if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { clk_disable_unprepare(mxc_per_clk); mxc_per_clk = NULL; } + + return ret; } void fsl_udc_clk_release(void) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index c19f7f13790..667275cb7ba 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -41,6 +41,7 @@ #include <linux/fsl_devices.h> #include <linux/dmapool.h> #include <linux/delay.h> +#include <linux/of_device.h> #include <asm/byteorder.h> #include <asm/io.h> @@ -2438,11 +2439,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) unsigned int i; u32 dccparams; - if (strcmp(pdev->name, driver_name)) { - VDBG("Wrong device"); - return -ENODEV; - } - udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); if (udc_controller == NULL) { ERR("malloc udc failed\n"); @@ -2547,7 +2543,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev) dr_controller_setup(udc_controller); } - fsl_udc_clk_finalize(pdev); + ret = fsl_udc_clk_finalize(pdev); + if (ret) + goto err_free_irq; /* Setup gadget structure */ udc_controller->gadget.ops = &fsl_gadget_ops; @@ -2756,22 +2754,32 @@ static int fsl_udc_otg_resume(struct device *dev) return fsl_udc_resume(NULL); } - /*------------------------------------------------------------------------- Register entry point for the peripheral controller driver --------------------------------------------------------------------------*/ - +static const struct platform_device_id fsl_udc_devtype[] = { + { + .name = "imx-udc-mx27", + }, { + .name = "imx-udc-mx51", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, fsl_udc_devtype); static struct platform_driver udc_driver = { - .remove = __exit_p(fsl_udc_remove), + .remove = __exit_p(fsl_udc_remove), + /* Just for FSL i.mx SoC currently */ + .id_table = fsl_udc_devtype, /* these suspend and resume are not usb suspend and resume */ - .suspend = fsl_udc_suspend, - .resume = fsl_udc_resume, - .driver = { - .name = (char *)driver_name, - .owner = THIS_MODULE, - /* udc suspend/resume called from OTG driver */ - .suspend = fsl_udc_otg_suspend, - .resume = fsl_udc_otg_resume, + .suspend = fsl_udc_suspend, + .resume = fsl_udc_resume, + .driver = { + .name = (char *)driver_name, + .owner = THIS_MODULE, + /* udc suspend/resume called from OTG driver */ + .suspend = fsl_udc_otg_suspend, + .resume = fsl_udc_otg_resume, }, }; diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index f61a967f708..c6703bb07b2 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -592,15 +592,16 @@ static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep) struct platform_device; #ifdef CONFIG_ARCH_MXC int fsl_udc_clk_init(struct platform_device *pdev); -void fsl_udc_clk_finalize(struct platform_device *pdev); +int fsl_udc_clk_finalize(struct platform_device *pdev); void fsl_udc_clk_release(void); #else static inline int fsl_udc_clk_init(struct platform_device *pdev) { return 0; } -static inline void fsl_udc_clk_finalize(struct platform_device *pdev) +static inline int fsl_udc_clk_finalize(struct platform_device *pdev) { + return 0; } static inline void fsl_udc_clk_release(void) { diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index d6bb128ce21..3a21c5d683c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -148,7 +148,7 @@ config USB_EHCI_FSL Variation of ARC USB block used in some Freescale chips. config USB_EHCI_MXC - bool "Support for Freescale i.MX on-chip EHCI USB controller" + tristate "Support for Freescale i.MX on-chip EHCI USB controller" depends on USB_EHCI_HCD && ARCH_MXC select USB_EHCI_ROOT_HUB_TT ---help--- diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 1eb4c3006e9..001fbff2fde 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_PCI) += pci-quirks.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o +obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c97503bb0b0..09537b2f100 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -74,10 +74,6 @@ static const char hcd_name [] = "ehci_hcd"; #undef VERBOSE_DEBUG #undef EHCI_URB_TRACE -#ifdef DEBUG -#define EHCI_STATS -#endif - /* magic numbers that can affect system performance */ #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ @@ -1250,11 +1246,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_fsl_driver #endif -#ifdef CONFIG_USB_EHCI_MXC -#include "ehci-mxc.c" -#define PLATFORM_DRIVER ehci_mxc_driver -#endif - #ifdef CONFIG_USB_EHCI_SH #include "ehci-sh.c" #define PLATFORM_DRIVER ehci_hcd_sh_driver @@ -1352,7 +1343,8 @@ MODULE_LICENSE ("GPL"); #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ - !defined(CONFIG_USB_CHIPIDEA_HOST) && \ + !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ + !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index ec7f5d2c90d..dedb80bb8d4 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -17,75 +17,38 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/usb/otg.h> #include <linux/usb/ulpi.h> #include <linux/slab.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> #include <linux/platform_data/usb-ehci-mxc.h> #include <asm/mach-types.h> +#include "ehci.h" + +#define DRIVER_DESC "Freescale On-Chip EHCI Host driver" + +static const char hcd_name[] = "ehci-mxc"; + #define ULPI_VIEWPORT_OFFSET 0x170 struct ehci_mxc_priv { struct clk *usbclk, *ahbclk, *phyclk; - struct usb_hcd *hcd; }; -/* called during probe() after chip reset completes */ -static int ehci_mxc_setup(struct usb_hcd *hcd) -{ - hcd->has_tt = 1; - - return ehci_setup(hcd); -} +static struct hc_driver __read_mostly ehci_mxc_hc_driver; -static const struct hc_driver ehci_mxc_hc_driver = { - .description = hcd_name, - .product_desc = "Freescale On-Chip EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_USB2 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ehci_mxc_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = { + .extra_priv_size = sizeof(struct ehci_mxc_priv), }; static int ehci_mxc_drv_probe(struct platform_device *pdev) @@ -112,12 +75,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (!hcd) return -ENOMEM; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto err_alloc; - } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "Found HC with no register addr. Check setup!\n"); @@ -135,6 +92,10 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) goto err_alloc; } + hcd->has_tt = 1; + ehci = hcd_to_ehci(hcd); + priv = (struct ehci_mxc_priv *) ehci->priv; + /* enable clocks */ priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(priv->usbclk)) { @@ -169,8 +130,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) mdelay(10); } - ehci = hcd_to_ehci(hcd); - /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; ehci->regs = hcd->regs + 0x100 + @@ -198,8 +157,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) } } - priv->hcd = hcd; - platform_set_drvdata(pdev, priv); + platform_set_drvdata(pdev, hcd); ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) @@ -244,8 +202,11 @@ err_alloc: static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) { struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; - struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); - struct usb_hcd *hcd = priv->hcd; + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv; + + usb_remove_hcd(hcd); if (pdata && pdata->exit) pdata->exit(pdev); @@ -253,23 +214,20 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) if (pdata->otg) usb_phy_shutdown(pdata->otg); - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - platform_set_drvdata(pdev, NULL); - clk_disable_unprepare(priv->usbclk); clk_disable_unprepare(priv->ahbclk); if (priv->phyclk) clk_disable_unprepare(priv->phyclk); + usb_put_hcd(hcd); + platform_set_drvdata(pdev, NULL); return 0; } static void ehci_mxc_drv_shutdown(struct platform_device *pdev) { - struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); - struct usb_hcd *hcd = priv->hcd; + struct usb_hcd *hcd = platform_get_drvdata(pdev); if (hcd->driver->shutdown) hcd->driver->shutdown(hcd); @@ -279,9 +237,31 @@ MODULE_ALIAS("platform:mxc-ehci"); static struct platform_driver ehci_mxc_driver = { .probe = ehci_mxc_drv_probe, - .remove = __exit_p(ehci_mxc_drv_remove), + .remove = ehci_mxc_drv_remove, .shutdown = ehci_mxc_drv_shutdown, .driver = { .name = "mxc-ehci", }, }; + +static int __init ehci_mxc_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides); + return platform_driver_register(&ehci_mxc_driver); +} +module_init(ehci_mxc_init); + +static void __exit ehci_mxc_cleanup(void) +{ + platform_driver_unregister(&ehci_mxc_driver); +} +module_exit(ehci_mxc_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Sascha Hauer"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 9dadc7118d6..36c3a821059 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -38,6 +38,10 @@ typedef __u16 __bitwise __hc16; #endif /* statistics can be kept for tuning/monitoring */ +#ifdef DEBUG +#define EHCI_STATS +#endif + struct ehci_stats { /* irq usage */ unsigned long normal; @@ -221,6 +225,9 @@ struct ehci_hcd { /* one per controller */ #ifdef DEBUG struct dentry *debug_dir; #endif + + /* platform-specific data -- must come last */ + unsigned long priv[0] __aligned(sizeof(s64)); }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4b9e9aba266..4f64d24eebc 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) return IRQ_NONE; uhci_writew(uhci, status, USBSTS); /* Clear it */ + spin_lock(&uhci->lock); + if (unlikely(!uhci->is_initialized)) /* not yet configured */ + goto done; + if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { if (status & USBSTS_HSE) dev_err(uhci_dev(uhci), "host system error, " @@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) dev_err(uhci_dev(uhci), "host controller process " "error, something bad happened!\n"); if (status & USBSTS_HCH) { - spin_lock(&uhci->lock); if (uhci->rh_state >= UHCI_RH_RUNNING) { dev_err(uhci_dev(uhci), "host controller halted, " @@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) * pending unlinks */ mod_timer(&hcd->rh_timer, jiffies); } - spin_unlock(&uhci->lock); } } - if (status & USBSTS_RD) + if (status & USBSTS_RD) { + spin_unlock(&uhci->lock); usb_hcd_poll_rh_status(hcd); - else { - spin_lock(&uhci->lock); + } else { uhci_scan_schedule(uhci); + done: spin_unlock(&uhci->lock); } @@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd) */ mb(); + spin_lock_irq(&uhci->lock); configure_hc(uhci); uhci->is_initialized = 1; - spin_lock_irq(&uhci->lock); start_rh(uhci); spin_unlock_irq(&uhci->lock); return 0; diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 0968dd7a859..f522000e8f0 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -105,7 +105,7 @@ static void cppi_reset_tx(struct cppi_tx_stateram __iomem *tx, u32 ptr) musb_writel(&tx->tx_complete, 0, ptr); } -static void __init cppi_pool_init(struct cppi *cppi, struct cppi_channel *c) +static void cppi_pool_init(struct cppi *cppi, struct cppi_channel *c) { int j; @@ -150,7 +150,7 @@ static void cppi_pool_free(struct cppi_channel *c) c->last_processed = NULL; } -static int __init cppi_controller_start(struct dma_controller *c) +static int cppi_controller_start(struct dma_controller *c) { struct cppi *controller; void __iomem *tibase; diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 58184f3de68..82afc4d6a32 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -530,6 +530,9 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, wait_queue_t wait; unsigned long flags; + if (!tty) + return; + if (!timeout) timeout = (HZ * EDGE_CLOSING_WAIT)/100; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 478adcfcdf2..0d9dac9e7f9 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -449,6 +449,10 @@ static void option_instat_callback(struct urb *urb); #define PETATEL_VENDOR_ID 0x1ff4 #define PETATEL_PRODUCT_NP10T 0x600e +/* TP-LINK Incorporated products */ +#define TPLINK_VENDOR_ID 0x2357 +#define TPLINK_PRODUCT_MA180 0x0201 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -930,7 +934,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, @@ -1311,6 +1316,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, + { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c index 4362d9e7baa..f72323ef618 100644 --- a/drivers/vfio/pci/vfio_pci_rdwr.c +++ b/drivers/vfio/pci/vfio_pci_rdwr.c @@ -240,17 +240,17 @@ ssize_t vfio_pci_mem_readwrite(struct vfio_pci_device *vdev, char __user *buf, filled = 1; } else { /* Drop writes, fill reads with FF */ + filled = min((size_t)(x_end - pos), count); if (!iswrite) { char val = 0xFF; size_t i; - for (i = 0; i < x_end - pos; i++) { + for (i = 0; i < filled; i++) { if (put_user(val, buf + i)) goto out; } } - filled = x_end - pos; } count -= filled; diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 12526787a7c..0abf2bf2083 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -139,6 +139,7 @@ struct imxfb_info { struct clk *clk_ahb; struct clk *clk_per; enum imxfb_type devtype; + bool enabled; /* * These are the addresses we mapped @@ -536,6 +537,10 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi) static void imxfb_enable_controller(struct imxfb_info *fbi) { + + if (fbi->enabled) + return; + pr_debug("Enabling LCD controller\n"); writel(fbi->screen_dma, fbi->regs + LCDC_SSA); @@ -556,6 +561,7 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) clk_prepare_enable(fbi->clk_ipg); clk_prepare_enable(fbi->clk_ahb); clk_prepare_enable(fbi->clk_per); + fbi->enabled = true; if (fbi->backlight_power) fbi->backlight_power(1); @@ -565,6 +571,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) static void imxfb_disable_controller(struct imxfb_info *fbi) { + if (!fbi->enabled) + return; + pr_debug("Disabling LCD controller\n"); if (fbi->backlight_power) @@ -575,6 +584,7 @@ static void imxfb_disable_controller(struct imxfb_info *fbi) clk_disable_unprepare(fbi->clk_per); clk_disable_unprepare(fbi->clk_ipg); clk_disable_unprepare(fbi->clk_ahb); + fbi->enabled = false; writel(0, fbi->regs + LCDC_RMCR); } @@ -729,6 +739,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev) memset(fbi, 0, sizeof(struct imxfb_info)); + fbi->devtype = pdev->id_entry->driver_data; + strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); info->fix.type = FB_TYPE_PACKED_PIXELS; @@ -789,7 +801,6 @@ static int __init imxfb_probe(struct platform_device *pdev) return -ENOMEM; fbi = info->par; - fbi->devtype = pdev->id_entry->driver_data; if (!fb_mode) fb_mode = pdata->mode[0].mode.name; diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 4dcfced107f..084041d42c9 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c @@ -25,10 +25,10 @@ static void disable_hotplug_cpu(int cpu) static int vcpu_online(unsigned int cpu) { int err; - char dir[32], state[32]; + char dir[16], state[16]; sprintf(dir, "cpu/%u", cpu); - err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state); + err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state); if (err != 1) { if (!xen_initial_domain()) printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 2e22df2f7a3..3c8803feba2 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -56,10 +56,15 @@ MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped by " static atomic_t pages_mapped = ATOMIC_INIT(0); static int use_ptemod; +#define populate_freeable_maps use_ptemod struct gntdev_priv { + /* maps with visible offsets in the file descriptor */ struct list_head maps; - /* lock protects maps from concurrent changes */ + /* maps that are not visible; will be freed on munmap. + * Only populated if populate_freeable_maps == 1 */ + struct list_head freeable_maps; + /* lock protects maps and freeable_maps */ spinlock_t lock; struct mm_struct *mm; struct mmu_notifier mn; @@ -193,7 +198,7 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, return NULL; } -static void gntdev_put_map(struct grant_map *map) +static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map) { if (!map) return; @@ -208,6 +213,12 @@ static void gntdev_put_map(struct grant_map *map) evtchn_put(map->notify.event); } + if (populate_freeable_maps && priv) { + spin_lock(&priv->lock); + list_del(&map->next); + spin_unlock(&priv->lock); + } + if (map->pages && !use_ptemod) unmap_grant_pages(map, 0, map->count); gntdev_free_map(map); @@ -301,17 +312,10 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) { int pgno = (map->notify.addr >> PAGE_SHIFT); - if (pgno >= offset && pgno < offset + pages && use_ptemod) { - void __user *tmp = (void __user *) - map->vma->vm_start + map->notify.addr; - err = copy_to_user(tmp, &err, 1); - if (err) - return -EFAULT; - map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; - } else if (pgno >= offset && pgno < offset + pages) { - uint8_t *tmp = kmap(map->pages[pgno]); + if (pgno >= offset && pgno < offset + pages) { + /* No need for kmap, pages are in lowmem */ + uint8_t *tmp = pfn_to_kaddr(page_to_pfn(map->pages[pgno])); tmp[map->notify.addr & (PAGE_SIZE-1)] = 0; - kunmap(map->pages[pgno]); map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; } } @@ -376,11 +380,24 @@ static void gntdev_vma_open(struct vm_area_struct *vma) static void gntdev_vma_close(struct vm_area_struct *vma) { struct grant_map *map = vma->vm_private_data; + struct file *file = vma->vm_file; + struct gntdev_priv *priv = file->private_data; pr_debug("gntdev_vma_close %p\n", vma); - map->vma = NULL; + if (use_ptemod) { + /* It is possible that an mmu notifier could be running + * concurrently, so take priv->lock to ensure that the vma won't + * vanishing during the unmap_grant_pages call, since we will + * spin here until that completes. Such a concurrent call will + * not do any unmapping, since that has been done prior to + * closing the vma, but it may still iterate the unmap_ops list. + */ + spin_lock(&priv->lock); + map->vma = NULL; + spin_unlock(&priv->lock); + } vma->vm_private_data = NULL; - gntdev_put_map(map); + gntdev_put_map(priv, map); } static struct vm_operations_struct gntdev_vmops = { @@ -390,33 +407,43 @@ static struct vm_operations_struct gntdev_vmops = { /* ------------------------------------------------------------------ */ +static void unmap_if_in_range(struct grant_map *map, + unsigned long start, unsigned long end) +{ + unsigned long mstart, mend; + int err; + + if (!map->vma) + return; + if (map->vma->vm_start >= end) + return; + if (map->vma->vm_end <= start) + return; + mstart = max(start, map->vma->vm_start); + mend = min(end, map->vma->vm_end); + pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", + map->index, map->count, + map->vma->vm_start, map->vma->vm_end, + start, end, mstart, mend); + err = unmap_grant_pages(map, + (mstart - map->vma->vm_start) >> PAGE_SHIFT, + (mend - mstart) >> PAGE_SHIFT); + WARN_ON(err); +} + static void mn_invl_range_start(struct mmu_notifier *mn, struct mm_struct *mm, unsigned long start, unsigned long end) { struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); struct grant_map *map; - unsigned long mstart, mend; - int err; spin_lock(&priv->lock); list_for_each_entry(map, &priv->maps, next) { - if (!map->vma) - continue; - if (map->vma->vm_start >= end) - continue; - if (map->vma->vm_end <= start) - continue; - mstart = max(start, map->vma->vm_start); - mend = min(end, map->vma->vm_end); - pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", - map->index, map->count, - map->vma->vm_start, map->vma->vm_end, - start, end, mstart, mend); - err = unmap_grant_pages(map, - (mstart - map->vma->vm_start) >> PAGE_SHIFT, - (mend - mstart) >> PAGE_SHIFT); - WARN_ON(err); + unmap_if_in_range(map, start, end); + } + list_for_each_entry(map, &priv->freeable_maps, next) { + unmap_if_in_range(map, start, end); } spin_unlock(&priv->lock); } @@ -445,6 +472,15 @@ static void mn_release(struct mmu_notifier *mn, err = unmap_grant_pages(map, /* offset */ 0, map->count); WARN_ON(err); } + list_for_each_entry(map, &priv->freeable_maps, next) { + if (!map->vma) + continue; + pr_debug("map %d+%d (%lx %lx)\n", + map->index, map->count, + map->vma->vm_start, map->vma->vm_end); + err = unmap_grant_pages(map, /* offset */ 0, map->count); + WARN_ON(err); + } spin_unlock(&priv->lock); } @@ -466,6 +502,7 @@ static int gntdev_open(struct inode *inode, struct file *flip) return -ENOMEM; INIT_LIST_HEAD(&priv->maps); + INIT_LIST_HEAD(&priv->freeable_maps); spin_lock_init(&priv->lock); if (use_ptemod) { @@ -500,8 +537,9 @@ static int gntdev_release(struct inode *inode, struct file *flip) while (!list_empty(&priv->maps)) { map = list_entry(priv->maps.next, struct grant_map, next); list_del(&map->next); - gntdev_put_map(map); + gntdev_put_map(NULL /* already removed */, map); } + WARN_ON(!list_empty(&priv->freeable_maps)); if (use_ptemod) mmu_notifier_unregister(&priv->mn, priv->mm); @@ -529,14 +567,14 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) { pr_debug("can't map: over limit\n"); - gntdev_put_map(map); + gntdev_put_map(NULL, map); return err; } if (copy_from_user(map->grants, &u->refs, sizeof(map->grants[0]) * op.count) != 0) { - gntdev_put_map(map); - return err; + gntdev_put_map(NULL, map); + return -EFAULT; } spin_lock(&priv->lock); @@ -565,11 +603,13 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); if (map) { list_del(&map->next); + if (populate_freeable_maps) + list_add_tail(&map->next, &priv->freeable_maps); err = 0; } spin_unlock(&priv->lock); if (map) - gntdev_put_map(map); + gntdev_put_map(priv, map); return err; } @@ -579,25 +619,31 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv, struct ioctl_gntdev_get_offset_for_vaddr op; struct vm_area_struct *vma; struct grant_map *map; + int rv = -EINVAL; if (copy_from_user(&op, u, sizeof(op)) != 0) return -EFAULT; pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr); + down_read(¤t->mm->mmap_sem); vma = find_vma(current->mm, op.vaddr); if (!vma || vma->vm_ops != &gntdev_vmops) - return -EINVAL; + goto out_unlock; map = vma->vm_private_data; if (!map) - return -EINVAL; + goto out_unlock; op.offset = map->index << PAGE_SHIFT; op.count = map->count; + rv = 0; - if (copy_to_user(u, &op, sizeof(op)) != 0) + out_unlock: + up_read(¤t->mm->mmap_sem); + + if (rv == 0 && copy_to_user(u, &op, sizeof(op)) != 0) return -EFAULT; - return 0; + return rv; } static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) @@ -778,7 +824,7 @@ out_unlock_put: out_put_map: if (use_ptemod) map->vma = NULL; - gntdev_put_map(map); + gntdev_put_map(priv, map); return err; } diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 7038de53652..157c0ccda3e 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -56,10 +56,6 @@ /* External tools reserve first few grant table entries. */ #define NR_RESERVED_ENTRIES 8 #define GNTTAB_LIST_END 0xffffffff -#define GREFS_PER_GRANT_FRAME \ -(grant_table_version == 1 ? \ -(PAGE_SIZE / sizeof(struct grant_entry_v1)) : \ -(PAGE_SIZE / sizeof(union grant_entry_v2))) static grant_ref_t **gnttab_list; static unsigned int nr_grant_frames; @@ -154,6 +150,7 @@ static struct gnttab_ops *gnttab_interface; static grant_status_t *grstatus; static int grant_table_version; +static int grefs_per_grant_frame; static struct gnttab_free_callback *gnttab_free_callback_list; @@ -767,12 +764,14 @@ static int grow_gnttab_list(unsigned int more_frames) unsigned int new_nr_grant_frames, extra_entries, i; unsigned int nr_glist_frames, new_nr_glist_frames; + BUG_ON(grefs_per_grant_frame == 0); + new_nr_grant_frames = nr_grant_frames + more_frames; - extra_entries = more_frames * GREFS_PER_GRANT_FRAME; + extra_entries = more_frames * grefs_per_grant_frame; - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; new_nr_glist_frames = - (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); if (!gnttab_list[i]) @@ -780,12 +779,12 @@ static int grow_gnttab_list(unsigned int more_frames) } - for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; - i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) + for (i = grefs_per_grant_frame * nr_grant_frames; + i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++) gnttab_entry(i) = i + 1; gnttab_entry(i) = gnttab_free_head; - gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; + gnttab_free_head = grefs_per_grant_frame * nr_grant_frames; gnttab_free_count += extra_entries; nr_grant_frames = new_nr_grant_frames; @@ -957,7 +956,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs); static unsigned nr_status_frames(unsigned nr_grant_frames) { - return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; + BUG_ON(grefs_per_grant_frame == 0); + return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP; } static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) @@ -1115,6 +1115,7 @@ static void gnttab_request_version(void) rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); if (rc == 0 && gsv.version == 2) { grant_table_version = 2; + grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2); gnttab_interface = &gnttab_v2_ops; } else if (grant_table_version == 2) { /* @@ -1127,17 +1128,17 @@ static void gnttab_request_version(void) panic("we need grant tables version 2, but only version 1 is available"); } else { grant_table_version = 1; + grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1); gnttab_interface = &gnttab_v1_ops; } printk(KERN_INFO "Grant tables using version %d layout.\n", grant_table_version); } -int gnttab_resume(void) +static int gnttab_setup(void) { unsigned int max_nr_gframes; - gnttab_request_version(); max_nr_gframes = gnttab_max_grant_frames(); if (max_nr_gframes < nr_grant_frames) return -ENOSYS; @@ -1160,6 +1161,12 @@ int gnttab_resume(void) return 0; } +int gnttab_resume(void) +{ + gnttab_request_version(); + return gnttab_setup(); +} + int gnttab_suspend(void) { gnttab_interface->unmap_frames(); @@ -1171,9 +1178,10 @@ static int gnttab_expand(unsigned int req_entries) int rc; unsigned int cur, extra; + BUG_ON(grefs_per_grant_frame == 0); cur = nr_grant_frames; - extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / - GREFS_PER_GRANT_FRAME); + extra = ((req_entries + (grefs_per_grant_frame-1)) / + grefs_per_grant_frame); if (cur + extra > gnttab_max_grant_frames()) return -ENOSPC; @@ -1191,21 +1199,23 @@ int gnttab_init(void) unsigned int nr_init_grefs; int ret; + gnttab_request_version(); nr_grant_frames = 1; boot_max_nr_grant_frames = __max_nr_grant_frames(); /* Determine the maximum number of frames required for the * grant reference free list on the current hypervisor. */ + BUG_ON(grefs_per_grant_frame == 0); max_nr_glist_frames = (boot_max_nr_grant_frames * - GREFS_PER_GRANT_FRAME / RPP); + grefs_per_grant_frame / RPP); gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), GFP_KERNEL); if (gnttab_list == NULL) return -ENOMEM; - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; for (i = 0; i < nr_glist_frames; i++) { gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); if (gnttab_list[i] == NULL) { @@ -1214,12 +1224,12 @@ int gnttab_init(void) } } - if (gnttab_resume() < 0) { + if (gnttab_setup() < 0) { ret = -ENODEV; goto ini_nomem; } - nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; + nr_init_grefs = nr_grant_frames * grefs_per_grant_frame; for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) gnttab_entry(i) = i + 1; diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 0bbbccbb1f1..ca2b00e9d55 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -199,9 +199,6 @@ static long privcmd_ioctl_mmap(void __user *udata) LIST_HEAD(pagelist); struct mmap_mfn_state state; - if (!xen_initial_domain()) - return -EPERM; - /* We only support privcmd_ioctl_mmap_batch for auto translated. */ if (xen_feature(XENFEAT_auto_translated_physmap)) return -ENOSYS; @@ -261,11 +258,12 @@ struct mmap_batch_state { * -ENOENT if at least 1 -ENOENT has happened. */ int global_error; - /* An array for individual errors */ - int *err; + int version; /* User-space mfn array to store errors in the second pass for V1. */ xen_pfn_t __user *user_mfn; + /* User-space int array to store errors in the second pass for V2. */ + int __user *user_err; }; /* auto translated dom0 note: if domU being created is PV, then mfn is @@ -288,7 +286,19 @@ static int mmap_batch_fn(void *data, void *state) &cur_page); /* Store error code for second pass. */ - *(st->err++) = ret; + if (st->version == 1) { + if (ret < 0) { + /* + * V1 encodes the error codes in the 32bit top nibble of the + * mfn (with its known limitations vis-a-vis 64 bit callers). + */ + *mfnp |= (ret == -ENOENT) ? + PRIVCMD_MMAPBATCH_PAGED_ERROR : + PRIVCMD_MMAPBATCH_MFN_ERROR; + } + } else { /* st->version == 2 */ + *((int *) mfnp) = ret; + } /* And see if it affects the global_error. */ if (ret < 0) { @@ -305,20 +315,25 @@ static int mmap_batch_fn(void *data, void *state) return 0; } -static int mmap_return_errors_v1(void *data, void *state) +static int mmap_return_errors(void *data, void *state) { - xen_pfn_t *mfnp = data; struct mmap_batch_state *st = state; - int err = *(st->err++); - /* - * V1 encodes the error codes in the 32bit top nibble of the - * mfn (with its known limitations vis-a-vis 64 bit callers). - */ - *mfnp |= (err == -ENOENT) ? - PRIVCMD_MMAPBATCH_PAGED_ERROR : - PRIVCMD_MMAPBATCH_MFN_ERROR; - return __put_user(*mfnp, st->user_mfn++); + if (st->version == 1) { + xen_pfn_t mfnp = *((xen_pfn_t *) data); + if (mfnp & PRIVCMD_MMAPBATCH_MFN_ERROR) + return __put_user(mfnp, st->user_mfn++); + else + st->user_mfn++; + } else { /* st->version == 2 */ + int err = *((int *) data); + if (err) + return __put_user(err, st->user_err++); + else + st->user_err++; + } + + return 0; } /* Allocate pfns that are then mapped with gmfns from foreign domid. Update @@ -357,12 +372,8 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) struct vm_area_struct *vma; unsigned long nr_pages; LIST_HEAD(pagelist); - int *err_array = NULL; struct mmap_batch_state state; - if (!xen_initial_domain()) - return -EPERM; - switch (version) { case 1: if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch))) @@ -396,10 +407,12 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) goto out; } - err_array = kcalloc(m.num, sizeof(int), GFP_KERNEL); - if (err_array == NULL) { - ret = -ENOMEM; - goto out; + if (version == 2) { + /* Zero error array now to only copy back actual errors. */ + if (clear_user(m.err, sizeof(int) * m.num)) { + ret = -EFAULT; + goto out; + } } down_write(&mm->mmap_sem); @@ -427,7 +440,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) state.va = m.addr; state.index = 0; state.global_error = 0; - state.err = err_array; + state.version = version; /* mmap_batch_fn guarantees ret == 0 */ BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t), @@ -435,21 +448,14 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) up_write(&mm->mmap_sem); - if (version == 1) { - if (state.global_error) { - /* Write back errors in second pass. */ - state.user_mfn = (xen_pfn_t *)m.arr; - state.err = err_array; - ret = traverse_pages(m.num, sizeof(xen_pfn_t), - &pagelist, mmap_return_errors_v1, &state); - } else - ret = 0; - - } else if (version == 2) { - ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); - if (ret) - ret = -EFAULT; - } + if (state.global_error) { + /* Write back errors in second pass. */ + state.user_mfn = (xen_pfn_t *)m.arr; + state.user_err = m.err; + ret = traverse_pages(m.num, sizeof(xen_pfn_t), + &pagelist, mmap_return_errors, &state); + } else + ret = 0; /* If we have not had any EFAULT-like global errors then set the global * error to -ENOENT if necessary. */ @@ -457,7 +463,6 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) ret = -ENOENT; out: - kfree(err_array); free_page_list(&pagelist); return ret; diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h index a7def010eba..f72af87640e 100644 --- a/drivers/xen/xen-pciback/pciback.h +++ b/drivers/xen/xen-pciback/pciback.h @@ -124,7 +124,7 @@ static inline int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, struct pci_dev *dev) { - if (xen_pcibk_backend && xen_pcibk_backend->free) + if (xen_pcibk_backend && xen_pcibk_backend->release) return xen_pcibk_backend->release(pdev, dev); } |