diff options
Diffstat (limited to 'drivers')
157 files changed, 1792 insertions, 1004 deletions
diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 467a60235370..7e9359611d69 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -367,14 +367,19 @@ int ivpu_boot(struct ivpu_device *vdev) return 0; } -int ivpu_shutdown(struct ivpu_device *vdev) +void ivpu_prepare_for_reset(struct ivpu_device *vdev) { - int ret; - ivpu_hw_irq_disable(vdev); disable_irq(vdev->irq); ivpu_ipc_disable(vdev); ivpu_mmu_disable(vdev); +} + +int ivpu_shutdown(struct ivpu_device *vdev) +{ + int ret; + + ivpu_prepare_for_reset(vdev); ret = ivpu_hw_power_down(vdev); if (ret) diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 03b3d6532fb6..2adc349126bb 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -151,6 +151,7 @@ void ivpu_file_priv_put(struct ivpu_file_priv **link); int ivpu_boot(struct ivpu_device *vdev); int ivpu_shutdown(struct ivpu_device *vdev); +void ivpu_prepare_for_reset(struct ivpu_device *vdev); static inline u8 ivpu_revision(struct ivpu_device *vdev) { diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 0191cf8e5964..a277bbae78fc 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -220,8 +220,7 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) if (ret) return ret; - fw->mem = ivpu_bo_alloc_internal(vdev, fw->runtime_addr, fw->runtime_size, - DRM_IVPU_BO_CACHED | DRM_IVPU_BO_NOSNOOP); + fw->mem = ivpu_bo_alloc_internal(vdev, fw->runtime_addr, fw->runtime_size, DRM_IVPU_BO_WC); if (!fw->mem) { ivpu_err(vdev, "Failed to allocate firmware runtime memory\n"); return -ENOMEM; @@ -331,7 +330,7 @@ int ivpu_fw_load(struct ivpu_device *vdev) memset(start, 0, size); } - clflush_cache_range(fw->mem->kvaddr, fw->mem->base.size); + wmb(); /* Flush WC buffers after writing fw->mem */ return 0; } @@ -433,7 +432,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params if (!ivpu_fw_is_cold_boot(vdev)) { boot_params->save_restore_ret_address = 0; vdev->pm->is_warmboot = true; - clflush_cache_range(vdev->fw->mem->kvaddr, SZ_4K); + wmb(); /* Flush WC buffers after writing save_restore_ret_address */ return; } @@ -495,7 +494,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params boot_params->punit_telemetry_sram_size = ivpu_hw_reg_telemetry_size_get(vdev); boot_params->vpu_telemetry_enable = ivpu_hw_reg_telemetry_enable_get(vdev); - clflush_cache_range(vdev->fw->mem->kvaddr, SZ_4K); + wmb(); /* Flush WC buffers after writing bootparams */ ivpu_fw_boot_params_print(vdev, boot_params); } diff --git a/drivers/accel/ivpu/ivpu_gem.h b/drivers/accel/ivpu/ivpu_gem.h index f4130586ff1b..6b0ceda5f253 100644 --- a/drivers/accel/ivpu/ivpu_gem.h +++ b/drivers/accel/ivpu/ivpu_gem.h @@ -8,8 +8,6 @@ #include <drm/drm_gem.h> #include <drm/drm_mm.h> -#define DRM_IVPU_BO_NOSNOOP 0x10000000 - struct dma_buf; struct ivpu_bo_ops; struct ivpu_file_priv; @@ -85,9 +83,6 @@ static inline u32 ivpu_bo_cache_mode(struct ivpu_bo *bo) static inline bool ivpu_bo_is_snooped(struct ivpu_bo *bo) { - if (bo->flags & DRM_IVPU_BO_NOSNOOP) - return false; - return ivpu_bo_cache_mode(bo) == DRM_IVPU_BO_CACHED; } diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h index ab341237bcf9..1079e06255ba 100644 --- a/drivers/accel/ivpu/ivpu_hw.h +++ b/drivers/accel/ivpu/ivpu_hw.h @@ -13,6 +13,7 @@ struct ivpu_hw_ops { int (*power_up)(struct ivpu_device *vdev); int (*boot_fw)(struct ivpu_device *vdev); int (*power_down)(struct ivpu_device *vdev); + int (*reset)(struct ivpu_device *vdev); bool (*is_idle)(struct ivpu_device *vdev); void (*wdt_disable)(struct ivpu_device *vdev); void (*diagnose_failure)(struct ivpu_device *vdev); @@ -91,6 +92,13 @@ static inline int ivpu_hw_power_down(struct ivpu_device *vdev) return vdev->hw->ops->power_down(vdev); }; +static inline int ivpu_hw_reset(struct ivpu_device *vdev) +{ + ivpu_dbg(vdev, PM, "HW reset\n"); + + return vdev->hw->ops->reset(vdev); +}; + static inline void ivpu_hw_wdt_disable(struct ivpu_device *vdev) { vdev->hw->ops->wdt_disable(vdev); diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c index 9eae1c241bc0..976019429164 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c @@ -1029,6 +1029,7 @@ const struct ivpu_hw_ops ivpu_hw_37xx_ops = { .power_up = ivpu_hw_37xx_power_up, .is_idle = ivpu_hw_37xx_is_idle, .power_down = ivpu_hw_37xx_power_down, + .reset = ivpu_hw_37xx_reset, .boot_fw = ivpu_hw_37xx_boot_fw, .wdt_disable = ivpu_hw_37xx_wdt_disable, .diagnose_failure = ivpu_hw_37xx_diagnose_failure, diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c index 8bdb59a45da6..85171a408363 100644 --- a/drivers/accel/ivpu/ivpu_hw_40xx.c +++ b/drivers/accel/ivpu/ivpu_hw_40xx.c @@ -1179,6 +1179,7 @@ const struct ivpu_hw_ops ivpu_hw_40xx_ops = { .power_up = ivpu_hw_40xx_power_up, .is_idle = ivpu_hw_40xx_is_idle, .power_down = ivpu_hw_40xx_power_down, + .reset = ivpu_hw_40xx_reset, .boot_fw = ivpu_hw_40xx_boot_fw, .wdt_disable = ivpu_hw_40xx_wdt_disable, .diagnose_failure = ivpu_hw_40xx_diagnose_failure, diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c index 1d2e554e2c4a..ce94f4029127 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.c +++ b/drivers/accel/ivpu/ivpu_mmu_context.c @@ -11,6 +11,7 @@ #include "ivpu_mmu.h" #include "ivpu_mmu_context.h" +#define IVPU_MMU_VPU_ADDRESS_MASK GENMASK(47, 12) #define IVPU_MMU_PGD_INDEX_MASK GENMASK(47, 39) #define IVPU_MMU_PUD_INDEX_MASK GENMASK(38, 30) #define IVPU_MMU_PMD_INDEX_MASK GENMASK(29, 21) @@ -328,12 +329,8 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, if (!IS_ALIGNED(vpu_addr, IVPU_MMU_PAGE_SIZE)) return -EINVAL; - /* - * VPU is only 32 bit, but DMA engine is 38 bit - * Ranges < 2 GB are reserved for VPU internal registers - * Limit range to 8 GB - */ - if (vpu_addr < SZ_2G || vpu_addr > SZ_8G) + + if (vpu_addr & ~IVPU_MMU_VPU_ADDRESS_MASK) return -EINVAL; prot = IVPU_MMU_ENTRY_MAPPED; diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index e6f27daf5560..ffff2496e8e8 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -261,7 +261,8 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev) ivpu_dbg(vdev, PM, "Pre-reset..\n"); atomic_inc(&vdev->pm->reset_counter); atomic_set(&vdev->pm->in_reset, 1); - ivpu_shutdown(vdev); + ivpu_prepare_for_reset(vdev); + ivpu_hw_reset(vdev); ivpu_pm_prepare_cold_boot(vdev); ivpu_jobs_abort_all(vdev); ivpu_dbg(vdev, PM, "Pre-reset done.\n"); diff --git a/drivers/acpi/acpi_fpdt.c b/drivers/acpi/acpi_fpdt.c index a2056c4c8cb7..271092f2700a 100644 --- a/drivers/acpi/acpi_fpdt.c +++ b/drivers/acpi/acpi_fpdt.c @@ -194,12 +194,19 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) record_header = (void *)subtable_header + offset; offset += record_header->length; + if (!record_header->length) { + pr_err(FW_BUG "Zero-length record found in FPTD.\n"); + result = -EINVAL; + goto err; + } + switch (record_header->type) { case RECORD_S3_RESUME: if (subtable_type != SUBTABLE_S3PT) { pr_err(FW_BUG "Invalid record %d for subtable %s\n", record_header->type, signature); - return -EINVAL; + result = -EINVAL; + goto err; } if (record_resume) { pr_err("Duplicate resume performance record found.\n"); @@ -208,7 +215,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) record_resume = (struct resume_performance_record *)record_header; result = sysfs_create_group(fpdt_kobj, &resume_attr_group); if (result) - return result; + goto err; break; case RECORD_S3_SUSPEND: if (subtable_type != SUBTABLE_S3PT) { @@ -223,13 +230,14 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) record_suspend = (struct suspend_performance_record *)record_header; result = sysfs_create_group(fpdt_kobj, &suspend_attr_group); if (result) - return result; + goto err; break; case RECORD_BOOT: if (subtable_type != SUBTABLE_FBPT) { pr_err(FW_BUG "Invalid %d for subtable %s\n", record_header->type, signature); - return -EINVAL; + result = -EINVAL; + goto err; } if (record_boot) { pr_err("Duplicate boot performance record found.\n"); @@ -238,7 +246,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) record_boot = (struct boot_performance_record *)record_header; result = sysfs_create_group(fpdt_kobj, &boot_attr_group); if (result) - return result; + goto err; break; default: @@ -247,6 +255,18 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) } } return 0; + +err: + if (record_boot) + sysfs_remove_group(fpdt_kobj, &boot_attr_group); + + if (record_suspend) + sysfs_remove_group(fpdt_kobj, &suspend_attr_group); + + if (record_resume) + sysfs_remove_group(fpdt_kobj, &resume_attr_group); + + return result; } static int __init acpi_init_fpdt(void) @@ -255,6 +275,7 @@ static int __init acpi_init_fpdt(void) struct acpi_table_header *header; struct fpdt_subtable_entry *subtable; u32 offset = sizeof(*header); + int result; status = acpi_get_table(ACPI_SIG_FPDT, 0, &header); @@ -263,8 +284,8 @@ static int __init acpi_init_fpdt(void) fpdt_kobj = kobject_create_and_add("fpdt", acpi_kobj); if (!fpdt_kobj) { - acpi_put_table(header); - return -ENOMEM; + result = -ENOMEM; + goto err_nomem; } while (offset < header->length) { @@ -272,8 +293,10 @@ static int __init acpi_init_fpdt(void) switch (subtable->type) { case SUBTABLE_FBPT: case SUBTABLE_S3PT: - fpdt_process_subtable(subtable->address, + result = fpdt_process_subtable(subtable->address, subtable->type); + if (result) + goto err_subtable; break; default: /* Other types are reserved in ACPI 6.4 spec. */ @@ -282,6 +305,12 @@ static int __init acpi_init_fpdt(void) offset += sizeof(*subtable); } return 0; +err_subtable: + kobject_put(fpdt_kobj); + +err_nomem: + acpi_put_table(header); + return result; } fs_initcall(acpi_init_fpdt); diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 539e700de4d2..875de44961bf 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -368,7 +368,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT33C4", LPSS_ADDR(lpt_uart_dev_desc) }, { "INT33C5", LPSS_ADDR(lpt_uart_dev_desc) }, { "INT33C6", LPSS_ADDR(lpt_sdio_dev_desc) }, - { "INT33C7", }, /* BayTrail LPSS devices */ { "80860F09", LPSS_ADDR(byt_pwm_dev_desc) }, @@ -376,8 +375,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "80860F0E", LPSS_ADDR(byt_spi_dev_desc) }, { "80860F14", LPSS_ADDR(byt_sdio_dev_desc) }, { "80860F41", LPSS_ADDR(byt_i2c_dev_desc) }, - { "INT33B2", }, - { "INT33FC", }, /* Braswell LPSS devices */ { "80862286", LPSS_ADDR(lpss_dma_desc) }, @@ -396,7 +393,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT3434", LPSS_ADDR(lpt_uart_dev_desc) }, { "INT3435", LPSS_ADDR(lpt_uart_dev_desc) }, { "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) }, - { "INT3437", }, /* Wildcat Point LPSS devices */ { "INT3438", LPSS_ADDR(lpt_spi_dev_desc) }, @@ -578,6 +574,7 @@ static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle) { struct acpi_handle_list dep_devices; acpi_status status; + bool ret = false; int i; if (!acpi_has_method(adev->handle, "_DEP")) @@ -591,11 +588,14 @@ static bool acpi_lpss_dep(struct acpi_device *adev, acpi_handle handle) } for (i = 0; i < dep_devices.count; i++) { - if (dep_devices.handles[i] == handle) - return true; + if (dep_devices.handles[i] == handle) { + ret = true; + break; + } } - return false; + acpi_handle_list_free(&dep_devices); + return ret; } static void acpi_lpss_link_consumer(struct device *dev1, @@ -657,10 +657,9 @@ static int acpi_lpss_create_device(struct acpi_device *adev, int ret; dev_desc = (const struct lpss_device_desc *)id->driver_data; - if (!dev_desc) { - pdev = acpi_create_platform_device(adev, NULL); - return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1; - } + if (!dev_desc) + return -EINVAL; + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 247989060e29..bf65e3461531 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -59,6 +59,10 @@ static struct acpi_table_erst *erst_tab; #define ERST_RANGE_NVRAM 0x0002 #define ERST_RANGE_SLOW 0x0004 +/* ERST Exec max timings */ +#define ERST_EXEC_TIMING_MAX_MASK 0xFFFFFFFF00000000 +#define ERST_EXEC_TIMING_MAX_SHIFT 32 + /* * ERST Error Log Address Range, used as buffer for reading/writing * error records. @@ -68,6 +72,7 @@ static struct erst_erange { u64 size; void __iomem *vaddr; u32 attr; + u64 timings; } erst_erange; /* @@ -97,6 +102,19 @@ static inline int erst_errno(int command_status) } } +static inline u64 erst_get_timeout(void) +{ + u64 timeout = FIRMWARE_TIMEOUT; + + if (erst_erange.attr & ERST_RANGE_SLOW) { + timeout = ((erst_erange.timings & ERST_EXEC_TIMING_MAX_MASK) >> + ERST_EXEC_TIMING_MAX_SHIFT) * NSEC_PER_MSEC; + if (timeout < FIRMWARE_TIMEOUT) + timeout = FIRMWARE_TIMEOUT; + } + return timeout; +} + static int erst_timedout(u64 *t, u64 spin_unit) { if ((s64)*t < spin_unit) { @@ -191,9 +209,11 @@ static int erst_exec_stall_while_true(struct apei_exec_context *ctx, { int rc; u64 val; - u64 timeout = FIRMWARE_TIMEOUT; + u64 timeout; u64 stall_time; + timeout = erst_get_timeout(); + if (ctx->var1 > FIRMWARE_MAX_STALL) { if (!in_nmi()) pr_warn(FW_WARN @@ -389,6 +409,13 @@ static int erst_get_erange(struct erst_erange *range) if (rc) return rc; range->attr = apei_exec_ctx_get_output(&ctx); + rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_TIMINGS); + if (rc == 0) + range->timings = apei_exec_ctx_get_output(&ctx); + else if (rc == -ENOENT) + range->timings = 0; + else + return rc; return 0; } @@ -621,10 +648,12 @@ EXPORT_SYMBOL_GPL(erst_get_record_id_end); static int __erst_write_to_storage(u64 offset) { struct apei_exec_context ctx; - u64 timeout = FIRMWARE_TIMEOUT; + u64 timeout; u64 val; int rc; + timeout = erst_get_timeout(); + erst_exec_ctx_init(&ctx); rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_WRITE); if (rc) @@ -660,10 +689,12 @@ static int __erst_write_to_storage(u64 offset) static int __erst_read_from_storage(u64 record_id, u64 offset) { struct apei_exec_context ctx; - u64 timeout = FIRMWARE_TIMEOUT; + u64 timeout; u64 val; int rc; + timeout = erst_get_timeout(); + erst_exec_ctx_init(&ctx); rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_READ); if (rc) @@ -703,10 +734,12 @@ static int __erst_read_from_storage(u64 record_id, u64 offset) static int __erst_clear_from_storage(u64 record_id) { struct apei_exec_context ctx; - u64 timeout = FIRMWARE_TIMEOUT; + u64 timeout; u64 val; int rc; + timeout = erst_get_timeout(); + erst_exec_ctx_init(&ctx); rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_CLEAR); if (rc) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index ef59d6ea16da..63ad0541db38 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -209,6 +209,20 @@ err_pool_alloc: return -ENOMEM; } +/** + * ghes_estatus_pool_region_free - free previously allocated memory + * from the ghes_estatus_pool. + * @addr: address of memory to free. + * @size: size of memory to free. + * + * Returns none. + */ +void ghes_estatus_pool_region_free(unsigned long addr, u32 size) +{ + gen_pool_free(ghes_estatus_pool, addr, size); +} +EXPORT_SYMBOL_GPL(ghes_estatus_pool_region_free); + static int map_gen_v2(struct ghes *ghes) { return apei_map_generic_address(&ghes->generic_v2->read_ack_register); @@ -564,6 +578,7 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata) pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) { unsigned int devfn; int aer_severity; + u8 *aer_info; devfn = PCI_DEVFN(pcie_err->device_id.device, pcie_err->device_id.function); @@ -577,11 +592,17 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata) if (gdata->flags & CPER_SEC_RESET) aer_severity = AER_FATAL; + aer_info = (void *)gen_pool_alloc(ghes_estatus_pool, + sizeof(struct aer_capability_regs)); + if (!aer_info) + return; + memcpy(aer_info, pcie_err->aer_info, sizeof(struct aer_capability_regs)); + aer_recover_queue(pcie_err->device_id.segment, pcie_err->device_id.bus, devfn, aer_severity, (struct aer_capability_regs *) - pcie_err->aer_info); + aer_info); } #endif } diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index f41dda2d3493..a4aa53b7e2bb 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1410,10 +1410,10 @@ static int __init acpi_init(void) acpi_init_ffh(); pci_mmcfg_late_init(); - acpi_arm_init(); acpi_viot_early_init(); acpi_hest_init(); acpi_ghes_init(); + acpi_arm_init(); acpi_scan_init(); acpi_ec_init(); acpi_debugfs_init(); diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index 9d8e90744cb5..23373faa35ec 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -158,8 +158,8 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia return 0; len = snprintf(modalias, size, "acpi:"); - if (len <= 0) - return len; + if (len >= size) + return -ENOMEM; size -= len; @@ -168,8 +168,6 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia continue; count = snprintf(&modalias[len], size, "%s:", id->id); - if (count < 0) - return -EINVAL; if (count >= size) return -ENOMEM; @@ -177,7 +175,7 @@ static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalia len += count; size -= count; } - modalias[len] = '\0'; + return len; } @@ -212,8 +210,10 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer); ACPI_FREE(buf.pointer); - if (len <= 0) - return len; + if (len >= size) + return -ENOMEM; + + size -= len; of_compatible = acpi_dev->data.of_compatible; if (of_compatible->type == ACPI_TYPE_PACKAGE) { @@ -226,8 +226,6 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias for (i = 0; i < nval; i++, obj++) { count = snprintf(&modalias[len], size, "C%s", obj->string.pointer); - if (count < 0) - return -EINVAL; if (count >= size) return -ENOMEM; @@ -235,7 +233,7 @@ static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias len += count; size -= count; } - modalias[len] = '\0'; + return len; } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index c95d0edb0be9..a59c11df7375 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1926,6 +1926,16 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { }, { /* + * HP 250 G7 Notebook PC + */ + .callback = ec_honor_dsdt_gpe, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G7 Notebook PC"), + }, + }, + { + /* * Samsung hardware * https://bugzilla.kernel.org/show_bug.cgi?id=44161 */ diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c index c2c786eb95ab..1687483ff319 100644 --- a/drivers/acpi/irq.c +++ b/drivers/acpi/irq.c @@ -57,6 +57,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) { struct irq_fwspec fwspec; + unsigned int irq; fwspec.fwnode = acpi_get_gsi_domain_id(gsi); if (WARN_ON(!fwspec.fwnode)) { @@ -68,7 +69,11 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity); fwspec.param_count = 2; - return irq_create_fwspec_mapping(&fwspec); + irq = irq_create_fwspec_mapping(&fwspec); + if (!irq) + return -EINVAL; + + return irq; } EXPORT_SYMBOL_GPL(acpi_register_gsi); diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index f96bf32cd368..7d88db451cfb 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -3339,6 +3339,16 @@ static int acpi_nfit_add(struct acpi_device *adev) acpi_size sz; int rc = 0; + rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY, + acpi_nfit_notify); + if (rc) + return rc; + + rc = devm_add_action_or_reset(dev, acpi_nfit_remove_notify_handler, + adev); + if (rc) + return rc; + status = acpi_get_table(ACPI_SIG_NFIT, 0, &tbl); if (ACPI_FAILURE(status)) { /* The NVDIMM root device allows OS to trigger enumeration of @@ -3386,17 +3396,7 @@ static int acpi_nfit_add(struct acpi_device *adev) if (rc) return rc; - rc = devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc); - if (rc) - return rc; - - rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY, - acpi_nfit_notify); - if (rc) - return rc; - - return devm_add_action_or_reset(dev, acpi_nfit_remove_notify_handler, - adev); + return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc); } static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle) diff --git a/drivers/acpi/osi.c b/drivers/acpi/osi.c index d4405e1ca9b9..df9328c850bd 100644 --- a/drivers/acpi/osi.c +++ b/drivers/acpi/osi.c @@ -110,7 +110,7 @@ void __init acpi_osi_setup(char *str) break; } else if (osi->string[0] == '\0') { osi->enable = enable; - strncpy(osi->string, str, OSI_STRING_LENGTH_MAX); + strscpy(osi->string, str, OSI_STRING_LENGTH_MAX); break; } } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index f725813d0cce..e154ad0be263 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -149,7 +149,7 @@ void acpi_os_printf(const char *fmt, ...) } EXPORT_SYMBOL(acpi_os_printf); -void acpi_os_vprintf(const char *fmt, va_list args) +void __printf(1, 0) acpi_os_vprintf(const char *fmt, va_list args) { static char buffer[512]; @@ -493,7 +493,7 @@ EXPORT_SYMBOL(acpi_os_unmap_generic_address); #ifdef ACPI_FUTURE_USAGE acpi_status -acpi_os_get_physical_address(void *virt, acpi_physical_address * phys) +acpi_os_get_physical_address(void *virt, acpi_physical_address *phys) { if (!phys || !virt) return AE_BAD_PARAMETER; @@ -784,7 +784,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width) #ifdef CONFIG_PCI acpi_status -acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, +acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id, u32 reg, u64 *value, u32 width) { int result, size; @@ -816,7 +816,7 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, } acpi_status -acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, +acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id, u32 reg, u64 value, u32 width) { int result, size; @@ -1067,6 +1067,7 @@ acpi_status acpi_os_execute(acpi_execute_type type, struct acpi_os_dpc *dpc; struct workqueue_struct *queue; int ret; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); @@ -1197,7 +1198,7 @@ bool acpi_queue_hotplug_work(struct work_struct *work) } acpi_status -acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) +acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle *handle) { struct semaphore *sem = NULL; @@ -1522,6 +1523,7 @@ acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp) __acquires(lockp) { acpi_cpu_flags flags; + spin_lock_irqsave(lockp, flags); return flags; } @@ -1554,7 +1556,7 @@ void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags) ******************************************************************************/ acpi_status -acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) +acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t **cache) { *cache = kmem_cache_create(name, size, 0, 0, NULL); if (*cache == NULL) @@ -1575,10 +1577,10 @@ acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) * ******************************************************************************/ -acpi_status acpi_os_purge_cache(acpi_cache_t * cache) +acpi_status acpi_os_purge_cache(acpi_cache_t *cache) { kmem_cache_shrink(cache); - return (AE_OK); + return AE_OK; } /******************************************************************************* @@ -1594,10 +1596,10 @@ acpi_status acpi_os_purge_cache(acpi_cache_t * cache) * ******************************************************************************/ -acpi_status acpi_os_delete_cache(acpi_cache_t * cache) +acpi_status acpi_os_delete_cache(acpi_cache_t *cache) { kmem_cache_destroy(cache); - return (AE_OK); + return AE_OK; } /******************************************************************************* @@ -1614,10 +1616,10 @@ acpi_status acpi_os_delete_cache(acpi_cache_t * cache) * ******************************************************************************/ -acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) +acpi_status acpi_os_release_object(acpi_cache_t *cache, void *object) { kmem_cache_free(cache, object); - return (AE_OK); + return AE_OK; } #endif @@ -1708,6 +1710,7 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control) { int rc = 0; + if (__acpi_os_prepare_sleep) rc = __acpi_os_prepare_sleep(sleep_state, pm1a_control, pm1b_control); @@ -1730,6 +1733,7 @@ acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, u32 val_b) { int rc = 0; + if (__acpi_os_prepare_extended_sleep) rc = __acpi_os_prepare_extended_sleep(sleep_state, val_a, val_b); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 84030804a763..58b89b8d950e 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -1055,9 +1055,9 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, * exists and returns 0, we must preserve any PCI resource * assignments made by firmware for this host bridge. */ - obj = acpi_evaluate_dsm(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1, - DSM_PCI_PRESERVE_BOOT_CONFIG, NULL); - if (obj && obj->type == ACPI_TYPE_INTEGER && obj->integer.value == 0) + obj = acpi_evaluate_dsm_typed(ACPI_HANDLE(bus->bridge), &pci_acpi_dsm_guid, 1, + DSM_PCI_PRESERVE_BOOT_CONFIG, NULL, ACPI_TYPE_INTEGER); + if (obj && obj->integer.value == 0) host_bridge->preserve_config = 1; ACPI_FREE(obj); diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 7020584096bf..c78453c74ef5 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -69,7 +69,7 @@ struct prm_module_info { bool updatable; struct list_head module_list; - struct prm_handler_info handlers[]; + struct prm_handler_info handlers[] __counted_by(handler_count); }; static u64 efi_pa_va_lookup(u64 pa) diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 413e4fcadcaf..6979a3f9f90a 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -55,6 +55,7 @@ static const guid_t ads_guid = GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6, 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b); +/* ACPI _DSD data buffer GUID: edb12dd0-363d-4085-a3d2-49522ca160c4 */ static const guid_t buffer_prop_guid = GUID_INIT(0xedb12dd0, 0x363d, 0x4085, 0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4); @@ -1102,25 +1103,26 @@ static int acpi_data_prop_read(const struct acpi_device_data *data, switch (proptype) { case DEV_PROP_STRING: break; - case DEV_PROP_U8 ... DEV_PROP_U64: + default: if (obj->type == ACPI_TYPE_BUFFER) { if (nval > obj->buffer.length) return -EOVERFLOW; - break; + } else { + if (nval > obj->package.count) + return -EOVERFLOW; } - fallthrough; - default: - if (nval > obj->package.count) - return -EOVERFLOW; break; } if (nval == 0) return -EINVAL; - if (obj->type != ACPI_TYPE_BUFFER) - items = obj->package.elements; - else + if (obj->type == ACPI_TYPE_BUFFER) { + if (proptype != DEV_PROP_U8) + return -EPROTO; items = obj; + } else { + items = obj->package.elements; + } switch (proptype) { case DEV_PROP_U8: diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 297a88587031..15a3bdbd0755 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -385,127 +385,144 @@ unsigned int acpi_dev_get_irq_type(int triggering, int polarity) } EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type); -static const struct dmi_system_id medion_laptop[] = { +/* + * DMI matches for boards where the DSDT specifies the kbd IRQ as + * level active-low and using the override changes this to rising edge, + * stopping the keyboard from working. + */ +static const struct dmi_system_id irq1_level_low_skip_override[] = { { - .ident = "MEDION P15651", + /* MEDION P15651 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), DMI_MATCH(DMI_BOARD_NAME, "M15T"), }, }, { - .ident = "MEDION S17405", + /* MEDION S17405 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), DMI_MATCH(DMI_BOARD_NAME, "M17T"), }, }, { - .ident = "MEDION S17413", + /* MEDION S17413 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), DMI_MATCH(DMI_BOARD_NAME, "M1xA"), }, }, - { } -}; - -static const struct dmi_system_id asus_laptop[] = { { - .ident = "Asus Vivobook K3402ZA", + /* Asus Vivobook K3402ZA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"), }, }, { - .ident = "Asus Vivobook K3502ZA", + /* Asus Vivobook K3502ZA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"), }, }, { - .ident = "Asus Vivobook S5402ZA", + /* Asus Vivobook S5402ZA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"), }, }, { - .ident = "Asus Vivobook S5602ZA", + /* Asus Vivobook S5602ZA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"), }, }, { - .ident = "Asus ExpertBook B1402CBA", + /* Asus ExpertBook B1402CBA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"), }, }, { - .ident = "Asus ExpertBook B1502CBA", + /* Asus ExpertBook B1502CBA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B1502CBA"), }, }, { - .ident = "Asus ExpertBook B2402CBA", + /* Asus ExpertBook B2402CBA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B2402CBA"), }, }, { - .ident = "Asus ExpertBook B2402FBA", + /* Asus ExpertBook B2402FBA */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B2402FBA"), }, }, { - .ident = "Asus ExpertBook B2502", + /* Asus ExpertBook B2502 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"), }, }, + { + /* LG Electronics 17U70P */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_BOARD_NAME, "17U70P"), + }, + }, { } }; -static const struct dmi_system_id tongfang_gm_rg[] = { +/* + * DMI matches for AMD Zen boards where the DSDT specifies the kbd IRQ + * as falling edge and this must be overridden to rising edge, + * to have a working keyboard. + */ +static const struct dmi_system_id irq1_edge_low_force_override[] = { { - .ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD", + /* TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"), }, }, - { } -}; - -static const struct dmi_system_id maingear_laptop[] = { { - .ident = "MAINGEAR Vector Pro 2 15", + /* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"), + }, + }, + { + /* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"), + }, + }, + { + /* MAINGEAR Vector Pro 2 15 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"), DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"), } }, { - .ident = "MAINGEAR Vector Pro 2 17", + /* MAINGEAR Vector Pro 2 17 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"), DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"), }, }, - { } -}; - -static const struct dmi_system_id pcspecialist_laptop[] = { { /* TongFang GM6BGEQ / PCSpecialist Elimina Pro 16 M, RTX 3050 */ .matches = { @@ -527,17 +544,6 @@ static const struct dmi_system_id pcspecialist_laptop[] = { { } }; -static const struct dmi_system_id lg_laptop[] = { - { - .ident = "LG Electronics 17U70P", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), - DMI_MATCH(DMI_BOARD_NAME, "17U70P"), - }, - }, - { } -}; - struct irq_override_cmp { const struct dmi_system_id *system; unsigned char irq; @@ -548,12 +554,8 @@ struct irq_override_cmp { }; static const struct irq_override_cmp override_table[] = { - { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, - { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, - { tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, - { maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, - { pcspecialist_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, - { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, + { irq1_level_low_skip_override, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, + { irq1_edge_low_force_override, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, }; static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 691d4b7686ee..fa5dd71a80fa 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -289,10 +289,10 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return 0; } -static int acpi_scan_device_not_present(struct acpi_device *adev) +static int acpi_scan_device_not_enumerated(struct acpi_device *adev) { if (!acpi_device_enumerated(adev)) { - dev_warn(&adev->dev, "Still not present\n"); + dev_warn(&adev->dev, "Still not enumerated\n"); return -EALREADY; } acpi_bus_trim(adev); @@ -304,7 +304,7 @@ static int acpi_scan_device_check(struct acpi_device *adev) int error; acpi_bus_get_status(adev); - if (adev->status.present || adev->status.functional) { + if (acpi_device_is_present(adev)) { /* * This function is only called for device objects for which * matching scan handlers exist. The only situation in which @@ -327,7 +327,7 @@ static int acpi_scan_device_check(struct acpi_device *adev) error = -ENODEV; } } else { - error = acpi_scan_device_not_present(adev); + error = acpi_scan_device_not_enumerated(adev); } return error; } @@ -338,8 +338,8 @@ static int acpi_scan_bus_check(struct acpi_device *adev, void *not_used) int error; acpi_bus_get_status(adev); - if (!(adev->status.present || adev->status.functional)) { - acpi_scan_device_not_present(adev); + if (!acpi_device_is_present(adev)) { + acpi_scan_device_not_enumerated(adev); return 0; } if (handler && handler->hotplug.scan_dependent) @@ -2032,6 +2032,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) mutex_unlock(&acpi_dep_list_lock); } + acpi_handle_list_free(&dep_devices); return count; } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 312730f8272e..42a3df9d625d 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -43,17 +43,7 @@ #define ACPI_THERMAL_MAX_ACTIVE 10 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 -#define ACPI_TRIPS_CRITICAL BIT(0) -#define ACPI_TRIPS_HOT BIT(1) -#define ACPI_TRIPS_PASSIVE BIT(2) -#define ACPI_TRIPS_ACTIVE BIT(3) -#define ACPI_TRIPS_DEVICES BIT(4) - -#define ACPI_TRIPS_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE) - -#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \ - ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \ - ACPI_TRIPS_DEVICES) +#define ACPI_THERMAL_TRIP_PASSIVE (-1) /* * This exception is thrown out in two cases: @@ -62,12 +52,11 @@ * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change. * We need to re-bind the cooling devices of a thermal zone when this occurs. */ -#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str) \ +#define ACPI_THERMAL_TRIPS_EXCEPTION(tz, str) \ do { \ - if (flags != ACPI_TRIPS_INIT) \ - acpi_handle_info(tz->device->handle, \ - "ACPI thermal trip point %s changed\n" \ - "Please report to linux-acpi@vger.kernel.org\n", str); \ + acpi_handle_info(tz->device->handle, \ + "ACPI thermal trip point %s changed\n" \ + "Please report to linux-acpi@vger.kernel.org\n", str); \ } while (0) static int act; @@ -94,12 +83,11 @@ static struct workqueue_struct *acpi_thermal_pm_queue; struct acpi_thermal_trip { unsigned long temperature; - bool valid; + struct acpi_handle_list devices; }; struct acpi_thermal_passive { struct acpi_thermal_trip trip; - struct acpi_handle_list devices; unsigned long tc1; unsigned long tc2; unsigned long tsp; @@ -107,14 +95,13 @@ struct acpi_thermal_passive { struct acpi_thermal_active { struct acpi_thermal_trip trip; - struct acpi_handle_list devices; }; struct acpi_thermal_trips { - struct acpi_thermal_trip critical; - struct acpi_thermal_trip hot; struct acpi_thermal_passive passive; struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; + bool critical_valid; + bool hot_valid; }; struct acpi_thermal { @@ -188,215 +175,117 @@ static int acpi_thermal_temp(struct acpi_thermal *tz, int temp_deci_k) tz->kelvin_offset); } -static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) +static bool acpi_thermal_trip_valid(struct acpi_thermal_trip *acpi_trip) +{ + return acpi_trip->temperature != THERMAL_TEMP_INVALID; +} + +static long get_passive_temp(struct acpi_thermal *tz) { - acpi_status status; unsigned long long tmp; - struct acpi_handle_list devices; - bool valid = false; - int i; + acpi_status status; - /* Critical Shutdown */ - if (flag & ACPI_TRIPS_CRITICAL) { - status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp); - tz->trips.critical.temperature = tmp; - /* - * Treat freezing temperatures as invalid as well; some - * BIOSes return really low values and cause reboots at startup. - * Below zero (Celsius) values clearly aren't right for sure.. - * ... so lets discard those as invalid. - */ - if (ACPI_FAILURE(status)) { - tz->trips.critical.valid = false; - acpi_handle_debug(tz->device->handle, - "No critical threshold\n"); - } else if (tmp <= 2732) { - pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp); - tz->trips.critical.valid = false; - } else { - tz->trips.critical.valid = true; - acpi_handle_debug(tz->device->handle, - "Found critical threshold [%lu]\n", - tz->trips.critical.temperature); - } - if (tz->trips.critical.valid) { - if (crt == -1) { - tz->trips.critical.valid = false; - } else if (crt > 0) { - unsigned long crt_k = celsius_to_deci_kelvin(crt); - - /* - * Allow override critical threshold - */ - if (crt_k > tz->trips.critical.temperature) - pr_info("Critical threshold %d C\n", crt); - - tz->trips.critical.temperature = crt_k; - } - } - } + status = acpi_evaluate_integer(tz->device->handle, "_PSV", NULL, &tmp); + if (ACPI_FAILURE(status)) + return THERMAL_TEMP_INVALID; - /* Critical Sleep (optional) */ - if (flag & ACPI_TRIPS_HOT) { - status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp); - if (ACPI_FAILURE(status)) { - tz->trips.hot.valid = false; - acpi_handle_debug(tz->device->handle, - "No hot threshold\n"); - } else { - tz->trips.hot.temperature = tmp; - tz->trips.hot.valid = true; - acpi_handle_debug(tz->device->handle, - "Found hot threshold [%lu]\n", - tz->trips.hot.temperature); - } - } + return tmp; +} - /* Passive (optional) */ - if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.trip.valid) || - flag == ACPI_TRIPS_INIT) { - valid = tz->trips.passive.trip.valid; - if (psv == -1) { - status = AE_SUPPORT; - } else if (psv > 0) { - tmp = celsius_to_deci_kelvin(psv); - status = AE_OK; - } else { - status = acpi_evaluate_integer(tz->device->handle, - "_PSV", NULL, &tmp); - } +static void acpi_thermal_update_passive_trip(struct acpi_thermal *tz) +{ + struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; - if (ACPI_FAILURE(status)) { - tz->trips.passive.trip.valid = false; - } else { - tz->trips.passive.trip.temperature = tmp; - tz->trips.passive.trip.valid = true; - if (flag == ACPI_TRIPS_INIT) { - status = acpi_evaluate_integer(tz->device->handle, - "_TC1", NULL, &tmp); - if (ACPI_FAILURE(status)) - tz->trips.passive.trip.valid = false; - else - tz->trips.passive.tc1 = tmp; - - status = acpi_evaluate_integer(tz->device->handle, - "_TC2", NULL, &tmp); - if (ACPI_FAILURE(status)) - tz->trips.passive.trip.valid = false; - else - tz->trips.passive.tc2 = tmp; - - status = acpi_evaluate_integer(tz->device->handle, - "_TSP", NULL, &tmp); - if (ACPI_FAILURE(status)) - tz->trips.passive.trip.valid = false; - else - tz->trips.passive.tsp = tmp; - } - } + if (!acpi_thermal_trip_valid(acpi_trip) || psv > 0) + return; + + acpi_trip->temperature = get_passive_temp(tz); + if (!acpi_thermal_trip_valid(acpi_trip)) + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); +} + +static bool update_trip_devices(struct acpi_thermal *tz, + struct acpi_thermal_trip *acpi_trip, + int index, bool compare) +{ + struct acpi_handle_list devices = { 0 }; + char method[] = "_PSL"; + acpi_status status; + + if (index != ACPI_THERMAL_TRIP_PASSIVE) { + method[1] = 'A'; + method[2] = 'L'; + method[3] = '0' + index; } - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.trip.valid) { - memset(&devices, 0, sizeof(struct acpi_handle_list)); - status = acpi_evaluate_reference(tz->device->handle, "_PSL", - NULL, &devices); - if (ACPI_FAILURE(status)) { - acpi_handle_info(tz->device->handle, - "Invalid passive threshold\n"); - tz->trips.passive.trip.valid = false; - } else { - tz->trips.passive.trip.valid = true; - } - if (memcmp(&tz->trips.passive.devices, &devices, - sizeof(struct acpi_handle_list))) { - memcpy(&tz->trips.passive.devices, &devices, - sizeof(struct acpi_handle_list)); - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); - } + status = acpi_evaluate_reference(tz->device->handle, method, NULL, &devices); + if (ACPI_FAILURE(status)) { + acpi_handle_info(tz->device->handle, "%s evaluation failure\n", method); + return false; } - if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) { - if (valid != tz->trips.passive.trip.valid) - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); + + if (acpi_handle_list_equal(&acpi_trip->devices, &devices)) { + acpi_handle_list_free(&devices); + return true; } - /* Active (optional) */ - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; - valid = tz->trips.active[i].trip.valid; + if (compare) + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device"); - if (act == -1) - break; /* disable all active trip points */ - - if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) && - tz->trips.active[i].trip.valid)) { - status = acpi_evaluate_integer(tz->device->handle, - name, NULL, &tmp); - if (ACPI_FAILURE(status)) { - tz->trips.active[i].trip.valid = false; - if (i == 0) - break; - - if (act <= 0) - break; - - if (i == 1) - tz->trips.active[0].trip.temperature = - celsius_to_deci_kelvin(act); - else - /* - * Don't allow override higher than - * the next higher trip point - */ - tz->trips.active[i-1].trip.temperature = - min_t(unsigned long, - tz->trips.active[i-2].trip.temperature, - celsius_to_deci_kelvin(act)); - - break; - } else { - tz->trips.active[i].trip.temperature = tmp; - tz->trips.active[i].trip.valid = true; - } - } + acpi_handle_list_replace(&acpi_trip->devices, &devices); + return true; +} - name[2] = 'L'; - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].trip.valid) { - memset(&devices, 0, sizeof(struct acpi_handle_list)); - status = acpi_evaluate_reference(tz->device->handle, - name, NULL, &devices); - if (ACPI_FAILURE(status)) { - acpi_handle_info(tz->device->handle, - "Invalid active%d threshold\n", i); - tz->trips.active[i].trip.valid = false; - } else { - tz->trips.active[i].trip.valid = true; - } - - if (memcmp(&tz->trips.active[i].devices, &devices, - sizeof(struct acpi_handle_list))) { - memcpy(&tz->trips.active[i].devices, &devices, - sizeof(struct acpi_handle_list)); - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); - } - } - if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES)) - if (valid != tz->trips.active[i].trip.valid) - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); +static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz, int index) +{ + struct acpi_thermal_trip *acpi_trip; - if (!tz->trips.active[i].trip.valid) - break; + acpi_trip = index == ACPI_THERMAL_TRIP_PASSIVE ? + &tz->trips.passive.trip : &tz->trips.active[index].trip; + if (!acpi_thermal_trip_valid(acpi_trip)) + return; + + if (update_trip_devices(tz, acpi_trip, index, true)) { + return; } - if (flag & ACPI_TRIPS_DEVICES) { - memset(&devices, 0, sizeof(devices)); - status = acpi_evaluate_reference(tz->device->handle, "_TZD", - NULL, &devices); - if (ACPI_SUCCESS(status) && - memcmp(&tz->devices, &devices, sizeof(devices))) { - tz->devices = devices; - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); - } + acpi_trip->temperature = THERMAL_TEMP_INVALID; + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); +} + +static long get_active_temp(struct acpi_thermal *tz, int index) +{ + char method[] = { '_', 'A', 'C', '0' + index, '\0' }; + unsigned long long tmp; + acpi_status status; + + status = acpi_evaluate_integer(tz->device->handle, method, NULL, &tmp); + if (ACPI_FAILURE(status)) + return THERMAL_TEMP_INVALID; + + /* + * If an override has been provided, apply it so there are no active + * trips with thresholds greater than the override. + */ + if (act > 0) { + unsigned long long override = celsius_to_deci_kelvin(act); + + if (tmp > override) + tmp = override; } + return tmp; +} + +static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) +{ + struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; + + if (!acpi_thermal_trip_valid(acpi_trip)) + return; + + acpi_trip->temperature = get_active_temp(tz, index); + if (!acpi_thermal_trip_valid(acpi_trip)) + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) @@ -407,7 +296,7 @@ static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) if (!acpi_trip) return 0; - if (acpi_trip->valid) + if (acpi_thermal_trip_valid(acpi_trip)) trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); else trip->temperature = THERMAL_TEMP_INVALID; @@ -419,10 +308,17 @@ static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal unsigned long data) { struct acpi_thermal *tz = thermal_zone_device_priv(thermal); - int flag = data == ACPI_THERMAL_NOTIFY_THRESHOLDS ? - ACPI_TRIPS_THRESHOLDS : ACPI_TRIPS_DEVICES; + int i; - __acpi_thermal_trips_update(tz, flag); + if (data == ACPI_THERMAL_NOTIFY_THRESHOLDS) { + acpi_thermal_update_passive_trip(tz); + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) + acpi_thermal_update_active_trip(tz, i); + } else { + acpi_thermal_update_trip_devices(tz, ACPI_THERMAL_TRIP_PASSIVE); + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) + acpi_thermal_update_trip_devices(tz, i); + } for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz); } @@ -451,25 +347,143 @@ static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event) dev_name(&adev->dev), event, 0); } +static long acpi_thermal_get_critical_trip(struct acpi_thermal *tz) +{ + unsigned long long tmp; + acpi_status status; + + if (crt > 0) { + tmp = celsius_to_deci_kelvin(crt); + goto set; + } + if (crt == -1) { + acpi_handle_debug(tz->device->handle, "Critical threshold disabled\n"); + goto fail; + } + + status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp); + if (ACPI_FAILURE(status)) { + acpi_handle_debug(tz->device->handle, "No critical threshold\n"); + goto fail; + } + if (tmp <= 2732) { + /* + * Below zero (Celsius) values clearly aren't right for sure, + * so discard them as invalid. + */ + pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp); + goto fail; + } + +set: + tz->trips.critical_valid = true; + acpi_handle_debug(tz->device->handle, "Critical threshold [%llu]\n", tmp); + return tmp; + +fail: + tz->trips.critical_valid = false; + return THERMAL_TEMP_INVALID; +} + +static long acpi_thermal_get_hot_trip(struct acpi_thermal *tz) +{ + unsigned long long tmp; + acpi_status status; + + status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp); + if (ACPI_FAILURE(status)) { + tz->trips.hot_valid = false; + acpi_handle_debug(tz->device->handle, "No hot threshold\n"); + return THERMAL_TEMP_INVALID; + } + + tz->trips.hot_valid = true; + acpi_handle_debug(tz->device->handle, "Hot threshold [%llu]\n", tmp); + return tmp; +} + +static bool passive_trip_params_init(struct acpi_thermal *tz) +{ + unsigned long long tmp; + acpi_status status; + + status = acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, &tmp); + if (ACPI_FAILURE(status)) + return false; + + tz->trips.passive.tc1 = tmp; + + status = acpi_evaluate_integer(tz->device->handle, "_TC2", NULL, &tmp); + if (ACPI_FAILURE(status)) + return false; + + tz->trips.passive.tc2 = tmp; + + status = acpi_evaluate_integer(tz->device->handle, "_TSP", NULL, &tmp); + if (ACPI_FAILURE(status)) + return false; + + tz->trips.passive.tsp = tmp; + + return true; +} + +static bool acpi_thermal_init_trip(struct acpi_thermal *tz, int index) +{ + struct acpi_thermal_trip *acpi_trip; + long temp; + + if (index == ACPI_THERMAL_TRIP_PASSIVE) { + acpi_trip = &tz->trips.passive.trip; + + if (psv == -1) + goto fail; + + if (!passive_trip_params_init(tz)) + goto fail; + + temp = psv > 0 ? celsius_to_deci_kelvin(psv) : + get_passive_temp(tz); + } else { + acpi_trip = &tz->trips.active[index].trip; + + if (act == -1) + goto fail; + + temp = get_active_temp(tz, index); + } + + if (temp == THERMAL_TEMP_INVALID) + goto fail; + + if (!update_trip_devices(tz, acpi_trip, index, false)) + goto fail; + + acpi_trip->temperature = temp; + return true; + +fail: + acpi_trip->temperature = THERMAL_TEMP_INVALID; + return false; +} + static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { - bool valid; + unsigned int count = 0; int i; - __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); - - valid = tz->trips.critical.valid | - tz->trips.hot.valid | - tz->trips.passive.trip.valid; + if (acpi_thermal_init_trip(tz, ACPI_THERMAL_TRIP_PASSIVE)) + count++; - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - valid = valid || tz->trips.active[i].trip.valid; + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { + if (acpi_thermal_init_trip(tz, i)) + count++; + else + break; - if (!valid) { - pr_warn(FW_BUG "No valid trip found\n"); - return -ENODEV; } - return 0; + + return count; } /* sys I/F for generic thermal sysfs support */ @@ -503,7 +517,7 @@ static int thermal_get_trend(struct thermal_zone_device *thermal, return -EINVAL; acpi_trip = trip->priv; - if (!acpi_trip || !acpi_trip->valid) + if (!acpi_trip || !acpi_thermal_trip_valid(acpi_trip)) return -EINVAL; switch (trip->type) { @@ -563,6 +577,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, { struct acpi_device *device = cdev->devdata; struct acpi_thermal *tz = thermal_zone_device_priv(thermal); + struct acpi_thermal_trip *acpi_trip; struct acpi_device *dev; acpi_handle handle; int i; @@ -570,16 +585,17 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, int trip = -1; int result = 0; - if (tz->trips.critical.valid) + if (tz->trips.critical_valid) trip++; - if (tz->trips.hot.valid) + if (tz->trips.hot_valid) trip++; - if (tz->trips.passive.trip.valid) { + acpi_trip = &tz->trips.passive.trip; + if (acpi_thermal_trip_valid(acpi_trip)) { trip++; - for (i = 0; i < tz->trips.passive.devices.count; i++) { - handle = tz->trips.passive.devices.handles[i]; + for (i = 0; i < acpi_trip->devices.count; i++) { + handle = acpi_trip->devices.handles[i]; dev = acpi_fetch_acpi_dev(handle); if (dev != device) continue; @@ -601,12 +617,13 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!tz->trips.active[i].trip.valid) + acpi_trip = &tz->trips.active[i].trip; + if (!acpi_thermal_trip_valid(acpi_trip)) break; trip++; - for (j = 0; j < tz->trips.active[i].devices.count; j++) { - handle = tz->trips.active[i].devices.handles[j]; + for (j = 0; j < acpi_trip->devices.count; j++) { + handle = acpi_trip->devices.handles[j]; dev = acpi_fetch_acpi_dev(handle); if (dev != device) continue; @@ -679,66 +696,11 @@ static void acpi_thermal_zone_sysfs_remove(struct acpi_thermal *tz) sysfs_remove_link(&tzdev->kobj, "device"); } -static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) +static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz, + unsigned int trip_count, + int passive_delay) { - struct acpi_thermal_trip *acpi_trip; - struct thermal_trip *trip; - int passive_delay = 0; - int trip_count = 0; int result; - int i; - - if (tz->trips.critical.valid) - trip_count++; - - if (tz->trips.hot.valid) - trip_count++; - - if (tz->trips.passive.trip.valid) { - trip_count++; - passive_delay = tz->trips.passive.tsp * 100; - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].trip.valid; i++) - trip_count++; - - trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); - if (!trip) - return -ENOMEM; - - tz->trip_table = trip; - - if (tz->trips.critical.valid) { - trip->type = THERMAL_TRIP_CRITICAL; - trip->temperature = acpi_thermal_temp(tz, tz->trips.critical.temperature); - trip++; - } - - if (tz->trips.hot.valid) { - trip->type = THERMAL_TRIP_HOT; - trip->temperature = acpi_thermal_temp(tz, tz->trips.hot.temperature); - trip++; - } - - acpi_trip = &tz->trips.passive.trip; - if (acpi_trip->valid) { - trip->type = THERMAL_TRIP_PASSIVE; - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); - trip->priv = acpi_trip; - trip++; - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - acpi_trip = &tz->trips.active[i].trip; - - if (!acpi_trip->valid) - break; - - trip->type = THERMAL_TRIP_ACTIVE; - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); - trip->priv = acpi_trip; - trip++; - } tz->thermal_zone = thermal_zone_device_register_with_trips("acpitz", tz->trip_table, @@ -748,10 +710,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) NULL, passive_delay, tz->polling_frequency * 100); - if (IS_ERR(tz->thermal_zone)) { - result = PTR_ERR(tz->thermal_zone); - goto free_trip_table; - } + if (IS_ERR(tz->thermal_zone)) + return PTR_ERR(tz->thermal_zone); result = acpi_thermal_zone_sysfs_add(tz); if (result) @@ -770,8 +730,6 @@ remove_links: acpi_thermal_zone_sysfs_remove(tz); unregister_tzd: thermal_zone_device_unregister(tz->thermal_zone); -free_trip_table: - kfree(tz->trip_table); return result; } @@ -844,38 +802,6 @@ static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz) acpi_evaluate_integer(handle, "_TMP", NULL, &value); } -static int acpi_thermal_get_info(struct acpi_thermal *tz) -{ - int result; - - if (!tz) - return -EINVAL; - - acpi_thermal_aml_dependency_fix(tz); - - /* Get trip points [_CRT, _PSV, etc.] (required) */ - result = acpi_thermal_get_trip_points(tz); - if (result) - return result; - - /* Get temperature [_TMP] (required) */ - result = acpi_thermal_get_temperature(tz); - if (result) - return result; - - /* Set the cooling mode [_SCP] to active cooling (default) */ - acpi_execute_simple_method(tz->device->handle, "_SCP", - ACPI_THERMAL_MODE_ACTIVE); - - /* Get default polling frequency [_TZP] (optional) */ - if (tzp) - tz->polling_frequency = tzp; - else - acpi_thermal_get_polling_frequency(tz); - - return 0; -} - /* * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI * handles temperature values with a single decimal place. As a consequence, @@ -886,10 +812,9 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz) * The heuristic below should work for all ACPI thermal zones which have a * critical trip point with a value being a multiple of 0.5 degree Celsius. */ -static void acpi_thermal_guess_offset(struct acpi_thermal *tz) +static void acpi_thermal_guess_offset(struct acpi_thermal *tz, long crit_temp) { - if (tz->trips.critical.valid && - (tz->trips.critical.temperature % 5) == 1) + if (tz->trips.critical_valid && crit_temp % 5 == 1) tz->kelvin_offset = 273100; else tz->kelvin_offset = 273200; @@ -920,10 +845,27 @@ static void acpi_thermal_check_fn(struct work_struct *work) mutex_unlock(&tz->thermal_check_lock); } +static void acpi_thermal_free_thermal_zone(struct acpi_thermal *tz) +{ + int i; + + acpi_handle_list_free(&tz->trips.passive.trip.devices); + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) + acpi_handle_list_free(&tz->trips.active[i].trip.devices); + + kfree(tz); +} + static int acpi_thermal_add(struct acpi_device *device) { + struct acpi_thermal_trip *acpi_trip; + struct thermal_trip *trip; struct acpi_thermal *tz; + unsigned int trip_count; + int crit_temp, hot_temp; + int passive_delay = 0; int result; + int i; if (!device) return -EINVAL; @@ -938,15 +880,87 @@ static int acpi_thermal_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); device->driver_data = tz; - result = acpi_thermal_get_info(tz); + acpi_thermal_aml_dependency_fix(tz); + + /* Get trip points [_CRT, _PSV, etc.] (required). */ + trip_count = acpi_thermal_get_trip_points(tz); + + crit_temp = acpi_thermal_get_critical_trip(tz); + if (tz->trips.critical_valid) + trip_count++; + + hot_temp = acpi_thermal_get_hot_trip(tz); + if (tz->trips.hot_valid) + trip_count++; + + if (!trip_count) { + pr_warn(FW_BUG "No valid trip points!\n"); + result = -ENODEV; + goto free_memory; + } + + /* Get temperature [_TMP] (required). */ + result = acpi_thermal_get_temperature(tz); if (result) goto free_memory; - acpi_thermal_guess_offset(tz); + /* Set the cooling mode [_SCP] to active cooling. */ + acpi_execute_simple_method(tz->device->handle, "_SCP", + ACPI_THERMAL_MODE_ACTIVE); - result = acpi_thermal_register_thermal_zone(tz); - if (result) + /* Determine the default polling frequency [_TZP]. */ + if (tzp) + tz->polling_frequency = tzp; + else + acpi_thermal_get_polling_frequency(tz); + + acpi_thermal_guess_offset(tz, crit_temp); + + trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); + if (!trip) { + result = -ENOMEM; goto free_memory; + } + + tz->trip_table = trip; + + if (tz->trips.critical_valid) { + trip->type = THERMAL_TRIP_CRITICAL; + trip->temperature = acpi_thermal_temp(tz, crit_temp); + trip++; + } + + if (tz->trips.hot_valid) { + trip->type = THERMAL_TRIP_HOT; + trip->temperature = acpi_thermal_temp(tz, hot_temp); + trip++; + } + + acpi_trip = &tz->trips.passive.trip; + if (acpi_thermal_trip_valid(acpi_trip)) { + passive_delay = tz->trips.passive.tsp * 100; + + trip->type = THERMAL_TRIP_PASSIVE; + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + trip->priv = acpi_trip; + trip++; + } + + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { + acpi_trip = &tz->trips.active[i].trip; + + if (!acpi_thermal_trip_valid(acpi_trip)) + break; + + trip->type = THERMAL_TRIP_ACTIVE; + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + trip->priv = acpi_trip; + trip++; + } + + result = acpi_thermal_register_thermal_zone(tz, trip_count, passive_delay); + if (result) + goto free_trips; refcount_set(&tz->thermal_check_count, 3); mutex_init(&tz->thermal_check_lock); @@ -965,8 +979,10 @@ static int acpi_thermal_add(struct acpi_device *device) flush_wq: flush_workqueue(acpi_thermal_pm_queue); acpi_thermal_unregister_thermal_zone(tz); +free_trips: + kfree(tz->trip_table); free_memory: - kfree(tz); + acpi_thermal_free_thermal_zone(tz); return result; } @@ -986,7 +1002,7 @@ static void acpi_thermal_remove(struct acpi_device *device) flush_workqueue(acpi_thermal_pm_queue); acpi_thermal_unregister_thermal_zone(tz); - kfree(tz); + acpi_thermal_free_thermal_zone(tz); } #ifdef CONFIG_PM_SLEEP @@ -1010,11 +1026,13 @@ static int acpi_thermal_resume(struct device *dev) return -EINVAL; for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!tz->trips.active[i].trip.valid) + struct acpi_thermal_trip *acpi_trip = &tz->trips.active[i].trip; + + if (!acpi_thermal_trip_valid(acpi_trip)) break; - for (j = 0; j < tz->trips.active[i].devices.count; j++) { - acpi_bus_update_power(tz->trips.active[i].devices.handles[j], + for (j = 0; j < acpi_trip->devices.count; j++) { + acpi_bus_update_power(acpi_trip->devices.handles[j], &power_state); } } diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 558464c088bf..28c75242fca9 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -342,9 +342,8 @@ acpi_evaluate_reference(acpi_handle handle, u32 i = 0; - if (!list) { + if (!list) return AE_BAD_PARAMETER; - } /* Evaluate object. */ @@ -370,7 +369,8 @@ acpi_evaluate_reference(acpi_handle handle, goto end; } - if (package->package.count > ACPI_MAX_HANDLES) { + list->handles = kcalloc(package->package.count, sizeof(*list->handles), GFP_KERNEL); + if (!list->handles) { kfree(package); return AE_NO_MEMORY; } @@ -399,10 +399,11 @@ acpi_evaluate_reference(acpi_handle handle, acpi_handle_debug(list->handles[i], "Found in reference list\n"); } - end: +end: if (ACPI_FAILURE(status)) { list->count = 0; - //kfree(list->handles); + kfree(list->handles); + list->handles = NULL; } kfree(buffer.pointer); @@ -412,6 +413,61 @@ acpi_evaluate_reference(acpi_handle handle, EXPORT_SYMBOL(acpi_evaluate_reference); +/** + * acpi_handle_list_equal - Check if two ACPI handle lists are the same + * @list1: First list to compare. + * @list2: Second list to compare. + * + * Return true if the given ACPI handle lists are of the same size and + * contain the same ACPI handles in the same order. Otherwise, return false. + */ +bool acpi_handle_list_equal(struct acpi_handle_list *list1, + struct acpi_handle_list *list2) +{ + return list1->count == list2->count && + !memcmp(list1->handles, list2->handles, + list1->count * sizeof(acpi_handle)); +} +EXPORT_SYMBOL_GPL(acpi_handle_list_equal); + +/** + * acpi_handle_list_replace - Replace one ACPI handle list with another + * @dst: ACPI handle list to replace. + * @src: Source ACPI handle list. + * + * Free the handles table in @dst, move the handles table from @src to @dst, + * copy count from @src to @dst and clear @src. + */ +void acpi_handle_list_replace(struct acpi_handle_list *dst, + struct acpi_handle_list *src) +{ + if (dst->count) + kfree(dst->handles); + + dst->count = src->count; + dst->handles = src->handles; + + src->handles = NULL; + src->count = 0; +} +EXPORT_SYMBOL_GPL(acpi_handle_list_replace); + +/** + * acpi_handle_list_free - Free the handles table in an ACPI handle list + * @list: ACPI handle list to free. + * + * Free the handles table in @list and clear its count field. + */ +void acpi_handle_list_free(struct acpi_handle_list *list) +{ + if (!list->count) + return; + + kfree(list->handles); + list->count = 0; +} +EXPORT_SYMBOL_GPL(acpi_handle_list_free); + acpi_status acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld) { @@ -523,7 +579,7 @@ acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...) vaf.va = &args; path = acpi_handle_path(handle); - printk("%sACPI: %s: %pV", level, path ? path : "<n/a>" , &vaf); + printk("%sACPI: %s: %pV", level, path ? path : "<n/a>", &vaf); va_end(args); kfree(path); diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 442396f6ed1f..9fdcc620c652 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -130,6 +130,16 @@ static int video_detect_force_native(const struct dmi_system_id *d) return 0; } +static int video_detect_portege_r100(const struct dmi_system_id *d) +{ + struct pci_dev *dev; + /* Search for Trident CyberBlade XP4m32 to confirm Portégé R100 */ + dev = pci_get_device(PCI_VENDOR_ID_TRIDENT, 0x2100, NULL); + if (dev) + acpi_backlight_dmi = acpi_backlight_vendor; + return 0; +} + static const struct dmi_system_id video_detect_dmi_table[] = { /* * Models which should use the vendor backlight interface, @@ -229,14 +239,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"), }, }, - { - .callback = video_detect_force_vendor, - /* Xiaomi Mi Pad 2 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), - DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), - }, - }, /* * Models which should use the vendor backlight interface, @@ -271,6 +273,22 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, /* + * Toshiba Portégé R100 has working both acpi_video and toshiba_acpi + * vendor driver. But none of them gets activated as it has a VGA with + * no kernel driver (Trident CyberBlade XP4m32). + * The DMI strings are generic so check for the VGA chip in callback. + */ + { + .callback = video_detect_portege_r100, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"), + DMI_MATCH(DMI_BOARD_NAME, "Portable PC") + }, + }, + + /* * Models which need acpi_video backlight control where the GPU drivers * do not call acpi_video_register_backlight() because no internal panel * is detected. Typically these are all-in-ones (monitors with builtin @@ -799,6 +817,56 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 15 3535"), }, }, + + /* + * x86 android tablets which directly control the backlight through + * an external backlight controller, typically TI's LP8557. + * The backlight is directly controlled by the lp855x driver on these. + * This setup means that neither i915's native nor acpi_video backlight + * control works. Add a "vendor" quirk to disable both. Note these + * devices do not use vendor control in the typical meaning of + * vendor specific SMBIOS or ACPI calls being used. + */ + { + .callback = video_detect_force_vendor, + /* Lenovo Yoga Book X90F / X90L */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"), + }, + }, + { + .callback = video_detect_force_vendor, + /* + * Lenovo Yoga Tablet 2 830F/L or 1050F/L (The 8" and 10" + * Lenovo Yoga Tablet 2 use the same mainboard) + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."), + DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"), + DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"), + /* Partial match on beginning of BIOS version */ + DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"), + }, + }, + { + .callback = video_detect_force_vendor, + /* Lenovo Yoga Tab 3 Pro YT3-X90F */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"), + }, + }, + { + .callback = video_detect_force_vendor, + /* Xiaomi Mi Pad 2 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"), + DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), + }, + }, { }, }; diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index 08f7c6708206..7d64e655f1b8 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -417,11 +417,10 @@ static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *d int ret = -EINVAL; guid_parse(uuid, dsm_guid); - obj = acpi_evaluate_dsm(handle, dsm_guid, rev, 0, NULL); /* Check if the _DSM is present and as expected. */ - if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length == 0 || - obj->buffer.length > sizeof(u32)) { + obj = acpi_evaluate_dsm_typed(handle, dsm_guid, rev, 0, NULL, ACPI_TYPE_BUFFER); + if (!obj || obj->buffer.length == 0 || obj->buffer.length > sizeof(u32)) { acpi_handle_debug(handle, "_DSM UUID %s rev %d function 0 evaluation failed\n", uuid, rev); goto out; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 884cb51c8f67..234a84ecde8b 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1478,7 +1478,7 @@ static int dev_get_regmap_match(struct device *dev, void *res, void *data) /* If the user didn't specify a name match any */ if (data) - return !strcmp((*r)->name, data); + return (*r)->name && !strcmp((*r)->name, data); else return 1; } diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 84c2c2e1122f..277d039ecbb4 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -962,13 +962,10 @@ static void btrtl_dmp_hdr(struct hci_dev *hdev, struct sk_buff *skb) skb_put_data(skb, buf, strlen(buf)); } -static int btrtl_register_devcoredump_support(struct hci_dev *hdev) +static void btrtl_register_devcoredump_support(struct hci_dev *hdev) { - int err; + hci_devcd_register(hdev, btrtl_coredump, btrtl_dmp_hdr, NULL); - err = hci_devcd_register(hdev, btrtl_coredump, btrtl_dmp_hdr, NULL); - - return err; } void btrtl_set_driver_name(struct hci_dev *hdev, const char *driver_name) @@ -1255,8 +1252,7 @@ int btrtl_download_firmware(struct hci_dev *hdev, } done: - if (!err) - err = btrtl_register_devcoredump_support(hdev); + btrtl_register_devcoredump_support(hdev); return err; } diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 40e2b9fa11a2..f3892e9ce800 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -74,7 +74,10 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) struct vhci_data *data = hci_get_drvdata(hdev); memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); + + mutex_lock(&data->open_mutex); skb_queue_tail(&data->readq, skb); + mutex_unlock(&data->open_mutex); wake_up_interruptible(&data->read_wait); return 0; diff --git a/drivers/crypto/virtio/virtio_crypto_common.h b/drivers/crypto/virtio/virtio_crypto_common.h index 59a4c0259456..154590e1f764 100644 --- a/drivers/crypto/virtio/virtio_crypto_common.h +++ b/drivers/crypto/virtio/virtio_crypto_common.h @@ -35,6 +35,9 @@ struct virtio_crypto { struct virtqueue *ctrl_vq; struct data_queue *data_vq; + /* Work struct for config space updates */ + struct work_struct config_work; + /* To protect the vq operations for the controlq */ spinlock_t ctrl_lock; diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c index 94849fa3bd74..43a0838d31ff 100644 --- a/drivers/crypto/virtio/virtio_crypto_core.c +++ b/drivers/crypto/virtio/virtio_crypto_core.c @@ -335,6 +335,14 @@ static void virtcrypto_del_vqs(struct virtio_crypto *vcrypto) virtcrypto_free_queues(vcrypto); } +static void vcrypto_config_changed_work(struct work_struct *work) +{ + struct virtio_crypto *vcrypto = + container_of(work, struct virtio_crypto, config_work); + + virtcrypto_update_status(vcrypto); +} + static int virtcrypto_probe(struct virtio_device *vdev) { int err = -EFAULT; @@ -454,6 +462,8 @@ static int virtcrypto_probe(struct virtio_device *vdev) if (err) goto free_engines; + INIT_WORK(&vcrypto->config_work, vcrypto_config_changed_work); + return 0; free_engines: @@ -490,6 +500,7 @@ static void virtcrypto_remove(struct virtio_device *vdev) dev_info(&vdev->dev, "Start virtcrypto_remove.\n"); + flush_work(&vcrypto->config_work); if (virtcrypto_dev_started(vcrypto)) virtcrypto_dev_stop(vcrypto); virtio_reset_device(vdev); @@ -504,7 +515,7 @@ static void virtcrypto_config_changed(struct virtio_device *vdev) { struct virtio_crypto *vcrypto = vdev->priv; - virtcrypto_update_status(vcrypto); + schedule_work(&vcrypto->config_work); } #ifdef CONFIG_PM_SLEEP @@ -512,6 +523,7 @@ static int virtcrypto_freeze(struct virtio_device *vdev) { struct virtio_crypto *vcrypto = vdev->priv; + flush_work(&vcrypto->config_work); virtio_reset_device(vdev); virtcrypto_free_unused_reqs(vcrypto); if (virtcrypto_dev_started(vcrypto)) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index ce20a60676f0..1974f0ad32ba 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -273,9 +273,13 @@ static __init int efivar_ssdt_load(void) if (status == EFI_NOT_FOUND) { break; } else if (status == EFI_BUFFER_TOO_SMALL) { - name = krealloc(name, name_size, GFP_KERNEL); - if (!name) + efi_char16_t *name_tmp = + krealloc(name, name_size, GFP_KERNEL); + if (!name_tmp) { + kfree(name); return -ENOMEM; + } + name = name_tmp; continue; } diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c index 2fee52ed335d..9d5df683f882 100644 --- a/drivers/firmware/efi/libstub/x86-stub.c +++ b/drivers/firmware/efi/libstub/x86-stub.c @@ -605,11 +605,8 @@ setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_s break; case EFI_UNACCEPTED_MEMORY: - if (!IS_ENABLED(CONFIG_UNACCEPTED_MEMORY)) { - efi_warn_once( -"The system has unaccepted memory, but kernel does not support it\nConsider enabling CONFIG_UNACCEPTED_MEMORY\n"); + if (!IS_ENABLED(CONFIG_UNACCEPTED_MEMORY)) continue; - } e820_type = E820_TYPE_RAM; process_unaccepted_memory(d->phys_addr, d->phys_addr + PAGE_SIZE * d->num_pages); @@ -852,6 +849,8 @@ void __noreturn efi_stub_entry(efi_handle_t handle, unsigned long kernel_entry; efi_status_t status; + boot_params_pointer = boot_params; + efi_system_table = sys_table_arg; /* Check if we were booted by the EFI firmware */ if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) diff --git a/drivers/firmware/efi/libstub/x86-stub.h b/drivers/firmware/efi/libstub/x86-stub.h index 37c5a36b9d8c..2748bca192df 100644 --- a/drivers/firmware/efi/libstub/x86-stub.h +++ b/drivers/firmware/efi/libstub/x86-stub.h @@ -2,6 +2,8 @@ #include <linux/efi.h> +extern struct boot_params *boot_params_pointer asm("boot_params"); + extern void trampoline_32bit_src(void *, bool); extern const u16 trampoline_ljmp_imm_offset; diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c index 853f7dc3c21d..135278ddaf62 100644 --- a/drivers/firmware/efi/unaccepted_memory.c +++ b/drivers/firmware/efi/unaccepted_memory.c @@ -5,9 +5,17 @@ #include <linux/spinlock.h> #include <asm/unaccepted_memory.h> -/* Protects unaccepted memory bitmap */ +/* Protects unaccepted memory bitmap and accepting_list */ static DEFINE_SPINLOCK(unaccepted_memory_lock); +struct accept_range { + struct list_head list; + unsigned long start; + unsigned long end; +}; + +static LIST_HEAD(accepting_list); + /* * accept_memory() -- Consult bitmap and accept the memory if needed. * @@ -24,6 +32,7 @@ void accept_memory(phys_addr_t start, phys_addr_t end) { struct efi_unaccepted_memory *unaccepted; unsigned long range_start, range_end; + struct accept_range range, *entry; unsigned long flags; u64 unit_size; @@ -78,20 +87,67 @@ void accept_memory(phys_addr_t start, phys_addr_t end) if (end > unaccepted->size * unit_size * BITS_PER_BYTE) end = unaccepted->size * unit_size * BITS_PER_BYTE; - range_start = start / unit_size; - + range.start = start / unit_size; + range.end = DIV_ROUND_UP(end, unit_size); +retry: spin_lock_irqsave(&unaccepted_memory_lock, flags); + + /* + * Check if anybody works on accepting the same range of the memory. + * + * The check is done with unit_size granularity. It is crucial to catch + * all accept requests to the same unit_size block, even if they don't + * overlap on physical address level. + */ + list_for_each_entry(entry, &accepting_list, list) { + if (entry->end < range.start) + continue; + if (entry->start >= range.end) + continue; + + /* + * Somebody else accepting the range. Or at least part of it. + * + * Drop the lock and retry until it is complete. + */ + spin_unlock_irqrestore(&unaccepted_memory_lock, flags); + goto retry; + } + + /* + * Register that the range is about to be accepted. + * Make sure nobody else will accept it. + */ + list_add(&range.list, &accepting_list); + + range_start = range.start; for_each_set_bitrange_from(range_start, range_end, unaccepted->bitmap, - DIV_ROUND_UP(end, unit_size)) { + range.end) { unsigned long phys_start, phys_end; unsigned long len = range_end - range_start; phys_start = range_start * unit_size + unaccepted->phys_base; phys_end = range_end * unit_size + unaccepted->phys_base; + /* + * Keep interrupts disabled until the accept operation is + * complete in order to prevent deadlocks. + * + * Enabling interrupts before calling arch_accept_memory() + * creates an opportunity for an interrupt handler to request + * acceptance for the same memory. The handler will continuously + * spin with interrupts disabled, preventing other task from + * making progress with the acceptance process. + */ + spin_unlock(&unaccepted_memory_lock); + arch_accept_memory(phys_start, phys_end); + + spin_lock(&unaccepted_memory_lock); bitmap_clear(unaccepted->bitmap, range_start, len); } + + list_del(&range.list); spin_unlock_irqrestore(&unaccepted_memory_lock, flags); } diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index dbc7ba0ee72c..656d6b1dddb5 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -126,14 +126,14 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, unsigned long mask = BIT(gpio); u32 val; + vf610_gpio_set(chip, gpio, value); + if (port->sdata && port->sdata->have_paddr) { val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR); val |= mask; vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR); } - vf610_gpio_set(chip, gpio, value); - return pinctrl_gpio_direction_output(chip->base + gpio); } @@ -246,7 +246,8 @@ static const struct irq_chip vf610_irqchip = { .irq_unmask = vf610_gpio_irq_unmask, .irq_set_type = vf610_gpio_irq_set_type, .irq_set_wake = vf610_gpio_irq_set_wake, - .flags = IRQCHIP_IMMUTABLE, + .flags = IRQCHIP_IMMUTABLE | IRQCHIP_MASK_ON_SUSPEND + | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND, GPIOCHIP_IRQ_RESOURCE_HELPERS, }; diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index fbda452fb4d6..51e41676de0b 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -951,6 +951,7 @@ static struct gpio_desc *acpi_get_gpiod_from_data(struct fwnode_handle *fwnode, if (!propname) return ERR_PTR(-EINVAL); + memset(&lookup, 0, sizeof(lookup)); lookup.index = index; ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 0dc9c655c4fb..aac52d9754e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -47,7 +47,6 @@ const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = { bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio) { switch (ctx_prio) { - case AMDGPU_CTX_PRIORITY_UNSET: case AMDGPU_CTX_PRIORITY_VERY_LOW: case AMDGPU_CTX_PRIORITY_LOW: case AMDGPU_CTX_PRIORITY_NORMAL: @@ -55,6 +54,7 @@ bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio) case AMDGPU_CTX_PRIORITY_VERY_HIGH: return true; default: + case AMDGPU_CTX_PRIORITY_UNSET: return false; } } @@ -64,7 +64,8 @@ amdgpu_ctx_to_drm_sched_prio(int32_t ctx_prio) { switch (ctx_prio) { case AMDGPU_CTX_PRIORITY_UNSET: - return DRM_SCHED_PRIORITY_UNSET; + pr_warn_once("AMD-->DRM context priority value UNSET-->NORMAL"); + return DRM_SCHED_PRIORITY_NORMAL; case AMDGPU_CTX_PRIORITY_VERY_LOW: return DRM_SCHED_PRIORITY_MIN; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 12210598e5b8..ba3a87cb88cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -403,7 +403,10 @@ amdgpu_dma_buf_move_notify(struct dma_buf_attachment *attach) continue; } - r = amdgpu_vm_clear_freed(adev, vm, NULL); + /* Reserve fences for two SDMA page table updates */ + r = dma_resv_reserve_fences(resv, 2); + if (!r) + r = amdgpu_vm_clear_freed(adev, vm, NULL); if (!r) r = amdgpu_vm_handle_moved(adev, vm); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f5daadcec865..82f25996ff5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1090,7 +1090,8 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, struct drm_gem_object *gobj = dma_buf->priv; struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj); - if (abo->tbo.resource->mem_type == TTM_PL_VRAM) + if (abo->tbo.resource && + abo->tbo.resource->mem_type == TTM_PL_VRAM) bo = gem_to_amdgpu_bo(gobj); } mem = bo->tbo.resource; diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index f448b903e190..84148a79414b 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -692,7 +692,7 @@ static struct ti_sn65dsi86 *bridge_to_ti_sn65dsi86(struct drm_bridge *bridge) return container_of(bridge, struct ti_sn65dsi86, bridge); } -static int ti_sn_attach_host(struct ti_sn65dsi86 *pdata) +static int ti_sn_attach_host(struct auxiliary_device *adev, struct ti_sn65dsi86 *pdata) { int val; struct mipi_dsi_host *host; @@ -707,7 +707,7 @@ static int ti_sn_attach_host(struct ti_sn65dsi86 *pdata) if (!host) return -EPROBE_DEFER; - dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + dsi = devm_mipi_dsi_device_register_full(&adev->dev, host, &info); if (IS_ERR(dsi)) return PTR_ERR(dsi); @@ -725,7 +725,7 @@ static int ti_sn_attach_host(struct ti_sn65dsi86 *pdata) pdata->dsi = dsi; - return devm_mipi_dsi_attach(dev, dsi); + return devm_mipi_dsi_attach(&adev->dev, dsi); } static int ti_sn_bridge_attach(struct drm_bridge *bridge, @@ -1298,9 +1298,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, struct device_node *np = pdata->dev->of_node; int ret; - pdata->next_bridge = devm_drm_of_get_bridge(pdata->dev, np, 1, 0); + pdata->next_bridge = devm_drm_of_get_bridge(&adev->dev, np, 1, 0); if (IS_ERR(pdata->next_bridge)) - return dev_err_probe(pdata->dev, PTR_ERR(pdata->next_bridge), + return dev_err_probe(&adev->dev, PTR_ERR(pdata->next_bridge), "failed to create panel bridge\n"); ti_sn_bridge_parse_lanes(pdata, np); @@ -1319,9 +1319,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, drm_bridge_add(&pdata->bridge); - ret = ti_sn_attach_host(pdata); + ret = ti_sn_attach_host(adev, pdata); if (ret) { - dev_err_probe(pdata->dev, ret, "failed to attach dsi host\n"); + dev_err_probe(&adev->dev, ret, "failed to attach dsi host\n"); goto err_remove_bridge; } diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 340da8257b51..4b71040ae5be 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -123,6 +123,9 @@ static const struct edid_quirk { /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */ EDID_QUIRK('A', 'E', 'O', 0, EDID_QUIRK_FORCE_6BPC), + /* BenQ GW2765 */ + EDID_QUIRK('B', 'N', 'Q', 0x78d6, EDID_QUIRK_FORCE_8BPC), + /* BOE model on HP Pavilion 15-n233sl reports 8 bpc, but is a 6 bpc panel */ EDID_QUIRK('B', 'O', 'E', 0x78b, EDID_QUIRK_FORCE_6BPC), diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 1b00ef2c6185..80e4ec6ee403 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2553,8 +2553,7 @@ static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915, drm_warn(&i915->drm, "PHY %c failed to bring out of SOC reset after %dus.\n", phy_name(phy), XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US); - intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port), - XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1), + intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port), lane_pipe_reset, lane_pipe_reset); if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL2(port), diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index aa4d842d4c5a..310654542b42 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -235,6 +235,7 @@ static vm_fault_t i915_error_to_vmf_fault(int err) case 0: case -EAGAIN: case -ENOSPC: /* transient failure to evict? */ + case -ENOBUFS: /* temporarily out of fences? */ case -ERESTARTSYS: case -EINTR: case -EBUSY: diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 9f364df52478..0e0a41b2f57f 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -239,6 +239,7 @@ int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) npages = obj->size >> PAGE_SHIFT; mtk_gem->pages = kcalloc(npages, sizeof(*mtk_gem->pages), GFP_KERNEL); if (!mtk_gem->pages) { + sg_free_table(sgt); kfree(sgt); return -ENOMEM; } @@ -248,12 +249,15 @@ int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); if (!mtk_gem->kvaddr) { + sg_free_table(sgt); kfree(sgt); kfree(mtk_gem->pages); return -ENOMEM; } -out: + sg_free_table(sgt); kfree(sgt); + +out: iosys_map_set_vaddr(map, mtk_gem->kvaddr); return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c index 46b057fe1412..3249e5c1c893 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c @@ -62,6 +62,18 @@ nvkm_uconn_uevent_gpio(struct nvkm_object *object, u64 token, u32 bits) return object->client->event(token, &args, sizeof(args.v0)); } +static bool +nvkm_connector_is_dp_dms(u8 type) +{ + switch (type) { + case DCB_CONNECTOR_DMS59_DP0: + case DCB_CONNECTOR_DMS59_DP1: + return true; + default: + return false; + } +} + static int nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent) { @@ -101,7 +113,7 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_ if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO; if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) { /* TODO: support DP IRQ on ANX9805 and remove this hack. */ - if (!outp->info.location) + if (!outp->info.location && !nvkm_connector_is_dp_dms(conn->info.type)) return -EINVAL; } diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index feb665df35a1..95c8472d878a 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -976,32 +976,6 @@ static const struct panel_desc auo_b116xak01 = { }, }; -static const struct drm_display_mode auo_b116xw03_mode = { - .clock = 70589, - .hdisplay = 1366, - .hsync_start = 1366 + 40, - .hsync_end = 1366 + 40 + 40, - .htotal = 1366 + 40 + 40 + 32, - .vdisplay = 768, - .vsync_start = 768 + 10, - .vsync_end = 768 + 10 + 12, - .vtotal = 768 + 10 + 12 + 6, - .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, -}; - -static const struct panel_desc auo_b116xw03 = { - .modes = &auo_b116xw03_mode, - .num_modes = 1, - .bpc = 6, - .size = { - .width = 256, - .height = 144, - }, - .delay = { - .enable = 400, - }, -}; - static const struct drm_display_mode auo_b133han05_mode = { .clock = 142600, .hdisplay = 1920, @@ -1726,9 +1700,6 @@ static const struct of_device_id platform_of_match[] = { .compatible = "auo,b116xa01", .data = &auo_b116xak01, }, { - .compatible = "auo,b116xw03", - .data = &auo_b116xw03, - }, { .compatible = "auo,b133han05", .data = &auo_b133han05, }, { diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 95959dcc6e0e..dd7928d9570f 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -919,6 +919,38 @@ static const struct panel_desc auo_b101xtn01 = { }, }; +static const struct drm_display_mode auo_b116xw03_mode = { + .clock = 70589, + .hdisplay = 1366, + .hsync_start = 1366 + 40, + .hsync_end = 1366 + 40 + 40, + .htotal = 1366 + 40 + 40 + 32, + .vdisplay = 768, + .vsync_start = 768 + 10, + .vsync_end = 768 + 10 + 12, + .vtotal = 768 + 10 + 12 + 6, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc auo_b116xw03 = { + .modes = &auo_b116xw03_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 256, + .height = 144, + }, + .delay = { + .prepare = 1, + .enable = 200, + .disable = 200, + .unprepare = 500, + }, + .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct display_timing auo_g070vvn01_timings = { .pixelclock = { 33300000, 34209000, 45000000 }, .hactive = { 800, 800, 800 }, @@ -4103,6 +4135,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "auo,b101xtn01", .data = &auo_b101xtn01, }, { + .compatible = "auo,b116xw03", + .data = &auo_b116xw03, + }, { .compatible = "auo,g070vvn01", .data = &auo_g070vvn01, }, { diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index 7726a72befc5..d48b39132b32 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -232,10 +232,6 @@ void ttm_device_fini(struct ttm_device *bdev) struct ttm_resource_manager *man; unsigned i; - man = ttm_manager_type(bdev, TTM_PL_SYSTEM); - ttm_resource_manager_set_used(man, false); - ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, NULL); - mutex_lock(&ttm_global_mutex); list_del(&bdev->device_list); mutex_unlock(&ttm_global_mutex); @@ -243,6 +239,10 @@ void ttm_device_fini(struct ttm_device *bdev) drain_workqueue(bdev->wq); destroy_workqueue(bdev->wq); + man = ttm_manager_type(bdev, TTM_PL_SYSTEM); + ttm_resource_manager_set_used(man, false); + ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, NULL); + spin_lock(&bdev->lru_lock); for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) if (list_empty(&man->lru[0])) diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c index 78d9f52e2a71..1ccdd61b6d13 100644 --- a/drivers/hwmon/xgene-hwmon.c +++ b/drivers/hwmon/xgene-hwmon.c @@ -57,12 +57,6 @@ (MSG_TYPE_SET(MSG_TYPE_PWRMGMT) | \ MSG_SUBTYPE_SET(hndl) | TPC_CMD_SET(cmd) | type) -/* PCC defines */ -#define PCC_SIGNATURE_MASK 0x50424300 -#define PCCC_GENERATE_DB_INT BIT(15) -#define PCCS_CMD_COMPLETE BIT(0) -#define PCCS_SCI_DOORBEL BIT(1) -#define PCCS_PLATFORM_NOTIFICATION BIT(3) /* * Arbitrary retries in case the remote processor is slow to respond * to PCC commands @@ -142,15 +136,15 @@ static int xgene_hwmon_pcc_rd(struct xgene_hwmon_dev *ctx, u32 *msg) /* Write signature for subspace */ WRITE_ONCE(generic_comm_base->signature, - cpu_to_le32(PCC_SIGNATURE_MASK | ctx->mbox_idx)); + cpu_to_le32(PCC_SIGNATURE | ctx->mbox_idx)); /* Write to the shared command region */ WRITE_ONCE(generic_comm_base->command, - cpu_to_le16(MSG_TYPE(msg[0]) | PCCC_GENERATE_DB_INT)); + cpu_to_le16(MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INTR)); /* Flip CMD COMPLETE bit */ val = le16_to_cpu(READ_ONCE(generic_comm_base->status)); - val &= ~PCCS_CMD_COMPLETE; + val &= ~PCC_STATUS_CMD_COMPLETE; WRITE_ONCE(generic_comm_base->status, cpu_to_le16(val)); /* Copy the message to the PCC comm space */ @@ -544,7 +538,7 @@ static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg) msg = generic_comm_base + 1; /* Check if platform sends interrupt */ if (!xgene_word_tst_and_clr(&generic_comm_base->status, - PCCS_SCI_DOORBEL)) + PCC_STATUS_SCI_DOORBELL)) return; /* @@ -566,7 +560,7 @@ static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg) TPC_CMD(((u32 *)msg)[0]) == TPC_ALARM))) { /* Check if platform completes command */ if (xgene_word_tst_and_clr(&generic_comm_base->status, - PCCS_CMD_COMPLETE)) { + PCC_STATUS_CMD_COMPLETE)) { ctx->sync_msg.msg = ((u32 *)msg)[0]; ctx->sync_msg.param1 = ((u32 *)msg)[1]; ctx->sync_msg.param2 = ((u32 *)msg)[2]; diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index fbc1ffbd2fa7..658396c9eeab 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -91,14 +91,6 @@ #define SLIMPRO_IIC_MSG_DWORD_COUNT 3 -/* PCC related defines */ -#define PCC_SIGNATURE 0x50424300 -#define PCC_STS_CMD_COMPLETE BIT(0) -#define PCC_STS_SCI_DOORBELL BIT(1) -#define PCC_STS_ERR BIT(2) -#define PCC_STS_PLAT_NOTIFY BIT(3) -#define PCC_CMD_GENERATE_DB_INT BIT(15) - struct slimpro_i2c_dev { struct i2c_adapter adapter; struct device *dev; @@ -160,11 +152,11 @@ static void slimpro_i2c_pcc_rx_cb(struct mbox_client *cl, void *msg) /* Check if platform sends interrupt */ if (!xgene_word_tst_and_clr(&generic_comm_base->status, - PCC_STS_SCI_DOORBELL)) + PCC_STATUS_SCI_DOORBELL)) return; if (xgene_word_tst_and_clr(&generic_comm_base->status, - PCC_STS_CMD_COMPLETE)) { + PCC_STATUS_CMD_COMPLETE)) { msg = generic_comm_base + 1; /* Response message msg[1] contains the return value. */ @@ -186,10 +178,10 @@ static void slimpro_i2c_pcc_tx_prepare(struct slimpro_i2c_dev *ctx, u32 *msg) cpu_to_le32(PCC_SIGNATURE | ctx->mbox_idx)); WRITE_ONCE(generic_comm_base->command, - cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INT)); + cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INTR)); status = le16_to_cpu(READ_ONCE(generic_comm_base->status)); - status &= ~PCC_STS_CMD_COMPLETE; + status &= ~PCC_STATUS_CMD_COMPLETE; WRITE_ONCE(generic_comm_base->status, cpu_to_le16(status)); /* Copy the message to the PCC comm space */ diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index a44d4b3e5beb..94885e411085 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -91,6 +91,14 @@ struct pcc_chan_reg { * @cmd_update: PCC register bundle for the command complete update register * @error: PCC register bundle for the error status register * @plat_irq: platform interrupt + * @type: PCC subspace type + * @plat_irq_flags: platform interrupt flags + * @chan_in_use: this flag is used just to check if the interrupt needs + * handling when it is shared. Since only one transfer can occur + * at a time and mailbox takes care of locking, this flag can be + * accessed without a lock. Note: the type only support the + * communication from OSPM to Platform, like type3, use it, and + * other types completely ignore it. */ struct pcc_chan_info { struct pcc_mbox_chan chan; @@ -100,12 +108,17 @@ struct pcc_chan_info { struct pcc_chan_reg cmd_update; struct pcc_chan_reg error; int plat_irq; + u8 type; + unsigned int plat_irq_flags; + bool chan_in_use; }; #define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan) static struct pcc_chan_info *chan_info; static int pcc_chan_count; +static int pcc_send_data(struct mbox_chan *chan, void *data); + /* * PCC can be used with perf critical drivers such as CPPC * So it makes sense to locally cache the virtual address and @@ -221,6 +234,41 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags) return acpi_register_gsi(NULL, interrupt, trigger, polarity); } +static bool pcc_chan_plat_irq_can_be_shared(struct pcc_chan_info *pchan) +{ + return (pchan->plat_irq_flags & ACPI_PCCT_INTERRUPT_MODE) == + ACPI_LEVEL_SENSITIVE; +} + +static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) +{ + u64 val; + int ret; + + ret = pcc_chan_reg_read(&pchan->cmd_complete, &val); + if (ret) + return false; + + if (!pchan->cmd_complete.gas) + return true; + + /* + * Judge if the channel respond the interrupt based on the value of + * command complete. + */ + val &= pchan->cmd_complete.status_mask; + + /* + * If this is PCC slave subspace channel, and the command complete + * bit 0 indicates that Platform is sending a notification and OSPM + * needs to respond this interrupt to process this command. + */ + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) + return !val; + + return !!val; +} + /** * pcc_mbox_irq - PCC mailbox interrupt handler * @irq: interrupt number @@ -236,16 +284,12 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) int ret; pchan = chan->con_priv; - - ret = pcc_chan_reg_read(&pchan->cmd_complete, &val); - if (ret) + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE && + !pchan->chan_in_use) return IRQ_NONE; - if (val) { /* Ensure GAS exists and value is non-zero */ - val &= pchan->cmd_complete.status_mask; - if (!val) - return IRQ_NONE; - } + if (!pcc_mbox_cmd_complete_check(pchan)) + return IRQ_NONE; ret = pcc_chan_reg_read(&pchan->error, &val); if (ret) @@ -262,6 +306,16 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) mbox_chan_received_data(chan, NULL); + /* + * The PCC slave subspace channel needs to set the command complete bit + * and ring doorbell after processing message. + * + * The PCC master subspace channel clears chan_in_use to free channel. + */ + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) + pcc_send_data(chan, NULL); + pchan->chan_in_use = false; + return IRQ_HANDLED; } @@ -340,7 +394,11 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) if (ret) return ret; - return pcc_chan_reg_read_modify_write(&pchan->db); + ret = pcc_chan_reg_read_modify_write(&pchan->db); + if (!ret && pchan->plat_irq > 0) + pchan->chan_in_use = true; + + return ret; } /** @@ -353,11 +411,14 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) static int pcc_startup(struct mbox_chan *chan) { struct pcc_chan_info *pchan = chan->con_priv; + unsigned long irqflags; int rc; if (pchan->plat_irq > 0) { - rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0, - MBOX_IRQ_NAME, chan); + irqflags = pcc_chan_plat_irq_can_be_shared(pchan) ? + IRQF_SHARED | IRQF_ONESHOT : 0; + rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, + irqflags, MBOX_IRQ_NAME, chan); if (unlikely(rc)) { dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n", pchan->plat_irq); @@ -463,6 +524,7 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan, pcct_ss->platform_interrupt); return -EINVAL; } + pchan->plat_irq_flags = pcct_ss->flags; if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) { struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss; @@ -484,6 +546,12 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan, "PLAT IRQ ACK"); } + if (pcc_chan_plat_irq_can_be_shared(pchan) && + !pchan->plat_irq_ack.gas) { + pr_err("PCC subspace has level IRQ with no ACK register\n"); + return -EINVAL; + } + return ret; } @@ -698,6 +766,7 @@ static int pcc_mbox_probe(struct platform_device *pdev) pcc_parse_subspace_shmem(pchan, pcct_entry); + pchan->type = pcct_entry->type; pcct_entry = (struct acpi_subtable_header *) ((unsigned long) pcct_entry + pcct_entry->length); } diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index b5b414a71e0b..3a8f27c3e310 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -179,6 +179,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, struct mmc_queue *mq); static void mmc_blk_hsq_req_done(struct mmc_request *mrq); static int mmc_spi_err_check(struct mmc_card *card); +static int mmc_blk_busy_cb(void *cb_data, bool *busy); static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) { @@ -470,7 +471,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, struct mmc_data data = {}; struct mmc_request mrq = {}; struct scatterlist sg; - bool r1b_resp, use_r1b_resp = false; + bool r1b_resp; unsigned int busy_timeout_ms; int err; unsigned int target_part; @@ -551,8 +552,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, busy_timeout_ms = idata->ic.cmd_timeout_ms ? : MMC_BLK_TIMEOUT_MS; r1b_resp = (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B; if (r1b_resp) - use_r1b_resp = mmc_prepare_busy_cmd(card->host, &cmd, - busy_timeout_ms); + mmc_prepare_busy_cmd(card->host, &cmd, busy_timeout_ms); mmc_wait_for_req(card->host, &mrq); memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp)); @@ -605,19 +605,28 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, if (idata->ic.postsleep_min_us) usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us); - /* No need to poll when using HW busy detection. */ - if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) - return 0; - if (mmc_host_is_spi(card->host)) { if (idata->ic.write_flag || r1b_resp || cmd.flags & MMC_RSP_SPI_BUSY) return mmc_spi_err_check(card); return err; } - /* Ensure RPMB/R1B command has completed by polling with CMD13. */ - if (idata->rpmb || r1b_resp) - err = mmc_poll_for_busy(card, busy_timeout_ms, false, - MMC_BUSY_IO); + + /* + * Ensure RPMB, writes and R1B responses are completed by polling with + * CMD13. Note that, usually we don't need to poll when using HW busy + * detection, but here it's needed since some commands may indicate the + * error through the R1 status bits. + */ + if (idata->rpmb || idata->ic.write_flag || r1b_resp) { + struct mmc_blk_busy_data cb_data = { + .card = card, + }; + + err = __mmc_poll_for_busy(card->host, 0, busy_timeout_ms, + &mmc_blk_busy_cb, &cb_data); + + idata->ic.response[0] = cb_data.status; + } return err; } diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 89cd48fcec79..4a4bab9aa726 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -104,7 +104,7 @@ static int mmc_decode_cid(struct mmc_card *card) case 3: /* MMC v3.1 - v3.3 */ case 4: /* MMC v4 */ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); - card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); + card->cid.oemid = UNSTUFF_BITS(resp, 104, 8); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index f64b9ac76a5c..5914516df2f7 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1089,8 +1089,14 @@ static int mmc_sdio_resume(struct mmc_host *host) } err = mmc_sdio_reinit_card(host); } else if (mmc_card_wake_sdio_irq(host)) { - /* We may have switched to 1-bit mode during suspend */ + /* + * We may have switched to 1-bit mode during suspend, + * need to hold retuning, because tuning only supprt + * 4-bit mode or 8 bit mode. + */ + mmc_retune_hold_now(host); err = sdio_enable_4bit_bus(host->card); + mmc_retune_release(host); } if (err) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 5392200cfdf7..97f7c3d4be6e 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -669,11 +669,11 @@ static void msdc_reset_hw(struct msdc_host *host) u32 val; sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST); - readl_poll_timeout(host->base + MSDC_CFG, val, !(val & MSDC_CFG_RST), 0, 0); + readl_poll_timeout_atomic(host->base + MSDC_CFG, val, !(val & MSDC_CFG_RST), 0, 0); sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR); - readl_poll_timeout(host->base + MSDC_FIFOCS, val, - !(val & MSDC_FIFOCS_CLR), 0, 0); + readl_poll_timeout_atomic(host->base + MSDC_FIFOCS, val, + !(val & MSDC_FIFOCS_CLR), 0, 0); val = readl(host->base + MSDC_INT); writel(val, host->base + MSDC_INT); diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index ae8c307b7aa7..109d4b010f97 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -1144,42 +1144,6 @@ static u32 sdhci_gl9750_readl(struct sdhci_host *host, int reg) return value; } -#ifdef CONFIG_PM_SLEEP -static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip) -{ - struct sdhci_pci_slot *slot = chip->slots[0]; - - pci_free_irq_vectors(slot->chip->pdev); - gli_pcie_enable_msi(slot); - - return sdhci_pci_resume_host(chip); -} - -static int sdhci_cqhci_gli_resume(struct sdhci_pci_chip *chip) -{ - struct sdhci_pci_slot *slot = chip->slots[0]; - int ret; - - ret = sdhci_pci_gli_resume(chip); - if (ret) - return ret; - - return cqhci_resume(slot->host->mmc); -} - -static int sdhci_cqhci_gli_suspend(struct sdhci_pci_chip *chip) -{ - struct sdhci_pci_slot *slot = chip->slots[0]; - int ret; - - ret = cqhci_suspend(slot->host->mmc); - if (ret) - return ret; - - return sdhci_suspend_host(slot->host); -} -#endif - static void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios) { @@ -1420,6 +1384,70 @@ static int gl9763e_runtime_resume(struct sdhci_pci_chip *chip) } #endif +#ifdef CONFIG_PM_SLEEP +static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip) +{ + struct sdhci_pci_slot *slot = chip->slots[0]; + + pci_free_irq_vectors(slot->chip->pdev); + gli_pcie_enable_msi(slot); + + return sdhci_pci_resume_host(chip); +} + +static int gl9763e_resume(struct sdhci_pci_chip *chip) +{ + struct sdhci_pci_slot *slot = chip->slots[0]; + int ret; + + ret = sdhci_pci_gli_resume(chip); + if (ret) + return ret; + + ret = cqhci_resume(slot->host->mmc); + if (ret) + return ret; + + /* + * Disable LPM negotiation to bring device back in sync + * with its runtime_pm state. + */ + gl9763e_set_low_power_negotiation(slot, false); + + return 0; +} + +static int gl9763e_suspend(struct sdhci_pci_chip *chip) +{ + struct sdhci_pci_slot *slot = chip->slots[0]; + int ret; + + /* + * Certain SoCs can suspend only with the bus in low- + * power state, notably x86 SoCs when using S0ix. + * Re-enable LPM negotiation to allow entering L1 state + * and entering system suspend. + */ + gl9763e_set_low_power_negotiation(slot, true); + + ret = cqhci_suspend(slot->host->mmc); + if (ret) + goto err_suspend; + + ret = sdhci_suspend_host(slot->host); + if (ret) + goto err_suspend_host; + + return 0; + +err_suspend_host: + cqhci_resume(slot->host->mmc); +err_suspend: + gl9763e_set_low_power_negotiation(slot, false); + return ret; +} +#endif + static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) { struct pci_dev *pdev = slot->chip->pdev; @@ -1527,8 +1555,8 @@ const struct sdhci_pci_fixes sdhci_gl9763e = { .probe_slot = gli_probe_slot_gl9763e, .ops = &sdhci_gl9763e_ops, #ifdef CONFIG_PM_SLEEP - .resume = sdhci_cqhci_gli_resume, - .suspend = sdhci_cqhci_gli_suspend, + .resume = gl9763e_resume, + .suspend = gl9763e_suspend, #endif #ifdef CONFIG_PM .runtime_suspend = gl9763e_runtime_suspend, diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 649ae075e229..6b84ba27e6ab 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -644,6 +644,7 @@ static int sdhci_sprd_tuning(struct mmc_host *mmc, struct mmc_card *card, best_clk_sample = sdhci_sprd_get_best_clk_sample(mmc, value); if (best_clk_sample < 0) { dev_err(mmc_dev(host->mmc), "all tuning phase fail!\n"); + err = best_clk_sample; goto out; } diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index 78710fbc8e7f..fc8721339282 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c @@ -551,6 +551,17 @@ static int physmap_flash_probe(struct platform_device *dev) if (info->probe_type) { info->mtds[i] = do_map_probe(info->probe_type, &info->maps[i]); + + /* Fall back to mapping region as ROM */ + if (!info->mtds[i] && IS_ENABLED(CONFIG_MTD_ROM) && + strcmp(info->probe_type, "map_rom")) { + dev_warn(&dev->dev, + "map_probe() failed for type %s\n", + info->probe_type); + + info->mtds[i] = do_map_probe("map_rom", + &info->maps[i]); + } } else { int j; diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c index 4621ec549cc7..a492051c46f5 100644 --- a/drivers/mtd/nand/raw/arasan-nand-controller.c +++ b/drivers/mtd/nand/raw/arasan-nand-controller.c @@ -515,6 +515,7 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, struct mtd_info *mtd = nand_to_mtd(chip); unsigned int len = mtd->writesize + (oob_required ? mtd->oobsize : 0); dma_addr_t dma_addr; + u8 status; int ret; struct anfc_op nfc_op = { .pkt_reg = @@ -561,10 +562,21 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, } /* Spare data is not protected */ - if (oob_required) + if (oob_required) { ret = nand_write_oob_std(chip, page); + if (ret) + return ret; + } - return ret; + /* Check write status on the chip side */ + ret = nand_status_op(chip, &status); + if (ret) + return ret; + + if (status & NAND_STATUS_FAIL) + return -EIO; + + return 0; } static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 2c94da7a3b3a..b841a81cb128 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -1165,6 +1165,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, .ndcb[2] = NDCB2_ADDR5_PAGE(page), }; unsigned int oob_bytes = lt->spare_bytes + (raw ? lt->ecc_bytes : 0); + u8 status; int ret; /* NFCv2 needs more information about the operation being executed */ @@ -1198,7 +1199,18 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, ret = marvell_nfc_wait_op(chip, PSEC_TO_MSEC(sdr->tPROG_max)); - return ret; + if (ret) + return ret; + + /* Check write status on the chip side */ + ret = nand_status_op(chip, &status); + if (ret) + return ret; + + if (status & NAND_STATUS_FAIL) + return -EIO; + + return 0; } static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct nand_chip *chip, @@ -1627,6 +1639,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, int data_len = lt->data_bytes; int spare_len = lt->spare_bytes; int chunk, ret; + u8 status; marvell_nfc_select_target(chip, chip->cur_cs); @@ -1663,6 +1676,14 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, if (ret) return ret; + /* Check write status on the chip side */ + ret = nand_status_op(chip, &status); + if (ret) + return ret; + + if (status & NAND_STATUS_FAIL) + return -EIO; + return 0; } diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index d4b55155aeae..1fcac403cee6 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -5110,6 +5110,9 @@ static void rawnand_check_cont_read_support(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); + if (!chip->parameters.supports_read_cache) + return; + if (chip->read_retries) return; diff --git a/drivers/mtd/nand/raw/nand_jedec.c b/drivers/mtd/nand/raw/nand_jedec.c index 836757717660..b3cc8f360529 100644 --- a/drivers/mtd/nand/raw/nand_jedec.c +++ b/drivers/mtd/nand/raw/nand_jedec.c @@ -94,6 +94,9 @@ int nand_jedec_detect(struct nand_chip *chip) goto free_jedec_param_page; } + if (p->opt_cmd[0] & JEDEC_OPT_CMD_READ_CACHE) + chip->parameters.supports_read_cache = true; + memorg->pagesize = le32_to_cpu(p->byte_per_page); mtd->writesize = memorg->pagesize; diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c index f15ef90aec8c..861975e44b55 100644 --- a/drivers/mtd/nand/raw/nand_onfi.c +++ b/drivers/mtd/nand/raw/nand_onfi.c @@ -303,6 +303,9 @@ int nand_onfi_detect(struct nand_chip *chip) ONFI_FEATURE_ADDR_TIMING_MODE, 1); } + if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_READ_CACHE) + chip->parameters.supports_read_cache = true; + onfi = kzalloc(sizeof(*onfi), GFP_KERNEL); if (!onfi) { ret = -ENOMEM; diff --git a/drivers/mtd/nand/raw/pl35x-nand-controller.c b/drivers/mtd/nand/raw/pl35x-nand-controller.c index 8da5fee321b5..c506e92a3e45 100644 --- a/drivers/mtd/nand/raw/pl35x-nand-controller.c +++ b/drivers/mtd/nand/raw/pl35x-nand-controller.c @@ -511,6 +511,7 @@ static int pl35x_nand_write_page_hwecc(struct nand_chip *chip, u32 addr1 = 0, addr2 = 0, row; u32 cmd_addr; int i, ret; + u8 status; ret = pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_APB); if (ret) @@ -563,6 +564,14 @@ static int pl35x_nand_write_page_hwecc(struct nand_chip *chip, if (ret) goto disable_ecc_engine; + /* Check write status on the chip side */ + ret = nand_status_op(chip, &status); + if (ret) + goto disable_ecc_engine; + + if (status & NAND_STATUS_FAIL) + ret = -EIO; + disable_ecc_engine: pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS); diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 64499c1b3603..b079605c84d3 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -3444,7 +3444,7 @@ err_nandc_alloc: err_aon_clk: clk_disable_unprepare(nandc->core_clk); err_core_clk: - dma_unmap_resource(dev, res->start, resource_size(res), + dma_unmap_resource(dev, nandc->base_dma, resource_size(res), DMA_BIDIRECTIONAL, 0); return ret; } diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c index 50b7295bc922..12601bc4227a 100644 --- a/drivers/mtd/nand/spi/micron.c +++ b/drivers/mtd/nand/spi/micron.c @@ -12,7 +12,7 @@ #define SPINAND_MFR_MICRON 0x2c -#define MICRON_STATUS_ECC_MASK GENMASK(7, 4) +#define MICRON_STATUS_ECC_MASK GENMASK(6, 4) #define MICRON_STATUS_ECC_NO_BITFLIPS (0 << 4) #define MICRON_STATUS_ECC_1TO3_BITFLIPS (1 << 4) #define MICRON_STATUS_ECC_4TO6_BITFLIPS (3 << 4) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index ed7212e61c54..51d47eda1c87 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4023,7 +4023,7 @@ static inline const void *bond_pull_data(struct sk_buff *skb, if (likely(n <= hlen)) return data; else if (skb && likely(pskb_may_pull(skb, n))) - return skb->head; + return skb->data; return NULL; } diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 72374b066f64..cd1f240c90f3 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -617,17 +617,16 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) dn = of_find_compatible_node(NULL, NULL, "brcm,unimac-mdio"); priv->master_mii_bus = of_mdio_find_bus(dn); if (!priv->master_mii_bus) { - of_node_put(dn); - return -EPROBE_DEFER; + err = -EPROBE_DEFER; + goto err_of_node_put; } - get_device(&priv->master_mii_bus->dev); priv->master_mii_dn = dn; priv->slave_mii_bus = mdiobus_alloc(); if (!priv->slave_mii_bus) { - of_node_put(dn); - return -ENOMEM; + err = -ENOMEM; + goto err_put_master_mii_bus_dev; } priv->slave_mii_bus->priv = priv; @@ -684,11 +683,17 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) } err = mdiobus_register(priv->slave_mii_bus); - if (err && dn) { - mdiobus_free(priv->slave_mii_bus); - of_node_put(dn); - } + if (err && dn) + goto err_free_slave_mii_bus; + return 0; + +err_free_slave_mii_bus: + mdiobus_free(priv->slave_mii_bus); +err_put_master_mii_bus_dev: + put_device(&priv->master_mii_bus->dev); +err_of_node_put: + of_node_put(dn); return err; } @@ -696,6 +701,7 @@ static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv *priv) { mdiobus_unregister(priv->slave_mii_bus); mdiobus_free(priv->slave_mii_bus); + put_device(&priv->master_mii_bus->dev); of_node_put(priv->master_mii_dn); } diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c index 5fc64e47568a..d567e42e1760 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c @@ -911,7 +911,7 @@ static int csk_wait_memory(struct chtls_dev *cdev, struct sock *sk, long *timeo_p) { DEFINE_WAIT_FUNC(wait, woken_wake_function); - int err = 0; + int ret, err = 0; long current_timeo; long vm_wait = 0; bool noblock; @@ -942,10 +942,13 @@ static int csk_wait_memory(struct chtls_dev *cdev, set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); sk->sk_write_pending++; - sk_wait_event(sk, ¤t_timeo, sk->sk_err || - (sk->sk_shutdown & SEND_SHUTDOWN) || - (csk_mem_free(cdev, sk) && !vm_wait), &wait); + ret = sk_wait_event(sk, ¤t_timeo, sk->sk_err || + (sk->sk_shutdown & SEND_SHUTDOWN) || + (csk_mem_free(cdev, sk) && !vm_wait), + &wait); sk->sk_write_pending--; + if (ret < 0) + goto do_error; if (vm_wait) { vm_wait -= current_timeo; @@ -1348,6 +1351,7 @@ static int chtls_pt_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int copied = 0; int target; long timeo; + int ret; buffers_freed = 0; @@ -1423,7 +1427,11 @@ static int chtls_pt_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, if (copied >= target) break; chtls_cleanup_rbuf(sk, copied); - sk_wait_data(sk, &timeo, NULL); + ret = sk_wait_data(sk, &timeo, NULL); + if (ret < 0) { + copied = copied ? : ret; + goto unlock; + } continue; found_ok_skb: if (!skb->len) { @@ -1518,6 +1526,8 @@ skip_copy: if (buffers_freed) chtls_cleanup_rbuf(sk, copied); + +unlock: release_sock(sk); return copied; } @@ -1534,6 +1544,7 @@ static int peekmsg(struct sock *sk, struct msghdr *msg, int copied = 0; size_t avail; /* amount of available data in current skb */ long timeo; + int ret; lock_sock(sk); timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); @@ -1585,7 +1596,12 @@ static int peekmsg(struct sock *sk, struct msghdr *msg, release_sock(sk); lock_sock(sk); } else { - sk_wait_data(sk, &timeo, NULL); + ret = sk_wait_data(sk, &timeo, NULL); + if (ret < 0) { + /* here 'copied' is 0 due to previous checks */ + copied = ret; + break; + } } if (unlikely(peek_seq != tp->copied_seq)) { @@ -1656,6 +1672,7 @@ int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int copied = 0; long timeo; int target; /* Read at least this many bytes */ + int ret; buffers_freed = 0; @@ -1747,7 +1764,11 @@ int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, if (copied >= target) break; chtls_cleanup_rbuf(sk, copied); - sk_wait_data(sk, &timeo, NULL); + ret = sk_wait_data(sk, &timeo, NULL); + if (ret < 0) { + copied = copied ? : ret; + goto unlock; + } continue; found_ok_skb: @@ -1816,6 +1837,7 @@ skip_copy: if (buffers_freed) chtls_cleanup_rbuf(sk, copied); +unlock: release_sock(sk); return copied; } diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c index d1da7413dc4d..e84a066aa1a4 100644 --- a/drivers/net/ethernet/google/gve/gve_rx.c +++ b/drivers/net/ethernet/google/gve/gve_rx.c @@ -146,7 +146,7 @@ static int gve_prefill_rx_pages(struct gve_rx_ring *rx) err = gve_rx_alloc_buffer(priv, &priv->pdev->dev, &rx->data.page_info[i], &rx->data.data_ring[i]); if (err) - goto alloc_err; + goto alloc_err_rda; } if (!rx->data.raw_addressing) { @@ -171,12 +171,26 @@ static int gve_prefill_rx_pages(struct gve_rx_ring *rx) return slots; alloc_err_qpl: + /* Fully free the copy pool pages. */ while (j--) { page_ref_sub(rx->qpl_copy_pool[j].page, rx->qpl_copy_pool[j].pagecnt_bias - 1); put_page(rx->qpl_copy_pool[j].page); } -alloc_err: + + /* Do not fully free QPL pages - only remove the bias added in this + * function with gve_setup_rx_buffer. + */ + while (i--) + page_ref_sub(rx->data.page_info[i].page, + rx->data.page_info[i].pagecnt_bias - 1); + + gve_unassign_qpl(priv, rx->data.qpl->id); + rx->data.qpl = NULL; + + return err; + +alloc_err_rda: while (i--) gve_rx_free_buffer(&priv->pdev->dev, &rx->data.page_info[i], diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index eeef20f77106..1b493854f522 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1082,7 +1082,7 @@ void i40e_clear_hw(struct i40e_hw *hw) I40E_PFLAN_QALLOC_FIRSTQ_SHIFT; j = (val & I40E_PFLAN_QALLOC_LASTQ_MASK) >> I40E_PFLAN_QALLOC_LASTQ_SHIFT; - if (val & I40E_PFLAN_QALLOC_VALID_MASK) + if (val & I40E_PFLAN_QALLOC_VALID_MASK && j >= base_queue) num_queues = (j - base_queue) + 1; else num_queues = 0; @@ -1092,7 +1092,7 @@ void i40e_clear_hw(struct i40e_hw *hw) I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT; j = (val & I40E_PF_VT_PFALLOC_LASTVF_MASK) >> I40E_PF_VT_PFALLOC_LASTVF_SHIFT; - if (val & I40E_PF_VT_PFALLOC_VALID_MASK) + if (val & I40E_PF_VT_PFALLOC_VALID_MASK && j >= i) num_vfs = (j - i) + 1; else num_vfs = 0; diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 7bf9b7069754..73bbf06a76db 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1201,8 +1201,7 @@ static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | - ((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) & - ICE_AQ_VSI_Q_OPT_RSS_HASH_M); + (hash_type & ICE_AQ_VSI_Q_OPT_RSS_HASH_M); } static void diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index c8286adae946..7784135160fd 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -6,6 +6,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <generated/utsrelease.h> +#include <linux/crash_dump.h> #include "ice.h" #include "ice_base.h" #include "ice_lib.h" @@ -4683,6 +4684,9 @@ static void ice_init_features(struct ice_pf *pf) static void ice_deinit_features(struct ice_pf *pf) { + if (ice_is_safe_mode(pf)) + return; + ice_deinit_lag(pf); if (test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)) ice_cfg_lldp_mib_change(&pf->hw, false); @@ -5014,6 +5018,20 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) return -EINVAL; } + /* when under a kdump kernel initiate a reset before enabling the + * device in order to clear out any pending DMA transactions. These + * transactions can cause some systems to machine check when doing + * the pcim_enable_device() below. + */ + if (is_kdump_kernel()) { + pci_save_state(pdev); + pci_clear_master(pdev); + err = pcie_flr(pdev); + if (err) + return err; + pci_restore_state(pdev); + } + /* this driver uses devres, see * Documentation/driver-api/driver-model/devres.rst */ diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c index dbc518ff8276..5b46ca47c8e5 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c @@ -715,20 +715,19 @@ static netdev_tx_t octep_start_xmit(struct sk_buff *skb, hw_desc->dptr = tx_buffer->sglist_dma; } - /* Flush the hw descriptor before writing to doorbell */ - wmb(); - - /* Ring Doorbell to notify the NIC there is a new packet */ - writel(1, iq->doorbell_reg); + netdev_tx_sent_queue(iq->netdev_q, skb->len); + skb_tx_timestamp(skb); atomic_inc(&iq->instr_pending); wi++; if (wi == iq->max_count) wi = 0; iq->host_write_index = wi; + /* Flush the hw descriptor before writing to doorbell */ + wmb(); - netdev_tx_sent_queue(iq->netdev_q, skb->len); + /* Ring Doorbell to notify the NIC there is a new packet */ + writel(1, iq->doorbell_reg); iq->stats.instr_posted++; - skb_tx_timestamp(skb); return NETDEV_TX_OK; dma_map_sg_err: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index afb348579577..c22b0ad0c870 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -2186,52 +2186,23 @@ static u16 cmdif_rev(struct mlx5_core_dev *dev) int mlx5_cmd_init(struct mlx5_core_dev *dev) { - int size = sizeof(struct mlx5_cmd_prot_block); - int align = roundup_pow_of_two(size); struct mlx5_cmd *cmd = &dev->cmd; - u32 cmd_l; - int err; - - cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0); - if (!cmd->pool) - return -ENOMEM; - err = alloc_cmd_page(dev, cmd); - if (err) - goto err_free_pool; - - cmd_l = (u32)(cmd->dma); - if (cmd_l & 0xfff) { - mlx5_core_err(dev, "invalid command queue address\n"); - err = -ENOMEM; - goto err_cmd_page; - } cmd->checksum_disabled = 1; spin_lock_init(&cmd->alloc_lock); spin_lock_init(&cmd->token_lock); - create_msg_cache(dev); - set_wqname(dev); cmd->wq = create_singlethread_workqueue(cmd->wq_name); if (!cmd->wq) { mlx5_core_err(dev, "failed to create command workqueue\n"); - err = -ENOMEM; - goto err_cache; + return -ENOMEM; } mlx5_cmdif_debugfs_init(dev); return 0; - -err_cache: - destroy_msg_cache(dev); -err_cmd_page: - free_cmd_page(dev, cmd); -err_free_pool: - dma_pool_destroy(cmd->pool); - return err; } void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) @@ -2240,15 +2211,15 @@ void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) mlx5_cmdif_debugfs_cleanup(dev); destroy_workqueue(cmd->wq); - destroy_msg_cache(dev); - free_cmd_page(dev, cmd); - dma_pool_destroy(cmd->pool); } int mlx5_cmd_enable(struct mlx5_core_dev *dev) { + int size = sizeof(struct mlx5_cmd_prot_block); + int align = roundup_pow_of_two(size); struct mlx5_cmd *cmd = &dev->cmd; u32 cmd_h, cmd_l; + int err; memset(&cmd->vars, 0, sizeof(cmd->vars)); cmd->vars.cmdif_rev = cmdif_rev(dev); @@ -2281,10 +2252,21 @@ int mlx5_cmd_enable(struct mlx5_core_dev *dev) sema_init(&cmd->vars.pages_sem, 1); sema_init(&cmd->vars.throttle_sem, DIV_ROUND_UP(cmd->vars.max_reg_cmds, 2)); + cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0); + if (!cmd->pool) + return -ENOMEM; + + err = alloc_cmd_page(dev, cmd); + if (err) + goto err_free_pool; + cmd_h = (u32)((u64)(cmd->dma) >> 32); cmd_l = (u32)(cmd->dma); - if (WARN_ON(cmd_l & 0xfff)) - return -EINVAL; + if (cmd_l & 0xfff) { + mlx5_core_err(dev, "invalid command queue address\n"); + err = -ENOMEM; + goto err_cmd_page; + } iowrite32be(cmd_h, &dev->iseg->cmdq_addr_h); iowrite32be(cmd_l, &dev->iseg->cmdq_addr_l_sz); @@ -2297,17 +2279,27 @@ int mlx5_cmd_enable(struct mlx5_core_dev *dev) cmd->mode = CMD_MODE_POLLING; cmd->allowed_opcode = CMD_ALLOWED_OPCODE_ALL; + create_msg_cache(dev); create_debugfs_files(dev); return 0; + +err_cmd_page: + free_cmd_page(dev, cmd); +err_free_pool: + dma_pool_destroy(cmd->pool); + return err; } void mlx5_cmd_disable(struct mlx5_core_dev *dev) { struct mlx5_cmd *cmd = &dev->cmd; - clean_debug_files(dev); flush_workqueue(cmd->wq); + clean_debug_files(dev); + destroy_msg_cache(dev); + free_cmd_page(dev, cmd); + dma_pool_destroy(cmd->pool); } void mlx5_cmd_set_state(struct mlx5_core_dev *dev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c index 7c0f2adbea00..ad789349c06e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c @@ -848,7 +848,7 @@ static void mlx5_fw_tracer_ownership_change(struct work_struct *work) mlx5_core_dbg(tracer->dev, "FWTracer: ownership changed, current=(%d)\n", tracer->owner); if (tracer->owner) { - tracer->owner = false; + mlx5_fw_tracer_ownership_acquire(tracer); return; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c index 0fef853eab62..5d128c5b4529 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c @@ -467,6 +467,17 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb, /* only handle the event on peers */ if (mlx5_esw_bridge_is_local(dev, rep, esw)) break; + + fdb_info = container_of(info, + struct switchdev_notifier_fdb_info, + info); + /* Mark for deletion to prevent the update wq task from + * spuriously refreshing the entry which would mark it again as + * offloaded in SW bridge. After this fallthrough to regular + * async delete code. + */ + mlx5_esw_bridge_fdb_mark_deleted(dev, vport_num, esw_owner_vhca_id, br_offloads, + fdb_info); fallthrough; case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c index 1730f6a716ee..b10e40e1a9c1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c @@ -24,7 +24,8 @@ static int mlx5e_set_int_port_tunnel(struct mlx5e_priv *priv, route_dev = dev_get_by_index(dev_net(e->out_dev), e->route_dev_ifindex); - if (!route_dev || !netif_is_ovs_master(route_dev)) + if (!route_dev || !netif_is_ovs_master(route_dev) || + attr->parse_attr->filter_dev == e->out_dev) goto out; err = mlx5e_set_fwd_to_int_port_actions(priv, attr, e->route_dev_ifindex, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index 12f56d0db0af..8bed17d8fe56 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -874,11 +874,11 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, } out: - if (flags & XDP_XMIT_FLUSH) { - if (sq->mpwqe.wqe) - mlx5e_xdp_mpwqe_complete(sq); + if (sq->mpwqe.wqe) + mlx5e_xdp_mpwqe_complete(sq); + + if (flags & XDP_XMIT_FLUSH) mlx5e_xmit_xdp_doorbell(sq); - } return nxmit; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 2fdb8895aecd..fd1cce542b68 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -701,7 +701,7 @@ mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) /* update HW stats in background for next time */ mlx5e_queue_update_stats(priv); - memcpy(stats, &priv->stats.vf_vport, sizeof(*stats)); + mlx5e_stats_copy_rep_stats(stats, &priv->stats.rep_stats); } static int mlx5e_rep_change_mtu(struct net_device *netdev, int new_mtu) @@ -769,6 +769,7 @@ static int mlx5e_rep_max_nch_limit(struct mlx5_core_dev *mdev) static void mlx5e_build_rep_params(struct net_device *netdev) { + const bool take_rtnl = netdev->reg_state == NETREG_REGISTERED; struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5_eswitch_rep *rep = rpriv->rep; @@ -794,8 +795,15 @@ static void mlx5e_build_rep_params(struct net_device *netdev) /* RQ */ mlx5e_build_rq_params(mdev, params); + /* If netdev is already registered (e.g. move from nic profile to uplink, + * RTNL lock must be held before triggering netdev notifiers. + */ + if (take_rtnl) + rtnl_lock(); /* update XDP supported features */ mlx5e_set_xdp_feature(netdev); + if (take_rtnl) + rtnl_unlock(); /* CQ moderation params */ params->rx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 3fd11b0761e0..8d9743a5e42c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -457,26 +457,41 @@ static int mlx5e_alloc_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk) static int mlx5e_refill_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk) { int remaining = wqe_bulk; - int i = 0; + int total_alloc = 0; + int refill_alloc; + int refill; /* The WQE bulk is split into smaller bulks that are sized * according to the page pool cache refill size to avoid overflowing * the page pool cache due to too many page releases at once. */ do { - int refill = min_t(u16, rq->wqe.info.refill_unit, remaining); - int alloc_count; + refill = min_t(u16, rq->wqe.info.refill_unit, remaining); - mlx5e_free_rx_wqes(rq, ix + i, refill); - alloc_count = mlx5e_alloc_rx_wqes(rq, ix + i, refill); - i += alloc_count; - if (unlikely(alloc_count != refill)) - break; + mlx5e_free_rx_wqes(rq, ix + total_alloc, refill); + refill_alloc = mlx5e_alloc_rx_wqes(rq, ix + total_alloc, refill); + if (unlikely(refill_alloc != refill)) + goto err_free; + total_alloc += refill_alloc; remaining -= refill; } while (remaining); - return i; + return total_alloc; + +err_free: + mlx5e_free_rx_wqes(rq, ix, total_alloc + refill_alloc); + + for (int i = 0; i < total_alloc + refill; i++) { + int j = mlx5_wq_cyc_ctr2ix(&rq->wqe.wq, ix + i); + struct mlx5e_wqe_frag_info *frag; + + frag = get_frag(rq, j); + for (int k = 0; k < rq->wqe.info.num_frags; k++, frag++) + frag->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE); + } + + return 0; } static void @@ -816,6 +831,8 @@ err_unmap: mlx5e_page_release_fragmented(rq, frag_page); } + bitmap_fill(wi->skip_release_bitmap, rq->mpwqe.pages_per_wqe); + err: rq->stats->buff_alloc_err++; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 176fa5976259..477c547dcc04 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -484,11 +484,20 @@ struct mlx5e_stats { struct mlx5e_vnic_env_stats vnic; struct mlx5e_vport_stats vport; struct mlx5e_pport_stats pport; - struct rtnl_link_stats64 vf_vport; struct mlx5e_pcie_stats pcie; struct mlx5e_rep_stats rep_stats; }; +static inline void mlx5e_stats_copy_rep_stats(struct rtnl_link_stats64 *vf_vport, + struct mlx5e_rep_stats *rep_stats) +{ + memset(vf_vport, 0, sizeof(*vf_vport)); + vf_vport->rx_packets = rep_stats->vport_rx_packets; + vf_vport->tx_packets = rep_stats->vport_tx_packets; + vf_vport->rx_bytes = rep_stats->vport_rx_bytes; + vf_vport->tx_bytes = rep_stats->vport_tx_bytes; +} + extern mlx5e_stats_grp_t mlx5e_nic_stats_grps[]; unsigned int mlx5e_nic_stats_grps_num(struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index c24828b688ac..c8590483ddc6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -4972,7 +4972,8 @@ static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv, if (err) return err; - rpriv->prev_vf_vport_stats = priv->stats.vf_vport; + mlx5e_stats_copy_rep_stats(&rpriv->prev_vf_vport_stats, + &priv->stats.rep_stats); break; default: NL_SET_ERR_MSG_MOD(extack, "mlx5 supports only police action for matchall"); @@ -5012,7 +5013,7 @@ void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv, u64 dbytes; u64 dpkts; - cur_stats = priv->stats.vf_vport; + mlx5e_stats_copy_rep_stats(&cur_stats, &priv->stats.rep_stats); dpkts = cur_stats.rx_packets - rpriv->prev_vf_vport_stats.rx_packets; dbytes = cur_stats.rx_bytes - rpriv->prev_vf_vport_stats.rx_bytes; rpriv->prev_vf_vport_stats = cur_stats; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c index e36294b7ade2..1b9bc32efd6f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c @@ -1748,6 +1748,28 @@ void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 entry->lastuse = jiffies; } +void mlx5_esw_bridge_fdb_mark_deleted(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, + struct mlx5_esw_bridge_offloads *br_offloads, + struct switchdev_notifier_fdb_info *fdb_info) +{ + struct mlx5_esw_bridge_fdb_entry *entry; + struct mlx5_esw_bridge *bridge; + + bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads); + if (!bridge) + return; + + entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid); + if (!entry) { + esw_debug(br_offloads->esw->dev, + "FDB mark deleted entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n", + fdb_info->addr, fdb_info->vid, vport_num); + return; + } + + entry->flags |= MLX5_ESW_BRIDGE_FLAG_DELETED; +} + void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct switchdev_notifier_fdb_info *fdb_info) @@ -1810,7 +1832,8 @@ void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads) unsigned long lastuse = (unsigned long)mlx5_fc_query_lastuse(entry->ingress_counter); - if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER) + if (entry->flags & (MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER | + MLX5_ESW_BRIDGE_FLAG_DELETED)) continue; if (time_after(lastuse, entry->lastuse)) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h index c2c7c70d99eb..d6f539161993 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h @@ -62,6 +62,9 @@ int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_nu void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct switchdev_notifier_fdb_info *fdb_info); +void mlx5_esw_bridge_fdb_mark_deleted(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, + struct mlx5_esw_bridge_offloads *br_offloads, + struct switchdev_notifier_fdb_info *fdb_info); void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, struct mlx5_esw_bridge_offloads *br_offloads, struct switchdev_notifier_fdb_info *fdb_info); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h index 4911cc32161b..7c251af566c6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h @@ -133,6 +133,7 @@ struct mlx5_esw_bridge_mdb_key { enum { MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER = BIT(0), MLX5_ESW_BRIDGE_FLAG_PEER = BIT(1), + MLX5_ESW_BRIDGE_FLAG_DELETED = BIT(2), }; enum { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index d4cde6555063..8d0b915a3121 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1038,11 +1038,8 @@ const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev) return ERR_PTR(err); } -static void mlx5_eswitch_event_handlers_register(struct mlx5_eswitch *esw) +static void mlx5_eswitch_event_handler_register(struct mlx5_eswitch *esw) { - MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE); - mlx5_eq_notifier_register(esw->dev, &esw->nb); - if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) { MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler, ESW_FUNCTIONS_CHANGED); @@ -1050,13 +1047,11 @@ static void mlx5_eswitch_event_handlers_register(struct mlx5_eswitch *esw) } } -static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw) +static void mlx5_eswitch_event_handler_unregister(struct mlx5_eswitch *esw) { if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb); - mlx5_eq_notifier_unregister(esw->dev, &esw->nb); - flush_workqueue(esw->work_queue); } @@ -1483,6 +1478,9 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs) mlx5_eswitch_update_num_of_vfs(esw, num_vfs); + MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE); + mlx5_eq_notifier_register(esw->dev, &esw->nb); + if (esw->mode == MLX5_ESWITCH_LEGACY) { err = esw_legacy_enable(esw); } else { @@ -1495,7 +1493,7 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs) esw->fdb_table.flags |= MLX5_ESW_FDB_CREATED; - mlx5_eswitch_event_handlers_register(esw); + mlx5_eswitch_event_handler_register(esw); esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", @@ -1622,7 +1620,8 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw) */ mlx5_esw_mode_change_notify(esw, MLX5_ESWITCH_LEGACY); - mlx5_eswitch_event_handlers_unregister(esw); + mlx5_eq_notifier_unregister(esw->dev, &esw->nb); + mlx5_eswitch_event_handler_unregister(esw); esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c index 717a0b3f89bd..ab5ef254a748 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c @@ -113,7 +113,10 @@ static void qed_ll2b_complete_tx_packet(void *cxt, static int qed_ll2_alloc_buffer(struct qed_dev *cdev, u8 **data, dma_addr_t *phys_addr) { - *data = kmalloc(cdev->ll2->rx_size, GFP_ATOMIC); + size_t size = cdev->ll2->rx_size + NET_SKB_PAD + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + *data = kmalloc(size, GFP_ATOMIC); if (!(*data)) { DP_INFO(cdev, "Failed to allocate LL2 buffer data\n"); return -ENOMEM; @@ -2589,7 +2592,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params) INIT_LIST_HEAD(&cdev->ll2->list); spin_lock_init(&cdev->ll2->lock); - cdev->ll2->rx_size = NET_SKB_PAD + ETH_HLEN + + cdev->ll2->rx_size = PRM_DMA_PAD_BYTES_NUM + ETH_HLEN + L1_CACHE_BYTES + params->mtu; /* Allocate memory for LL2. diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index 0a3346650e03..cac61f5d3fd4 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -90,12 +90,16 @@ config TI_CPTS The unit can time stamp PTP UDP/IPv4 and Layer 2 packets, and the driver offers a PTP Hardware Clock. +config TI_K3_CPPI_DESC_POOL + tristate + config TI_K3_AM65_CPSW_NUSS tristate "TI K3 AM654x/J721E CPSW Ethernet driver" depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER select NET_DEVLINK select TI_DAVINCI_MDIO select PHYLINK + select TI_K3_CPPI_DESC_POOL imply PHY_TI_GMII_SEL depends on TI_K3_AM65_CPTS || !TI_K3_AM65_CPTS help @@ -187,6 +191,7 @@ config TI_ICSSG_PRUETH tristate "TI Gigabit PRU Ethernet driver" select PHYLIB select TI_ICSS_IEP + select TI_K3_CPPI_DESC_POOL depends on PRU_REMOTEPROC depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER help diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 34fd7a716ba6..67bed861f31d 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile @@ -24,14 +24,15 @@ keystone_netcp-y := netcp_core.o cpsw_ale.o obj-$(CONFIG_TI_KEYSTONE_NETCP_ETHSS) += keystone_netcp_ethss.o keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o cpsw_ale.o +obj-$(CONFIG_TI_K3_CPPI_DESC_POOL) += k3-cppi-desc-pool.o + obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o -ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o k3-cppi-desc-pool.o am65-cpsw-qos.o +ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o am65-cpsw-qos.o ti-am65-cpsw-nuss-$(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV) += am65-cpsw-switchdev.o obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o obj-$(CONFIG_TI_ICSSG_PRUETH) += icssg-prueth.o -icssg-prueth-y := k3-cppi-desc-pool.o \ - icssg/icssg_prueth.o \ +icssg-prueth-y := icssg/icssg_prueth.o \ icssg/icssg_classifier.o \ icssg/icssg_queues.o \ icssg/icssg_config.o \ diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c index 933b84666574..b272361e378f 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_config.c +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c @@ -379,9 +379,9 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice) /* Bitmask for ICSSG r30 commands */ static const struct icssg_r30_cmd emac_r32_bitmask[] = { - {{0xffff0004, 0xffff0100, 0xffff0100, EMAC_NONE}}, /* EMAC_PORT_DISABLE */ + {{0xffff0004, 0xffff0100, 0xffff0004, EMAC_NONE}}, /* EMAC_PORT_DISABLE */ {{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}}, /* EMAC_PORT_BLOCK */ - {{0xffbb0000, 0xfcff0000, 0xdcff0000, EMAC_NONE}}, /* EMAC_PORT_FORWARD */ + {{0xffbb0000, 0xfcff0000, 0xdcfb0000, EMAC_NONE}}, /* EMAC_PORT_FORWARD */ {{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}}, /* EMAC_PORT_FORWARD_WO_LEARNING */ {{0xffff0001, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT ALL */ {{0xfffe0002, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT TAGGED */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/net/ethernet/ti/icssg/icssg_stats.c index bb0b33927e3b..3dbadddd7e35 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_stats.c +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c @@ -9,6 +9,9 @@ #include "icssg_stats.h" #include <linux/regmap.h> +#define ICSSG_TX_PACKET_OFFSET 0xA0 +#define ICSSG_TX_BYTE_OFFSET 0xEC + static u32 stats_base[] = { 0x54c, /* Slice 0 stats start */ 0xb18, /* Slice 1 stats start */ }; @@ -18,6 +21,7 @@ void emac_update_hardware_stats(struct prueth_emac *emac) struct prueth *prueth = emac->prueth; int slice = prueth_emac_slice(emac); u32 base = stats_base[slice]; + u32 tx_pkt_cnt = 0; u32 val; int i; @@ -29,7 +33,12 @@ void emac_update_hardware_stats(struct prueth_emac *emac) base + icssg_all_stats[i].offset, val); + if (icssg_all_stats[i].offset == ICSSG_TX_PACKET_OFFSET) + tx_pkt_cnt = val; + emac->stats[i] += val; + if (icssg_all_stats[i].offset == ICSSG_TX_BYTE_OFFSET) + emac->stats[i] -= tx_pkt_cnt * 8; } } diff --git a/drivers/net/ethernet/ti/k3-cppi-desc-pool.c b/drivers/net/ethernet/ti/k3-cppi-desc-pool.c index 38cc12f9f133..05cc7aab1ec8 100644 --- a/drivers/net/ethernet/ti/k3-cppi-desc-pool.c +++ b/drivers/net/ethernet/ti/k3-cppi-desc-pool.c @@ -39,6 +39,7 @@ void k3_cppi_desc_pool_destroy(struct k3_cppi_desc_pool *pool) gen_pool_destroy(pool->gen_pool); /* frees pool->name */ } +EXPORT_SYMBOL_GPL(k3_cppi_desc_pool_destroy); struct k3_cppi_desc_pool * k3_cppi_desc_pool_create_name(struct device *dev, size_t size, @@ -98,29 +99,38 @@ gen_pool_create_fail: devm_kfree(pool->dev, pool); return ERR_PTR(ret); } +EXPORT_SYMBOL_GPL(k3_cppi_desc_pool_create_name); dma_addr_t k3_cppi_desc_pool_virt2dma(struct k3_cppi_desc_pool *pool, void *addr) { return addr ? pool->dma_addr + (addr - pool->cpumem) : 0; } +EXPORT_SYMBOL_GPL(k3_cppi_desc_pool_virt2dma); void *k3_cppi_desc_pool_dma2virt(struct k3_cppi_desc_pool *pool, dma_addr_t dma) { return dma ? pool->cpumem + (dma - pool->dma_addr) : NULL; } +EXPORT_SYMBOL_GPL(k3_cppi_desc_pool_dma2virt); void *k3_cppi_desc_pool_alloc(struct k3_cppi_desc_pool *pool) { return (void *)gen_pool_alloc(pool->gen_pool, pool->desc_size); } +EXPORT_SYMBOL_GPL(k3_cppi_desc_pool_alloc); void k3_cppi_desc_pool_free(struct k3_cppi_desc_pool *pool, void *addr) { gen_pool_free(pool->gen_pool, (unsigned long)addr, pool->desc_size); } +EXPORT_SYMBOL_GPL(k3_cppi_desc_pool_free); size_t k3_cppi_desc_pool_avail(struct k3_cppi_desc_pool *pool) { return gen_pool_avail(pool->gen_pool) / pool->desc_size; } +EXPORT_SYMBOL_GPL(k3_cppi_desc_pool_avail); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("TI K3 CPPI5 descriptors pool API"); diff --git a/drivers/net/mdio/mdio-mux.c b/drivers/net/mdio/mdio-mux.c index a881e3523328..bef4cce71287 100644 --- a/drivers/net/mdio/mdio-mux.c +++ b/drivers/net/mdio/mdio-mux.c @@ -55,6 +55,27 @@ out: return r; } +static int mdio_mux_read_c45(struct mii_bus *bus, int phy_id, int dev_addr, + int regnum) +{ + struct mdio_mux_child_bus *cb = bus->priv; + struct mdio_mux_parent_bus *pb = cb->parent; + int r; + + mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX); + r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); + if (r) + goto out; + + pb->current_child = cb->bus_number; + + r = pb->mii_bus->read_c45(pb->mii_bus, phy_id, dev_addr, regnum); +out: + mutex_unlock(&pb->mii_bus->mdio_lock); + + return r; +} + /* * The parent bus' lock is used to order access to the switch_fn. */ @@ -80,6 +101,28 @@ out: return r; } +static int mdio_mux_write_c45(struct mii_bus *bus, int phy_id, int dev_addr, + int regnum, u16 val) +{ + struct mdio_mux_child_bus *cb = bus->priv; + struct mdio_mux_parent_bus *pb = cb->parent; + + int r; + + mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX); + r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); + if (r) + goto out; + + pb->current_child = cb->bus_number; + + r = pb->mii_bus->write_c45(pb->mii_bus, phy_id, dev_addr, regnum, val); +out: + mutex_unlock(&pb->mii_bus->mdio_lock); + + return r; +} + static int parent_count; static void mdio_mux_uninit_children(struct mdio_mux_parent_bus *pb) @@ -173,6 +216,10 @@ int mdio_mux_init(struct device *dev, cb->mii_bus->parent = dev; cb->mii_bus->read = mdio_mux_read; cb->mii_bus->write = mdio_mux_write; + if (parent_bus->read_c45) + cb->mii_bus->read_c45 = mdio_mux_read_c45; + if (parent_bus->write_c45) + cb->mii_bus->write_c45 = mdio_mux_write_c45; r = of_mdiobus_register(cb->mii_bus, child_bus_node); if (r) { mdiobus_free(cb->mii_bus); diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index 8478b081c058..97638ba7ae85 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -894,6 +894,9 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev) .name = _name, \ /* PHY_BASIC_FEATURES */ \ .flags = PHY_IS_INTERNAL, \ + .get_sset_count = bcm_phy_get_sset_count, \ + .get_strings = bcm_phy_get_strings, \ + .get_stats = bcm7xxx_28nm_get_phy_stats, \ .probe = bcm7xxx_28nm_probe, \ .config_init = bcm7xxx_16nm_ephy_config_init, \ .config_aneg = genphy_config_aneg, \ diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 89ab9efe522c..afa5497f7c35 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -3073,10 +3073,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, struct net *net = sock_net(&tfile->sk); struct tun_struct *tun; void __user* argp = (void __user*)arg; - unsigned int ifindex, carrier; + unsigned int carrier; struct ifreq ifr; kuid_t owner; kgid_t group; + int ifindex; int sndbuf; int vnet_hdr_sz; int le; @@ -3132,7 +3133,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = -EFAULT; if (copy_from_user(&ifindex, argp, sizeof(ifindex))) goto unlock; - + ret = -EINVAL; + if (ifindex < 0) + goto unlock; ret = 0; tfile->ifindex = ifindex; goto unlock; diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 563ecd27b93e..17da42fe605c 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -897,7 +897,7 @@ static int smsc95xx_reset(struct usbnet *dev) if (timeout >= 100) { netdev_warn(dev->net, "timeout waiting for completion of Lite Reset\n"); - return ret; + return -ETIMEDOUT; } ret = smsc95xx_set_mac_address(dev); diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.c b/drivers/net/wwan/iosm/iosm_ipc_imem.c index 635301d677e1..829515a601b3 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c @@ -4,7 +4,6 @@ */ #include <linux/delay.h> -#include <linux/pm_runtime.h> #include "iosm_ipc_chnl_cfg.h" #include "iosm_ipc_devlink.h" @@ -632,11 +631,6 @@ static void ipc_imem_run_state_worker(struct work_struct *instance) /* Complete all memory stores after setting bit */ smp_mb__after_atomic(); - if (ipc_imem->pcie->pci->device == INTEL_CP_DEVICE_7560_ID) { - pm_runtime_mark_last_busy(ipc_imem->dev); - pm_runtime_put_autosuspend(ipc_imem->dev); - } - return; err_ipc_mux_deinit: @@ -1240,7 +1234,6 @@ void ipc_imem_cleanup(struct iosm_imem *ipc_imem) /* forward MDM_NOT_READY to listeners */ ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_NOT_READY); - pm_runtime_get_sync(ipc_imem->dev); hrtimer_cancel(&ipc_imem->td_alloc_timer); hrtimer_cancel(&ipc_imem->tdupdate_timer); @@ -1426,16 +1419,6 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, set_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag); } - - if (!pm_runtime_enabled(ipc_imem->dev)) - pm_runtime_enable(ipc_imem->dev); - - pm_runtime_set_autosuspend_delay(ipc_imem->dev, - IPC_MEM_AUTO_SUSPEND_DELAY_MS); - pm_runtime_use_autosuspend(ipc_imem->dev); - pm_runtime_allow(ipc_imem->dev); - pm_runtime_mark_last_busy(ipc_imem->dev); - return ipc_imem; devlink_channel_fail: ipc_devlink_deinit(ipc_imem->ipc_devlink); diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h index 0144b45e2afb..5664ac507c90 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h @@ -103,8 +103,6 @@ struct ipc_chnl_cfg; #define FULLY_FUNCTIONAL 0 #define IOSM_DEVLINK_INIT 1 -#define IPC_MEM_AUTO_SUSPEND_DELAY_MS 5000 - /* List of the supported UL/DL pipes. */ enum ipc_mem_pipes { IPC_MEM_PIPE_0 = 0, diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c index 3a259c9abefd..04517bd3325a 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c +++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c @@ -6,7 +6,6 @@ #include <linux/acpi.h> #include <linux/bitfield.h> #include <linux/module.h> -#include <linux/pm_runtime.h> #include <net/rtnetlink.h> #include "iosm_ipc_imem.h" @@ -438,8 +437,7 @@ static int __maybe_unused ipc_pcie_resume_cb(struct device *dev) return 0; } -static DEFINE_RUNTIME_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb, - ipc_pcie_resume_cb, NULL); +static SIMPLE_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb, ipc_pcie_resume_cb); static struct pci_driver iosm_ipc_driver = { .name = KBUILD_MODNAME, diff --git a/drivers/net/wwan/iosm/iosm_ipc_port.c b/drivers/net/wwan/iosm/iosm_ipc_port.c index 2ba1ddca3945..5d5b4183e14a 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_port.c +++ b/drivers/net/wwan/iosm/iosm_ipc_port.c @@ -3,8 +3,6 @@ * Copyright (C) 2020-21 Intel Corporation. */ -#include <linux/pm_runtime.h> - #include "iosm_ipc_chnl_cfg.h" #include "iosm_ipc_imem_ops.h" #include "iosm_ipc_port.h" @@ -15,16 +13,12 @@ static int ipc_port_ctrl_start(struct wwan_port *port) struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); int ret = 0; - pm_runtime_get_sync(ipc_port->ipc_imem->dev); ipc_port->channel = ipc_imem_sys_port_open(ipc_port->ipc_imem, ipc_port->chl_id, IPC_HP_CDEV_OPEN); if (!ipc_port->channel) ret = -EIO; - pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev); - pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev); - return ret; } @@ -33,24 +27,15 @@ static void ipc_port_ctrl_stop(struct wwan_port *port) { struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); - pm_runtime_get_sync(ipc_port->ipc_imem->dev); ipc_imem_sys_port_close(ipc_port->ipc_imem, ipc_port->channel); - pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev); - pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev); } /* transfer control data to modem */ static int ipc_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb) { struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); - int ret; - pm_runtime_get_sync(ipc_port->ipc_imem->dev); - ret = ipc_imem_sys_cdev_write(ipc_port, skb); - pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev); - pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev); - - return ret; + return ipc_imem_sys_cdev_write(ipc_port, skb); } static const struct wwan_port_ops ipc_wwan_ctrl_ops = { diff --git a/drivers/net/wwan/iosm/iosm_ipc_trace.c b/drivers/net/wwan/iosm/iosm_ipc_trace.c index 4368373797b6..eeecfa3d10c5 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_trace.c +++ b/drivers/net/wwan/iosm/iosm_ipc_trace.c @@ -3,9 +3,7 @@ * Copyright (C) 2020-2021 Intel Corporation. */ -#include <linux/pm_runtime.h> #include <linux/wwan.h> - #include "iosm_ipc_trace.h" /* sub buffer size and number of sub buffer */ @@ -99,8 +97,6 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp, if (ret) return ret; - pm_runtime_get_sync(ipc_trace->ipc_imem->dev); - mutex_lock(&ipc_trace->trc_mutex); if (val == TRACE_ENABLE && ipc_trace->mode != TRACE_ENABLE) { ipc_trace->channel = ipc_imem_sys_port_open(ipc_trace->ipc_imem, @@ -121,10 +117,6 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp, ret = count; unlock: mutex_unlock(&ipc_trace->trc_mutex); - - pm_runtime_mark_last_busy(ipc_trace->ipc_imem->dev); - pm_runtime_put_autosuspend(ipc_trace->ipc_imem->dev); - return ret; } diff --git a/drivers/net/wwan/iosm/iosm_ipc_wwan.c b/drivers/net/wwan/iosm/iosm_ipc_wwan.c index 93d17de08786..ff747fc79aaf 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_wwan.c +++ b/drivers/net/wwan/iosm/iosm_ipc_wwan.c @@ -6,7 +6,6 @@ #include <linux/etherdevice.h> #include <linux/if_arp.h> #include <linux/if_link.h> -#include <linux/pm_runtime.h> #include <linux/rtnetlink.h> #include <linux/wwan.h> #include <net/pkt_sched.h> @@ -52,13 +51,11 @@ static int ipc_wwan_link_open(struct net_device *netdev) struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); struct iosm_wwan *ipc_wwan = priv->ipc_wwan; int if_id = priv->if_id; - int ret = 0; if (if_id < IP_MUX_SESSION_START || if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) return -EINVAL; - pm_runtime_get_sync(ipc_wwan->ipc_imem->dev); /* get channel id */ priv->ch_id = ipc_imem_sys_wwan_open(ipc_wwan->ipc_imem, if_id); @@ -66,8 +63,7 @@ static int ipc_wwan_link_open(struct net_device *netdev) dev_err(ipc_wwan->dev, "cannot connect wwan0 & id %d to the IPC mem layer", if_id); - ret = -ENODEV; - goto err_out; + return -ENODEV; } /* enable tx path, DL data may follow */ @@ -76,11 +72,7 @@ static int ipc_wwan_link_open(struct net_device *netdev) dev_dbg(ipc_wwan->dev, "Channel id %d allocated to if_id %d", priv->ch_id, priv->if_id); -err_out: - pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev); - pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev); - - return ret; + return 0; } /* Bring-down the wwan net link */ @@ -90,12 +82,9 @@ static int ipc_wwan_link_stop(struct net_device *netdev) netif_stop_queue(netdev); - pm_runtime_get_sync(priv->ipc_wwan->ipc_imem->dev); ipc_imem_sys_wwan_close(priv->ipc_wwan->ipc_imem, priv->if_id, priv->ch_id); priv->ch_id = -1; - pm_runtime_mark_last_busy(priv->ipc_wwan->ipc_imem->dev); - pm_runtime_put_autosuspend(priv->ipc_wwan->ipc_imem->dev); return 0; } @@ -117,7 +106,6 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb, if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) return -EINVAL; - pm_runtime_get(ipc_wwan->ipc_imem->dev); /* Send the SKB to device for transmission */ ret = ipc_imem_sys_wwan_transmit(ipc_wwan->ipc_imem, if_id, priv->ch_id, skb); @@ -131,14 +119,9 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb, ret = NETDEV_TX_BUSY; dev_err(ipc_wwan->dev, "unable to push packets"); } else { - pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev); - pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev); goto exit; } - pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev); - pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev); - return ret; exit: diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c index daf5d144a8ea..064592a5d546 100644 --- a/drivers/nvme/host/auth.c +++ b/drivers/nvme/host/auth.c @@ -341,7 +341,7 @@ static int nvme_auth_process_dhchap_success1(struct nvme_ctrl *ctrl, struct nvmf_auth_dhchap_success1_data *data = chap->buf; size_t size = sizeof(*data); - if (chap->ctrl_key) + if (chap->s2) size += chap->hash_len; if (size > CHAP_BUF_SIZE) { @@ -825,7 +825,7 @@ static void nvme_queue_auth_work(struct work_struct *work) goto fail2; } - if (chap->ctrl_key) { + if (chap->s2) { /* DH-HMAC-CHAP Step 5: send success2 */ dev_dbg(ctrl->device, "%s: qid %d send success2\n", __func__, chap->qid); diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index d8ff796fd5f2..747c879e8982 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -108,9 +108,13 @@ static void *nvme_add_user_metadata(struct request *req, void __user *ubuf, if (!buf) goto out; - ret = -EFAULT; - if ((req_op(req) == REQ_OP_DRV_OUT) && copy_from_user(buf, ubuf, len)) - goto out_free_meta; + if (req_op(req) == REQ_OP_DRV_OUT) { + ret = -EFAULT; + if (copy_from_user(buf, ubuf, len)) + goto out_free_meta; + } else { + memset(buf, 0, len); + } bip = bio_integrity_alloc(bio, GFP_KERNEL, 1); if (IS_ERR(bip)) { diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 347cb5daebc3..3f0c9ee09a12 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3329,7 +3329,8 @@ static const struct pci_device_id nvme_id_table[] = { { PCI_VDEVICE(INTEL, 0x0a54), /* Intel P4500/P4600 */ .driver_data = NVME_QUIRK_STRIPE_SIZE | NVME_QUIRK_DEALLOCATE_ZEROES | - NVME_QUIRK_IGNORE_DEV_SUBNQN, }, + NVME_QUIRK_IGNORE_DEV_SUBNQN | + NVME_QUIRK_BOGUS_NID, }, { PCI_VDEVICE(INTEL, 0x0a55), /* Dell Express Flash P4600 */ .driver_data = NVME_QUIRK_STRIPE_SIZE | NVME_QUIRK_DEALLOCATE_ZEROES, }, diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 337a624a537c..a7fea4cbacd7 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -638,6 +638,9 @@ static void __nvme_rdma_stop_queue(struct nvme_rdma_queue *queue) static void nvme_rdma_stop_queue(struct nvme_rdma_queue *queue) { + if (!test_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags)) + return; + mutex_lock(&queue->queue_lock); if (test_and_clear_bit(NVME_RDMA_Q_LIVE, &queue->flags)) __nvme_rdma_stop_queue(queue); diff --git a/drivers/nvme/target/fabrics-cmd-auth.c b/drivers/nvme/target/fabrics-cmd-auth.c index 586458f765f1..1d9854484e2e 100644 --- a/drivers/nvme/target/fabrics-cmd-auth.c +++ b/drivers/nvme/target/fabrics-cmd-auth.c @@ -333,19 +333,21 @@ done: __func__, ctrl->cntlid, req->sq->qid, status, req->error_loc); req->cqe->result.u64 = 0; - nvmet_req_complete(req, status); if (req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2 && req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) { unsigned long auth_expire_secs = ctrl->kato ? ctrl->kato : 120; mod_delayed_work(system_wq, &req->sq->auth_expired_work, auth_expire_secs * HZ); - return; + goto complete; } /* Final states, clear up variables */ nvmet_auth_sq_free(req->sq); if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) nvmet_ctrl_fatal_error(ctrl); + +complete: + nvmet_req_complete(req, status); } static int nvmet_auth_challenge(struct nvmet_req *req, void *d, int al) @@ -514,11 +516,12 @@ void nvmet_execute_auth_receive(struct nvmet_req *req) kfree(d); done: req->cqe->result.u64 = 0; - nvmet_req_complete(req, status); + if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2) nvmet_auth_sq_free(req->sq); else if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) { nvmet_auth_sq_free(req->sq); nvmet_ctrl_fatal_error(ctrl); } + nvmet_req_complete(req, status); } diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index cd92d7ddf5ed..197fc2ecb164 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -372,6 +372,7 @@ static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue) static void nvmet_tcp_socket_error(struct nvmet_tcp_queue *queue, int status) { + queue->rcv_state = NVMET_TCP_RECV_ERR; if (status == -EPIPE || status == -ECONNRESET) kernel_sock_shutdown(queue->sock, SHUT_RDWR); else @@ -910,15 +911,11 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue) iov.iov_len = sizeof(*icresp); ret = kernel_sendmsg(queue->sock, &msg, &iov, 1, iov.iov_len); if (ret < 0) - goto free_crypto; + return ret; /* queue removal will cleanup */ queue->state = NVMET_TCP_Q_LIVE; nvmet_prepare_receive_pdu(queue); return 0; -free_crypto: - if (queue->hdr_digest || queue->data_digest) - nvmet_tcp_free_crypto(queue); - return ret; } static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue, diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 9c8fd69ae5ad..40d84cb0c601 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -29,6 +29,7 @@ #include <linux/kfifo.h> #include <linux/slab.h> #include <acpi/apei.h> +#include <acpi/ghes.h> #include <ras/ras_event.h> #include "../pci.h" @@ -997,6 +998,15 @@ static void aer_recover_work_func(struct work_struct *work) continue; } cper_print_aer(pdev, entry.severity, entry.regs); + /* + * Memory for aer_capability_regs(entry.regs) is being allocated from the + * ghes_estatus_pool to protect it from overwriting when multiple sections + * are present in the error status. Thus free the same after processing + * the data. + */ + ghes_estatus_pool_region_free((unsigned long)entry.regs, + sizeof(struct aer_capability_regs)); + if (entry.severity == AER_NONFATAL) pcie_do_recovery(pdev, pci_channel_io_normal, aer_root_reset); diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c index 1d567604b650..376d023a0aa9 100644 --- a/drivers/phy/motorola/phy-mapphone-mdm6600.c +++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c @@ -122,16 +122,10 @@ static int phy_mdm6600_power_on(struct phy *x) { struct phy_mdm6600 *ddata = phy_get_drvdata(x); struct gpio_desc *enable_gpio = ddata->ctrl_gpios[PHY_MDM6600_ENABLE]; - int error; if (!ddata->enabled) return -ENODEV; - error = pinctrl_pm_select_default_state(ddata->dev); - if (error) - dev_warn(ddata->dev, "%s: error with default_state: %i\n", - __func__, error); - gpiod_set_value_cansleep(enable_gpio, 1); /* Allow aggressive PM for USB, it's only needed for n_gsm port */ @@ -160,11 +154,6 @@ static int phy_mdm6600_power_off(struct phy *x) gpiod_set_value_cansleep(enable_gpio, 0); - error = pinctrl_pm_select_sleep_state(ddata->dev); - if (error) - dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", - __func__, error); - return 0; } @@ -456,6 +445,7 @@ static void phy_mdm6600_device_power_off(struct phy_mdm6600 *ddata) { struct gpio_desc *reset_gpio = ddata->ctrl_gpios[PHY_MDM6600_RESET]; + int error; ddata->enabled = false; phy_mdm6600_cmd(ddata, PHY_MDM6600_CMD_BP_SHUTDOWN_REQ); @@ -471,6 +461,17 @@ static void phy_mdm6600_device_power_off(struct phy_mdm6600 *ddata) } else { dev_err(ddata->dev, "Timed out powering down\n"); } + + /* + * Keep reset gpio high with padconf internal pull-up resistor to + * prevent modem from waking up during deeper SoC idle states. The + * gpio bank lines can have glitches if not in the always-on wkup + * domain. + */ + error = pinctrl_pm_select_sleep_state(ddata->dev); + if (error) + dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", + __func__, error); } static void phy_mdm6600_deferred_power_on(struct work_struct *work) @@ -571,12 +572,6 @@ static int phy_mdm6600_probe(struct platform_device *pdev) ddata->dev = &pdev->dev; platform_set_drvdata(pdev, ddata); - /* Active state selected in phy_mdm6600_power_on() */ - error = pinctrl_pm_select_sleep_state(ddata->dev); - if (error) - dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", - __func__, error); - error = phy_mdm6600_init_lines(ddata); if (error) return error; @@ -627,10 +622,12 @@ idle: pm_runtime_put_autosuspend(ddata->dev); cleanup: - if (error < 0) + if (error < 0) { phy_mdm6600_device_power_off(ddata); - pm_runtime_disable(ddata->dev); - pm_runtime_dont_use_autosuspend(ddata->dev); + pm_runtime_disable(ddata->dev); + pm_runtime_dont_use_autosuspend(ddata->dev); + } + return error; } @@ -639,6 +636,7 @@ static void phy_mdm6600_remove(struct platform_device *pdev) struct phy_mdm6600 *ddata = platform_get_drvdata(pdev); struct gpio_desc *reset_gpio = ddata->ctrl_gpios[PHY_MDM6600_RESET]; + pm_runtime_get_noresume(ddata->dev); pm_runtime_dont_use_autosuspend(ddata->dev); pm_runtime_put_sync(ddata->dev); pm_runtime_disable(ddata->dev); diff --git a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c index 8814f4322adf..3642a5d4f2f3 100644 --- a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c +++ b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c @@ -152,7 +152,7 @@ static int qcom_apq8064_sata_phy_init(struct phy *generic_phy) return ret; } - /* SATA phy calibrated succesfully, power up to functional mode */ + /* SATA phy calibrated successfully, power up to functional mode */ writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1); writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0); writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0); diff --git a/drivers/phy/qualcomm/phy-qcom-m31.c b/drivers/phy/qualcomm/phy-qcom-m31.c index ed08072ca032..5cb7e79b99b3 100644 --- a/drivers/phy/qualcomm/phy-qcom-m31.c +++ b/drivers/phy/qualcomm/phy-qcom-m31.c @@ -82,7 +82,7 @@ struct m31_priv_data { unsigned int nregs; }; -struct m31_phy_regs m31_ipq5332_regs[] = { +static struct m31_phy_regs m31_ipq5332_regs[] = { { USB_PHY_CFG0, UTMI_PHY_OVERRIDE_EN, @@ -172,8 +172,7 @@ static int m31usb_phy_init(struct phy *phy) ret = clk_prepare_enable(qphy->clk); if (ret) { - if (qphy->vreg) - regulator_disable(qphy->vreg); + regulator_disable(qphy->vreg); dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret); return ret; } @@ -256,7 +255,7 @@ static int m31usb_phy_probe(struct platform_device *pdev) qphy->vreg = devm_regulator_get(dev, "vdda-phy"); if (IS_ERR(qphy->vreg)) - return dev_err_probe(dev, PTR_ERR(qphy->phy), + return dev_err_probe(dev, PTR_ERR(qphy->vreg), "failed to get vreg\n"); phy_set_drvdata(qphy->phy, qphy); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index cbb28afce135..5e6fc8103e9d 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -859,10 +859,10 @@ static const struct qmp_phy_init_tbl sm8550_usb3_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_USB_V6_PCS_PCS_TX_RX_CONFIG, 0x0c), QMP_PHY_INIT_CFG(QPHY_USB_V6_PCS_EQ_CONFIG1, 0x4b), QMP_PHY_INIT_CFG(QPHY_USB_V6_PCS_EQ_CONFIG5, 0x10), - QMP_PHY_INIT_CFG(QPHY_USB_V6_PCS_USB3_POWER_STATE_CONFIG1, 0x68), }; static const struct qmp_phy_init_tbl sm8550_usb3_pcs_usb_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_USB_V6_PCS_USB3_POWER_STATE_CONFIG1, 0x68), QMP_PHY_INIT_CFG(QPHY_USB_V6_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), QMP_PHY_INIT_CFG(QPHY_USB_V6_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), QMP_PHY_INIT_CFG(QPHY_USB_V6_PCS_USB3_RCVR_DTCT_DLY_U3_L, 0x40), @@ -2555,6 +2555,7 @@ static int qmp_combo_usb_power_on(struct phy *phy) void __iomem *tx2 = qmp->tx2; void __iomem *rx2 = qmp->rx2; void __iomem *pcs = qmp->pcs; + void __iomem *pcs_usb = qmp->pcs_usb; void __iomem *status; unsigned int val; int ret; @@ -2576,6 +2577,9 @@ static int qmp_combo_usb_power_on(struct phy *phy) qmp_combo_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); + if (pcs_usb) + qmp_combo_configure(pcs_usb, cfg->pcs_usb_tbl, cfg->pcs_usb_tbl_num); + if (cfg->has_pwrdn_delay) usleep_range(10, 20); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v6.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v6.h index 9510e63ba9d8..c38530d6776b 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v6.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-usb-v6.h @@ -12,7 +12,7 @@ #define QPHY_USB_V6_PCS_LOCK_DETECT_CONFIG3 0xcc #define QPHY_USB_V6_PCS_LOCK_DETECT_CONFIG6 0xd8 #define QPHY_USB_V6_PCS_REFGEN_REQ_CONFIG1 0xdc -#define QPHY_USB_V6_PCS_USB3_POWER_STATE_CONFIG1 0x90 +#define QPHY_USB_V6_PCS_POWER_STATE_CONFIG1 0x90 #define QPHY_USB_V6_PCS_RX_SIGDET_LVL 0x188 #define QPHY_USB_V6_PCS_RCVR_DTCT_DLY_P1U2_L 0x190 #define QPHY_USB_V6_PCS_RCVR_DTCT_DLY_P1U2_H 0x194 @@ -23,6 +23,7 @@ #define QPHY_USB_V6_PCS_EQ_CONFIG1 0x1dc #define QPHY_USB_V6_PCS_EQ_CONFIG5 0x1ec +#define QPHY_USB_V6_PCS_USB3_POWER_STATE_CONFIG1 0x00 #define QPHY_USB_V6_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL 0x18 #define QPHY_USB_V6_PCS_USB3_RXEQTRAINING_DFE_TIME_S2 0x3c #define QPHY_USB_V6_PCS_USB3_RCVR_DTCT_DLY_U3_L 0x40 diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c index 0130bb8e809a..c69577601ae0 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c @@ -1112,8 +1112,6 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa), QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), QMP_PHY_INIT_CFG(QPHY_V5_PCS_CDR_RESET_TIME, 0x0a), QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88), QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13), @@ -1122,6 +1120,11 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), }; +static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_pcs_usb_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), +}; + static const struct qmp_phy_init_tbl sa8775p_usb3_uniphy_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG1, 0xc4), QMP_PHY_INIT_CFG(QPHY_V5_PCS_LOCK_DETECT_CONFIG2, 0x89), @@ -1131,9 +1134,6 @@ static const struct qmp_phy_init_tbl sa8775p_usb3_uniphy_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0xaa), QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCS_TX_RX_CONFIG, 0x0c), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), - QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_POWER_STATE_CONFIG1, 0x6f), QMP_PHY_INIT_CFG(QPHY_V5_PCS_CDR_RESET_TIME, 0x0a), QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG1, 0x88), QMP_PHY_INIT_CFG(QPHY_V5_PCS_ALIGN_DETECT_CONFIG2, 0x13), @@ -1142,6 +1142,12 @@ static const struct qmp_phy_init_tbl sa8775p_usb3_uniphy_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x21), }; +static const struct qmp_phy_init_tbl sa8775p_usb3_uniphy_pcs_usb_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_POWER_STATE_CONFIG1, 0x6f), +}; + struct qmp_usb_offsets { u16 serdes; u16 pcs; @@ -1383,6 +1389,8 @@ static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = { .rx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_rx_tbl), .pcs_tbl = sa8775p_usb3_uniphy_pcs_tbl, .pcs_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_tbl), + .pcs_usb_tbl = sa8775p_usb3_uniphy_pcs_usb_tbl, + .pcs_usb_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_usb_tbl), .clk_list = qmp_v4_phy_clk_l, .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), .reset_list = qcm2290_usb3phy_reset_l, @@ -1405,6 +1413,8 @@ static const struct qmp_phy_cfg sc8280xp_usb3_uniphy_cfg = { .rx_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_rx_tbl), .pcs_tbl = sc8280xp_usb3_uniphy_pcs_tbl, .pcs_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_pcs_tbl), + .pcs_usb_tbl = sc8280xp_usb3_uniphy_pcs_usb_tbl, + .pcs_usb_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_pcs_usb_tbl), .clk_list = qmp_v4_phy_clk_l, .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), .reset_list = qcm2290_usb3phy_reset_l, @@ -1703,6 +1713,7 @@ static int qmp_usb_power_on(struct phy *phy) void __iomem *tx = qmp->tx; void __iomem *rx = qmp->rx; void __iomem *pcs = qmp->pcs; + void __iomem *pcs_usb = qmp->pcs_usb; void __iomem *status; unsigned int val; int ret; @@ -1726,6 +1737,9 @@ static int qmp_usb_power_on(struct phy *phy) qmp_usb_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); + if (pcs_usb) + qmp_usb_configure(pcs_usb, cfg->pcs_usb_tbl, cfg->pcs_usb_tbl_num); + if (cfg->has_pwrdn_delay) usleep_range(10, 20); diff --git a/drivers/phy/realtek/Kconfig b/drivers/phy/realtek/Kconfig index 650e20ed69af..75ac7e7c31ae 100644 --- a/drivers/phy/realtek/Kconfig +++ b/drivers/phy/realtek/Kconfig @@ -2,6 +2,9 @@ # # Phy drivers for Realtek platforms # + +if ARCH_REALTEK || COMPILE_TEST + config PHY_RTK_RTD_USB2PHY tristate "Realtek RTD USB2 PHY Transceiver Driver" depends on USB_SUPPORT @@ -25,3 +28,5 @@ config PHY_RTK_RTD_USB3PHY The DHC (digital home center) RTD series SoCs used the Synopsys DWC3 USB IP. This driver will do the PHY initialization of the parameters. + +endif # ARCH_REALTEK || COMPILE_TEST diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c index 5e7ee060b404..aedc78bd37f7 100644 --- a/drivers/phy/realtek/phy-rtk-usb2.c +++ b/drivers/phy/realtek/phy-rtk-usb2.c @@ -853,17 +853,11 @@ static inline void create_debug_files(struct rtk_phy *rtk_phy) rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev), phy_debug_root); - if (!rtk_phy->debug_dir) - return; - if (!debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy, - &rtk_usb2_parameter_fops)) - goto file_error; + debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy, + &rtk_usb2_parameter_fops); return; - -file_error: - debugfs_remove_recursive(rtk_phy->debug_dir); } static inline void remove_debug_files(struct rtk_phy *rtk_phy) diff --git a/drivers/phy/realtek/phy-rtk-usb3.c b/drivers/phy/realtek/phy-rtk-usb3.c index 7881f908aade..dfb3122f3f11 100644 --- a/drivers/phy/realtek/phy-rtk-usb3.c +++ b/drivers/phy/realtek/phy-rtk-usb3.c @@ -416,17 +416,11 @@ static inline void create_debug_files(struct rtk_phy *rtk_phy) return; rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev), phy_debug_root); - if (!rtk_phy->debug_dir) - return; - if (!debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy, - &rtk_usb3_parameter_fops)) - goto file_error; + debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy, + &rtk_usb3_parameter_fops); return; - -file_error: - debugfs_remove_recursive(rtk_phy->debug_dir); } static inline void remove_debug_files(struct rtk_phy *rtk_phy) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index e2f7519bef04..e9dc9638120a 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1022,20 +1022,17 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev, static struct pinctrl *find_pinctrl(struct device *dev) { - struct pinctrl *entry, *p = NULL; + struct pinctrl *p; mutex_lock(&pinctrl_list_mutex); - - list_for_each_entry(entry, &pinctrl_list, node) { - if (entry->dev == dev) { - p = entry; - kref_get(&p->users); - break; + list_for_each_entry(p, &pinctrl_list, node) + if (p->dev == dev) { + mutex_unlock(&pinctrl_list_mutex); + return p; } - } mutex_unlock(&pinctrl_list_mutex); - return p; + return NULL; } static void pinctrl_free(struct pinctrl *p, bool inlist); @@ -1143,6 +1140,7 @@ struct pinctrl *pinctrl_get(struct device *dev) p = find_pinctrl(dev); if (p) { dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n"); + kref_get(&p->users); return p; } diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c index e5a418026ba3..0b2839d27fd6 100644 --- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c @@ -32,7 +32,8 @@ struct lpi_pinctrl { char __iomem *tlmm_base; char __iomem *slew_base; struct clk_bulk_data clks[MAX_LPI_NUM_CLKS]; - struct mutex slew_access_lock; + /* Protects from concurrent register updates */ + struct mutex lock; DECLARE_BITMAP(ever_gpio, MAX_NR_GPIO); const struct lpi_pinctrl_variant_data *data; }; @@ -103,6 +104,7 @@ static int lpi_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned int function, if (WARN_ON(i == g->nfuncs)) return -EINVAL; + mutex_lock(&pctrl->lock); val = lpi_gpio_read(pctrl, pin, LPI_GPIO_CFG_REG); /* @@ -128,6 +130,7 @@ static int lpi_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned int function, u32p_replace_bits(&val, i, LPI_GPIO_FUNCTION_MASK); lpi_gpio_write(pctrl, pin, LPI_GPIO_CFG_REG, val); + mutex_unlock(&pctrl->lock); return 0; } @@ -233,14 +236,14 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, if (slew_offset == LPI_NO_SLEW) break; - mutex_lock(&pctrl->slew_access_lock); + mutex_lock(&pctrl->lock); sval = ioread32(pctrl->slew_base + LPI_SLEW_RATE_CTL_REG); sval &= ~(LPI_SLEW_RATE_MASK << slew_offset); sval |= arg << slew_offset; iowrite32(sval, pctrl->slew_base + LPI_SLEW_RATE_CTL_REG); - mutex_unlock(&pctrl->slew_access_lock); + mutex_unlock(&pctrl->lock); break; default: return -EINVAL; @@ -256,6 +259,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, lpi_gpio_write(pctrl, group, LPI_GPIO_VALUE_REG, val); } + mutex_lock(&pctrl->lock); val = lpi_gpio_read(pctrl, group, LPI_GPIO_CFG_REG); u32p_replace_bits(&val, pullup, LPI_GPIO_PULL_MASK); @@ -264,6 +268,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, u32p_replace_bits(&val, output_enabled, LPI_GPIO_OE_MASK); lpi_gpio_write(pctrl, group, LPI_GPIO_CFG_REG, val); + mutex_unlock(&pctrl->lock); return 0; } @@ -461,7 +466,7 @@ int lpi_pinctrl_probe(struct platform_device *pdev) pctrl->chip.label = dev_name(dev); pctrl->chip.can_sleep = false; - mutex_init(&pctrl->slew_access_lock); + mutex_init(&pctrl->lock); pctrl->ctrl = devm_pinctrl_register(dev, &pctrl->desc, pctrl); if (IS_ERR(pctrl->ctrl)) { @@ -483,7 +488,7 @@ int lpi_pinctrl_probe(struct platform_device *pdev) return 0; err_pinctrl: - mutex_destroy(&pctrl->slew_access_lock); + mutex_destroy(&pctrl->lock); clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks); return ret; @@ -495,7 +500,7 @@ int lpi_pinctrl_remove(struct platform_device *pdev) struct lpi_pinctrl *pctrl = platform_get_drvdata(pdev); int i; - mutex_destroy(&pctrl->slew_access_lock); + mutex_destroy(&pctrl->lock); clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks); for (i = 0; i < pctrl->data->npins; i++) diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c index fd38d8c8371e..ab7d7a1235b8 100644 --- a/drivers/platform/mellanox/mlxbf-tmfifo.c +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c @@ -609,24 +609,25 @@ static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring, if (vring->cur_len + sizeof(u64) <= len) { /* The whole word. */ - if (!IS_VRING_DROP(vring)) { - if (is_rx) + if (is_rx) { + if (!IS_VRING_DROP(vring)) memcpy(addr + vring->cur_len, &data, sizeof(u64)); - else - memcpy(&data, addr + vring->cur_len, - sizeof(u64)); + } else { + memcpy(&data, addr + vring->cur_len, + sizeof(u64)); } vring->cur_len += sizeof(u64); } else { /* Leftover bytes. */ - if (!IS_VRING_DROP(vring)) { - if (is_rx) + if (is_rx) { + if (!IS_VRING_DROP(vring)) memcpy(addr + vring->cur_len, &data, len - vring->cur_len); - else - memcpy(&data, addr + vring->cur_len, - len - vring->cur_len); + } else { + data = 0; + memcpy(&data, addr + vring->cur_len, + len - vring->cur_len); } vring->cur_len = len; } diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c index 897cdd9c3aae..0412a644fece 100644 --- a/drivers/platform/surface/surface_acpi_notify.c +++ b/drivers/platform/surface/surface_acpi_notify.c @@ -741,6 +741,7 @@ static bool is_san_consumer(struct platform_device *pdev, acpi_handle handle) struct acpi_handle_list dep_devices; acpi_handle supplier = ACPI_HANDLE(&pdev->dev); acpi_status status; + bool ret = false; int i; if (!acpi_has_method(handle, "_DEP")) @@ -753,11 +754,14 @@ static bool is_san_consumer(struct platform_device *pdev, acpi_handle handle) } for (i = 0; i < dep_devices.count; i++) { - if (dep_devices.handles[i] == supplier) - return true; + if (dep_devices.handles[i] == supplier) { + ret = true; + break; + } } - return false; + acpi_handle_list_free(&dep_devices); + return ret; } static acpi_status san_consumer_setup(acpi_handle handle, u32 lvl, diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c index f433a13c3689..a5a3941b3f43 100644 --- a/drivers/platform/surface/surface_platform_profile.c +++ b/drivers/platform/surface/surface_platform_profile.c @@ -159,8 +159,7 @@ static int surface_platform_profile_probe(struct ssam_device *sdev) set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, tpd->handler.choices); set_bit(PLATFORM_PROFILE_PERFORMANCE, tpd->handler.choices); - platform_profile_register(&tpd->handler); - return 0; + return platform_profile_register(&tpd->handler); } static void surface_platform_profile_remove(struct ssam_device *sdev) diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index cadbb557a108..1417e230edbd 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -105,6 +105,8 @@ struct apple_gmux_config { #define GMUX_BRIGHTNESS_MASK 0x00ffffff #define GMUX_MAX_BRIGHTNESS GMUX_BRIGHTNESS_MASK +# define MMIO_GMUX_MAX_BRIGHTNESS 0xffff + static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port) { return inb(gmux_data->iostart + port); @@ -857,7 +859,17 @@ get_version: memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_PLATFORM; - props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); + + /* + * All MMIO gmux's have 0xffff as max brightness, but some iMacs incorrectly + * report 0x03ff, despite the firmware being happy to set 0xffff as the brightness + * at boot. Force 0xffff for all MMIO gmux's so they all have the correct brightness + * range. + */ + if (type == APPLE_GMUX_TYPE_MMIO) + props.max_brightness = MMIO_GMUX_MAX_BRIGHTNESS; + else + props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); #if IS_REACHABLE(CONFIG_ACPI_VIDEO) register_bdev = acpi_video_get_backlight_type() == acpi_backlight_apple_gmux; diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index d85d895fee89..df1db54d4e18 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -531,6 +531,9 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, ASUS_WMI_BRN_DOWN, { KEY_BRIGHTNESSDOWN } }, { KE_KEY, ASUS_WMI_BRN_UP, { KEY_BRIGHTNESSUP } }, + { KE_KEY, 0x2a, { KEY_SELECTIVE_SCREENSHOT } }, + { KE_IGNORE, 0x2b, }, /* PrintScreen (also send via PS/2) on newer models */ + { KE_IGNORE, 0x2c, }, /* CapsLock (also send via PS/2) on newer models */ { KE_KEY, 0x30, { KEY_VOLUMEUP } }, { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, { KE_KEY, 0x32, { KEY_MUTE } }, diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 9f8cea5f9615..19bfd30861aa 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -3826,7 +3826,6 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) { unsigned int key_value = 1; bool autorelease = 1; - int orig_code = code; if (asus->driver->key_filter) { asus->driver->key_filter(asus->driver, &code, &key_value, @@ -3835,16 +3834,10 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) return; } - if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX) - code = ASUS_WMI_BRN_UP; - else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX) - code = ASUS_WMI_BRN_DOWN; - - if (code == ASUS_WMI_BRN_DOWN || code == ASUS_WMI_BRN_UP) { - if (acpi_video_get_backlight_type() == acpi_backlight_vendor) { - asus_wmi_backlight_notify(asus, orig_code); - return; - } + if (acpi_video_get_backlight_type() == acpi_backlight_vendor && + code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNDOWN_MAX) { + asus_wmi_backlight_notify(asus, code); + return; } if (code == NOTIFY_KBD_BRTUP) { diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index a478ebfd34df..fc41d1b1bb7f 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -18,7 +18,7 @@ #include <linux/i8042.h> #define ASUS_WMI_KEY_IGNORE (-1) -#define ASUS_WMI_BRN_DOWN 0x20 +#define ASUS_WMI_BRN_DOWN 0x2e #define ASUS_WMI_BRN_UP 0x2f struct module; diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c index 1152deaa0078..33ab207493e3 100644 --- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c @@ -176,7 +176,7 @@ show_uncore_data(initial_max_freq_khz); static int create_attr_group(struct uncore_data *data, char *name) { - int ret, index = 0; + int ret, freq, index = 0; init_attribute_rw(max_freq_khz); init_attribute_rw(min_freq_khz); @@ -197,7 +197,11 @@ static int create_attr_group(struct uncore_data *data, char *name) data->uncore_attrs[index++] = &data->min_freq_khz_dev_attr.attr; data->uncore_attrs[index++] = &data->initial_min_freq_khz_dev_attr.attr; data->uncore_attrs[index++] = &data->initial_max_freq_khz_dev_attr.attr; - data->uncore_attrs[index++] = &data->current_freq_khz_dev_attr.attr; + + ret = uncore_read_freq(data, &freq); + if (!ret) + data->uncore_attrs[index++] = &data->current_freq_khz_dev_attr.attr; + data->uncore_attrs[index] = NULL; data->uncore_attr_group.name = name; diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 3d96dbf79a72..a2ffe4157df1 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -6514,6 +6514,7 @@ static int mlxplat_i2c_main_init(struct mlxplat_priv *priv) return 0; fail_mlxplat_i2c_mux_topology_init: + platform_device_unregister(priv->pdev_i2c); fail_platform_i2c_register: fail_mlxplat_mlxcpld_verify_bus_topology: return err; @@ -6521,6 +6522,7 @@ fail_mlxplat_mlxcpld_verify_bus_topology: static void mlxplat_i2c_main_exit(struct mlxplat_priv *priv) { + mlxplat_pre_exit(priv); mlxplat_i2c_mux_topology_exit(priv); if (priv->pdev_i2c) platform_device_unregister(priv->pdev_i2c); @@ -6597,7 +6599,7 @@ static int mlxplat_probe(struct platform_device *pdev) fail_register_reboot_notifier: fail_regcache_sync: - mlxplat_pre_exit(priv); + mlxplat_i2c_main_exit(priv); fail_mlxplat_i2c_main_init: fail_regmap_write: fail_alloc: @@ -6614,7 +6616,6 @@ static int mlxplat_remove(struct platform_device *pdev) pm_power_off = NULL; if (mlxplat_reboot_nb) unregister_reboot_notifier(mlxplat_reboot_nb); - mlxplat_pre_exit(priv); mlxplat_i2c_main_exit(priv); mlxplat_post_exit(); return 0; diff --git a/drivers/platform/x86/msi-ec.c b/drivers/platform/x86/msi-ec.c index f26a3121092f..492eb383ee7a 100644 --- a/drivers/platform/x86/msi-ec.c +++ b/drivers/platform/x86/msi-ec.c @@ -276,14 +276,13 @@ static struct msi_ec_conf CONF2 __initdata = { static const char * const ALLOWED_FW_3[] __initconst = { "1592EMS1.111", - "E1592IMS.10C", NULL }; static struct msi_ec_conf CONF3 __initdata = { .allowed_fw = ALLOWED_FW_3, .charge_control = { - .address = 0xef, + .address = 0xd7, .offset_start = 0x8a, .offset_end = 0x80, .range_min = 0x8a, diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 3ef636935a54..3ff46fc694f8 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -233,17 +233,19 @@ struct subchannel *css_alloc_subchannel(struct subchannel_id schid, */ ret = dma_set_coherent_mask(&sch->dev, DMA_BIT_MASK(31)); if (ret) - goto err; + goto err_lock; /* * But we don't have such restrictions imposed on the stuff that * is handled by the streaming API. */ ret = dma_set_mask(&sch->dev, DMA_BIT_MASK(64)); if (ret) - goto err; + goto err_lock; return sch; +err_lock: + kfree(sch->lock); err: kfree(sch); return ERR_PTR(ret); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index c3c1f466fe01..605013d3ee83 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -12913,8 +12913,10 @@ _mpt3sas_init(void) mpt3sas_ctl_init(hbas_to_enumerate); error = pci_register_driver(&mpt3sas_driver); - if (error) + if (error) { + mpt3sas_ctl_exit(hbas_to_enumerate); scsih_exit(); + } return error; } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 50db08265c51..dcae09a37d49 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4953,7 +4953,7 @@ qla2x00_mem_free(struct qla_hw_data *ha) ha->gid_list = NULL; ha->gid_list_dma = 0; - if (!list_empty(&ha->base_qpair->dsd_list)) { + if (ha->base_qpair && !list_empty(&ha->base_qpair->dsd_list)) { struct dsd_dma *dsd_ptr, *tdsd_ptr; /* clean up allocated prev pool */ diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c index f3810d9d1caa..27a96cafd1ea 100644 --- a/drivers/soc/hisilicon/kunpeng_hccs.c +++ b/drivers/soc/hisilicon/kunpeng_hccs.c @@ -31,10 +31,6 @@ #include "kunpeng_hccs.h" -/* PCC defines */ -#define HCCS_PCC_SIGNATURE_MASK 0x50434300 -#define HCCS_PCC_STATUS_CMD_COMPLETE BIT(0) - /* * Arbitrary retries in case the remote processor is slow to respond * to PCC commands @@ -187,7 +183,7 @@ static int hccs_check_chan_cmd_complete(struct hccs_dev *hdev) * deadline_us(timeout_us) until PCC command complete bit is set(cond) */ ret = readw_poll_timeout(&comm_base->status, status, - status & HCCS_PCC_STATUS_CMD_COMPLETE, + status & PCC_STATUS_CMD_COMPLETE, HCCS_POLL_STATUS_TIME_INTERVAL_US, cl_info->deadline_us); if (unlikely(ret)) @@ -208,7 +204,7 @@ static int hccs_pcc_cmd_send(struct hccs_dev *hdev, u8 cmd, int ret; /* Write signature for this subspace */ - tmp.signature = HCCS_PCC_SIGNATURE_MASK | hdev->chan_id; + tmp.signature = PCC_SIGNATURE | hdev->chan_id; /* Write to the shared command region */ tmp.command = cmd; /* Clear cmd complete bit */ diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index 0ca21ff0e9cc..e42248519688 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -353,8 +353,9 @@ static int npcm_fiu_uma_read(struct spi_mem *mem, uma_cfg |= ilog2(op->cmd.buswidth); uma_cfg |= ilog2(op->addr.buswidth) << NPCM_FIU_UMA_CFG_ADBPCK_SHIFT; - uma_cfg |= ilog2(op->dummy.buswidth) - << NPCM_FIU_UMA_CFG_DBPCK_SHIFT; + if (op->dummy.nbytes) + uma_cfg |= ilog2(op->dummy.buswidth) + << NPCM_FIU_UMA_CFG_DBPCK_SHIFT; uma_cfg |= ilog2(op->data.buswidth) << NPCM_FIU_UMA_CFG_RDBPCK_SHIFT; uma_cfg |= op->dummy.nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT; diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index dd0a1ef8cf12..27bd6ca6f99e 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1907,14 +1907,14 @@ static void tb_handle_dp_bandwidth_request(struct work_struct *work) in = &sw->ports[ev->port]; if (!tb_port_is_dpin(in)) { tb_port_warn(in, "bandwidth request to non-DP IN adapter\n"); - goto unlock; + goto put_sw; } tb_port_dbg(in, "handling bandwidth allocation request\n"); if (!usb4_dp_port_bandwidth_mode_enabled(in)) { tb_port_warn(in, "bandwidth allocation mode not enabled\n"); - goto unlock; + goto put_sw; } ret = usb4_dp_port_requested_bandwidth(in); @@ -1923,7 +1923,7 @@ static void tb_handle_dp_bandwidth_request(struct work_struct *work) tb_port_dbg(in, "no bandwidth request active\n"); else tb_port_warn(in, "failed to read requested bandwidth\n"); - goto unlock; + goto put_sw; } requested_bw = ret; @@ -1932,7 +1932,7 @@ static void tb_handle_dp_bandwidth_request(struct work_struct *work) tunnel = tb_find_tunnel(tb, TB_TUNNEL_DP, in, NULL); if (!tunnel) { tb_port_warn(in, "failed to find tunnel\n"); - goto unlock; + goto put_sw; } out = tunnel->dst_port; @@ -1959,6 +1959,8 @@ static void tb_handle_dp_bandwidth_request(struct work_struct *work) tb_recalc_estimated_bandwidth(tb); } +put_sw: + tb_switch_put(sw); unlock: mutex_unlock(&tb->lock); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 7994a4549a6c..45dcfaadaf98 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -203,6 +203,9 @@ static void option_instat_callback(struct urb *urb); #define DELL_PRODUCT_5829E_ESIM 0x81e4 #define DELL_PRODUCT_5829E 0x81e6 +#define DELL_PRODUCT_FM101R 0x8213 +#define DELL_PRODUCT_FM101R_ESIM 0x8215 + #define KYOCERA_VENDOR_ID 0x0c88 #define KYOCERA_PRODUCT_KPC650 0x17da #define KYOCERA_PRODUCT_KPC680 0x180a @@ -1108,6 +1111,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(0) | RSVD(6) }, { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5829E_ESIM), .driver_info = RSVD(0) | RSVD(6) }, + { USB_DEVICE_INTERFACE_CLASS(DELL_VENDOR_ID, DELL_PRODUCT_FM101R, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(DELL_VENDOR_ID, DELL_PRODUCT_FM101R_ESIM, 0xff) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, @@ -1290,6 +1295,7 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */ .driver_info = NCTRL(0) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1035, 0xff) }, /* Telit LE910C4-WWX (ECM) */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0), .driver_info = RSVD(0) | RSVD(1) | NCTRL(2) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1), @@ -2262,6 +2268,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */ { USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, { } /* Terminating entry */ diff --git a/drivers/vdpa/mlx5/net/debug.c b/drivers/vdpa/mlx5/net/debug.c index 60d6ac68cdc4..9c85162c19fc 100644 --- a/drivers/vdpa/mlx5/net/debug.c +++ b/drivers/vdpa/mlx5/net/debug.c @@ -146,7 +146,8 @@ void mlx5_vdpa_add_debugfs(struct mlx5_vdpa_net *ndev) ndev->rx_dent = debugfs_create_dir("rx", ndev->debugfs); } -void mlx5_vdpa_remove_debugfs(struct dentry *dbg) +void mlx5_vdpa_remove_debugfs(struct mlx5_vdpa_net *ndev) { - debugfs_remove_recursive(dbg); + debugfs_remove_recursive(ndev->debugfs); + ndev->debugfs = NULL; } diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 40a03b08d7cf..946488b8989f 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -625,30 +625,70 @@ static void cq_destroy(struct mlx5_vdpa_net *ndev, u16 idx) mlx5_db_free(ndev->mvdev.mdev, &vcq->db); } +static int read_umem_params(struct mlx5_vdpa_net *ndev) +{ + u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {}; + u16 opmod = (MLX5_CAP_VDPA_EMULATION << 1) | (HCA_CAP_OPMOD_GET_CUR & 0x01); + struct mlx5_core_dev *mdev = ndev->mvdev.mdev; + int out_size; + void *caps; + void *out; + int err; + + out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out); + out = kzalloc(out_size, GFP_KERNEL); + if (!out) + return -ENOMEM; + + MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); + MLX5_SET(query_hca_cap_in, in, op_mod, opmod); + err = mlx5_cmd_exec_inout(mdev, query_hca_cap, in, out); + if (err) { + mlx5_vdpa_warn(&ndev->mvdev, + "Failed reading vdpa umem capabilities with err %d\n", err); + goto out; + } + + caps = MLX5_ADDR_OF(query_hca_cap_out, out, capability); + + ndev->umem_1_buffer_param_a = MLX5_GET(virtio_emulation_cap, caps, umem_1_buffer_param_a); + ndev->umem_1_buffer_param_b = MLX5_GET(virtio_emulation_cap, caps, umem_1_buffer_param_b); + + ndev->umem_2_buffer_param_a = MLX5_GET(virtio_emulation_cap, caps, umem_2_buffer_param_a); + ndev->umem_2_buffer_param_b = MLX5_GET(virtio_emulation_cap, caps, umem_2_buffer_param_b); + + ndev->umem_3_buffer_param_a = MLX5_GET(virtio_emulation_cap, caps, umem_3_buffer_param_a); + ndev->umem_3_buffer_param_b = MLX5_GET(virtio_emulation_cap, caps, umem_3_buffer_param_b); + +out: + kfree(out); + return 0; +} + static void set_umem_size(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq, int num, struct mlx5_vdpa_umem **umemp) { - struct mlx5_core_dev *mdev = ndev->mvdev.mdev; - int p_a; - int p_b; + u32 p_a; + u32 p_b; switch (num) { case 1: - p_a = MLX5_CAP_DEV_VDPA_EMULATION(mdev, umem_1_buffer_param_a); - p_b = MLX5_CAP_DEV_VDPA_EMULATION(mdev, umem_1_buffer_param_b); + p_a = ndev->umem_1_buffer_param_a; + p_b = ndev->umem_1_buffer_param_b; *umemp = &mvq->umem1; break; case 2: - p_a = MLX5_CAP_DEV_VDPA_EMULATION(mdev, umem_2_buffer_param_a); - p_b = MLX5_CAP_DEV_VDPA_EMULATION(mdev, umem_2_buffer_param_b); + p_a = ndev->umem_2_buffer_param_a; + p_b = ndev->umem_2_buffer_param_b; *umemp = &mvq->umem2; break; case 3: - p_a = MLX5_CAP_DEV_VDPA_EMULATION(mdev, umem_3_buffer_param_a); - p_b = MLX5_CAP_DEV_VDPA_EMULATION(mdev, umem_3_buffer_param_b); + p_a = ndev->umem_3_buffer_param_a; + p_b = ndev->umem_3_buffer_param_b; *umemp = &mvq->umem3; break; } + (*umemp)->size = p_a * mvq->num_ent + p_b; } @@ -2679,6 +2719,11 @@ static int setup_driver(struct mlx5_vdpa_dev *mvdev) goto out; } mlx5_vdpa_add_debugfs(ndev); + + err = read_umem_params(ndev); + if (err) + goto err_setup; + err = setup_virtqueues(mvdev); if (err) { mlx5_vdpa_warn(mvdev, "setup_virtqueues\n"); @@ -2713,7 +2758,7 @@ err_tir: err_rqt: teardown_virtqueues(ndev); err_setup: - mlx5_vdpa_remove_debugfs(ndev->debugfs); + mlx5_vdpa_remove_debugfs(ndev); out: return err; } @@ -2727,8 +2772,7 @@ static void teardown_driver(struct mlx5_vdpa_net *ndev) if (!ndev->setup) return; - mlx5_vdpa_remove_debugfs(ndev->debugfs); - ndev->debugfs = NULL; + mlx5_vdpa_remove_debugfs(ndev); teardown_steering(ndev); destroy_tir(ndev); destroy_rqt(ndev); @@ -3489,8 +3533,6 @@ static void mlx5_vdpa_dev_del(struct vdpa_mgmt_dev *v_mdev, struct vdpa_device * struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); struct workqueue_struct *wq; - mlx5_vdpa_remove_debugfs(ndev->debugfs); - ndev->debugfs = NULL; unregister_link_notifier(ndev); _vdpa_unregister_device(dev); wq = mvdev->wq; diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.h b/drivers/vdpa/mlx5/net/mlx5_vnet.h index 36c44d9fdd16..90b556a57971 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.h +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.h @@ -65,6 +65,15 @@ struct mlx5_vdpa_net { struct hlist_head macvlan_hash[MLX5V_MACVLAN_SIZE]; struct mlx5_vdpa_irq_pool irqp; struct dentry *debugfs; + + u32 umem_1_buffer_param_a; + u32 umem_1_buffer_param_b; + + u32 umem_2_buffer_param_a; + u32 umem_2_buffer_param_b; + + u32 umem_3_buffer_param_a; + u32 umem_3_buffer_param_b; }; struct mlx5_vdpa_counter { @@ -88,7 +97,7 @@ struct macvlan_node { }; void mlx5_vdpa_add_debugfs(struct mlx5_vdpa_net *ndev); -void mlx5_vdpa_remove_debugfs(struct dentry *dbg); +void mlx5_vdpa_remove_debugfs(struct mlx5_vdpa_net *ndev); void mlx5_vdpa_add_rx_flow_table(struct mlx5_vdpa_net *ndev); void mlx5_vdpa_remove_rx_flow_table(struct mlx5_vdpa_net *ndev); void mlx5_vdpa_add_tirn(struct mlx5_vdpa_net *ndev); diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c index 00d7d72713be..b3a3cb165795 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c @@ -499,12 +499,13 @@ static int __init vdpasim_blk_init(void) GFP_KERNEL); if (!shared_buffer) { ret = -ENOMEM; - goto parent_err; + goto mgmt_dev_err; } } return 0; - +mgmt_dev_err: + vdpa_mgmtdev_unregister(&mgmt_dev); parent_err: device_unregister(&vdpasim_blk_mgmtdev); return ret; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index c71d573f1c94..e0c181ad17e3 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1458,9 +1458,7 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev, goto done; } - if ((msg.type == VHOST_IOTLB_UPDATE || - msg.type == VHOST_IOTLB_INVALIDATE) && - msg.size == 0) { + if (msg.type == VHOST_IOTLB_UPDATE && msg.size == 0) { ret = -EINVAL; goto done; } diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index 5c87817a4f4c..3dcf83f5e7b4 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -3440,11 +3440,15 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, } info->fix.mmio_start = raddr; +#if defined(__i386__) || defined(__ia64__) /* * By using strong UC we force the MTRR to never have an * effect on the MMIO region on both non-PAT and PAT systems. */ par->ati_regbase = ioremap_uc(info->fix.mmio_start, 0x1000); +#else + par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000); +#endif if (par->ati_regbase == NULL) return -ENOMEM; diff --git a/drivers/video/fbdev/core/cfbcopyarea.c b/drivers/video/fbdev/core/cfbcopyarea.c index 6d4bfeecee35..5b80bf3dae50 100644 --- a/drivers/video/fbdev/core/cfbcopyarea.c +++ b/drivers/video/fbdev/core/cfbcopyarea.c @@ -382,7 +382,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) { u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; u32 height = area->height, width = area->width; - unsigned long const bits_per_line = p->fix.line_length*8u; + unsigned int const bits_per_line = p->fix.line_length * 8u; unsigned long __iomem *base = NULL; int bits = BITS_PER_LONG, bytes = bits >> 3; unsigned dst_idx = 0, src_idx = 0, rev_copy = 0; diff --git a/drivers/video/fbdev/core/syscopyarea.c b/drivers/video/fbdev/core/syscopyarea.c index c1eda3190968..7b8bd3a2bedc 100644 --- a/drivers/video/fbdev/core/syscopyarea.c +++ b/drivers/video/fbdev/core/syscopyarea.c @@ -316,7 +316,7 @@ void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area) { u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; u32 height = area->height, width = area->width; - unsigned long const bits_per_line = p->fix.line_length*8u; + unsigned int const bits_per_line = p->fix.line_length * 8u; unsigned long *base = NULL; int bits = BITS_PER_LONG, bytes = bits >> 3; unsigned dst_idx = 0, src_idx = 0, rev_copy = 0; diff --git a/drivers/video/fbdev/mmp/hw/mmp_ctrl.h b/drivers/video/fbdev/mmp/hw/mmp_ctrl.h index 167585a889d3..719b99a9bc77 100644 --- a/drivers/video/fbdev/mmp/hw/mmp_ctrl.h +++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.h @@ -1406,7 +1406,7 @@ struct mmphw_ctrl { /*pathes*/ int path_num; - struct mmphw_path_plat path_plats[]; + struct mmphw_path_plat path_plats[] __counted_by(path_num); }; static inline int overlay_is_vid(struct mmp_overlay *overlay) diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c index f28cb90947a3..42c96f1cfc93 100644 --- a/drivers/video/fbdev/omap/omapfb_main.c +++ b/drivers/video/fbdev/omap/omapfb_main.c @@ -1645,13 +1645,13 @@ static int omapfb_do_probe(struct platform_device *pdev, } fbdev->int_irq = platform_get_irq(pdev, 0); if (fbdev->int_irq < 0) { - r = ENXIO; + r = -ENXIO; goto cleanup; } fbdev->ext_irq = platform_get_irq(pdev, 1); if (fbdev->ext_irq < 0) { - r = ENXIO; + r = -ENXIO; goto cleanup; } diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index 3d76ce111488..cf0f706762b4 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -1214,7 +1214,7 @@ static struct platform_driver sa1100fb_driver = { }, }; -int __init sa1100fb_init(void) +static int __init sa1100fb_init(void) { if (fb_get_options("sa1100fb", NULL)) return -ENODEV; diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c index a1a67830fbbc..e1f421e91b4f 100644 --- a/drivers/video/fbdev/uvesafb.c +++ b/drivers/video/fbdev/uvesafb.c @@ -1928,10 +1928,10 @@ static void uvesafb_exit(void) } } - cn_del_callback(&uvesafb_cn_id); driver_remove_file(&uvesafb_driver.driver, &driver_attr_v86d); platform_device_unregister(uvesafb_device); platform_driver_unregister(&uvesafb_driver); + cn_del_callback(&uvesafb_cn_id); } module_exit(uvesafb_exit); diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 5b15936a5214..2d5d252ef419 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -395,7 +395,11 @@ static inline s64 towards_target(struct virtio_balloon *vb) virtio_cread_le(vb->vdev, struct virtio_balloon_config, num_pages, &num_pages); - target = num_pages; + /* + * Aligned up to guest page size to avoid inflating and deflating + * balloon endlessly. + */ + target = ALIGN(num_pages, VIRTIO_BALLOON_PAGES_PER_PAGE); return target - vb->num_pages; } diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 97760f611295..59892a31cf76 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -631,14 +631,17 @@ static int virtio_mmio_probe(struct platform_device *pdev) spin_lock_init(&vm_dev->lock); vm_dev->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(vm_dev->base)) - return PTR_ERR(vm_dev->base); + if (IS_ERR(vm_dev->base)) { + rc = PTR_ERR(vm_dev->base); + goto free_vm_dev; + } /* Check magic value */ magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) { dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); - return -ENODEV; + rc = -ENODEV; + goto free_vm_dev; } /* Check device version */ @@ -646,7 +649,8 @@ static int virtio_mmio_probe(struct platform_device *pdev) if (vm_dev->version < 1 || vm_dev->version > 2) { dev_err(&pdev->dev, "Version %ld not supported!\n", vm_dev->version); - return -ENXIO; + rc = -ENXIO; + goto free_vm_dev; } vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); @@ -655,7 +659,8 @@ static int virtio_mmio_probe(struct platform_device *pdev) * virtio-mmio device with an ID 0 is a (dummy) placeholder * with no function. End probing now with no error reported. */ - return -ENODEV; + rc = -ENODEV; + goto free_vm_dev; } vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); @@ -685,6 +690,10 @@ static int virtio_mmio_probe(struct platform_device *pdev) put_device(&vm_dev->vdev.dev); return rc; + +free_vm_dev: + kfree(vm_dev); + return rc; } static int virtio_mmio_remove(struct platform_device *pdev) diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c index aad7d9296e77..9cb601e16688 100644 --- a/drivers/virtio/virtio_pci_modern_dev.c +++ b/drivers/virtio/virtio_pci_modern_dev.c @@ -291,7 +291,7 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev) err = -EINVAL; mdev->common = vp_modern_map_capability(mdev, common, sizeof(struct virtio_pci_common_cfg), 4, - 0, sizeof(struct virtio_pci_common_cfg), + 0, sizeof(struct virtio_pci_modern_common_cfg), NULL, NULL); if (!mdev->common) goto err_map_common; |