diff options
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/dmi-sysfs.c | 2 | ||||
-rw-r--r-- | drivers/firmware/dmi_scan.c | 64 | ||||
-rw-r--r-- | drivers/firmware/edd.c | 8 | ||||
-rw-r--r-- | drivers/firmware/iscsi_ibft.c | 5 | ||||
-rw-r--r-- | drivers/firmware/psci.c | 55 | ||||
-rw-r--r-- | drivers/firmware/qemu_fw_cfg.c | 4 |
6 files changed, 87 insertions, 51 deletions
diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c index d5de6ee8466d..ecf2eeb5f6f9 100644 --- a/drivers/firmware/dmi-sysfs.c +++ b/drivers/firmware/dmi-sysfs.c @@ -652,7 +652,7 @@ static int __init dmi_sysfs_init(void) int val; if (!dmi_kobj) { - pr_err("dmi-sysfs: dmi entry is absent.\n"); + pr_debug("dmi-sysfs: dmi entry is absent.\n"); error = -ENODATA; goto err; } diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 783041964439..e763e1484331 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -18,7 +18,7 @@ EXPORT_SYMBOL_GPL(dmi_kobj); * of and an antecedent to, SMBIOS, which stands for System * Management BIOS. See further: http://www.dmtf.org/standards */ -static const char dmi_empty_string[] = " "; +static const char dmi_empty_string[] = ""; static u32 dmi_ver __initdata; static u32 dmi_len; @@ -26,11 +26,6 @@ static u16 dmi_num; static u8 smbios_entry_point[32]; static int smbios_entry_point_size; -/* - * Catch too early calls to dmi_check_system(): - */ -static int dmi_initialized; - /* DMI system identification string used during boot */ static char dmi_ids_string[128] __initdata; @@ -44,25 +39,21 @@ static int dmi_memdev_nr; static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s) { const u8 *bp = ((u8 *) dm) + dm->length; + const u8 *nsp; if (s) { - s--; - while (s > 0 && *bp) { + while (--s > 0 && *bp) bp += strlen(bp) + 1; - s--; - } - if (*bp != 0) { - size_t len = strlen(bp)+1; - size_t cmp_len = len > 8 ? 8 : len; - - if (!memcmp(bp, dmi_empty_string, cmp_len)) - return dmi_empty_string; + /* Strings containing only spaces are considered empty */ + nsp = bp; + while (*nsp == ' ') + nsp++; + if (*nsp != '\0') return bp; - } } - return ""; + return dmi_empty_string; } static const char * __init dmi_string(const struct dmi_header *dm, u8 s) @@ -633,7 +624,7 @@ void __init dmi_scan_machine(void) if (!dmi_smbios3_present(buf)) { dmi_available = 1; - goto out; + return; } } if (efi.smbios == EFI_INVALID_TABLE_ADDR) @@ -651,7 +642,7 @@ void __init dmi_scan_machine(void) if (!dmi_present(buf)) { dmi_available = 1; - goto out; + return; } } else if (IS_ENABLED(CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK)) { p = dmi_early_remap(0xF0000, 0x10000); @@ -668,7 +659,7 @@ void __init dmi_scan_machine(void) if (!dmi_smbios3_present(buf)) { dmi_available = 1; dmi_early_unmap(p, 0x10000); - goto out; + return; } memcpy(buf, buf + 16, 16); } @@ -686,7 +677,7 @@ void __init dmi_scan_machine(void) if (!dmi_present(buf)) { dmi_available = 1; dmi_early_unmap(p, 0x10000); - goto out; + return; } memcpy(buf, buf + 16, 16); } @@ -694,8 +685,6 @@ void __init dmi_scan_machine(void) } error: pr_info("DMI not present or invalid.\n"); - out: - dmi_initialized = 1; } static ssize_t raw_table_read(struct file *file, struct kobject *kobj, @@ -715,10 +704,8 @@ static int __init dmi_init(void) u8 *dmi_table; int ret = -ENOMEM; - if (!dmi_available) { - ret = -ENODATA; - goto err; - } + if (!dmi_available) + return 0; /* * Set up dmi directory at /sys/firmware/dmi. This entry should stay @@ -784,19 +771,20 @@ static bool dmi_matches(const struct dmi_system_id *dmi) { int i; - WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n"); - for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) { int s = dmi->matches[i].slot; if (s == DMI_NONE) break; if (dmi_ident[s]) { - if (!dmi->matches[i].exact_match && - strstr(dmi_ident[s], dmi->matches[i].substr)) - continue; - else if (dmi->matches[i].exact_match && - !strcmp(dmi_ident[s], dmi->matches[i].substr)) - continue; + if (dmi->matches[i].exact_match) { + if (!strcmp(dmi_ident[s], + dmi->matches[i].substr)) + continue; + } else { + if (strstr(dmi_ident[s], + dmi->matches[i].substr)) + continue; + } } /* No match */ @@ -826,6 +814,8 @@ static bool dmi_is_end_of_table(const struct dmi_system_id *dmi) * Walk the blacklist table running matching functions until someone * returns non zero or we hit the end. Callback function is called for * each successful match. Returns the number of matches. + * + * dmi_scan_machine must be called before this function is called. */ int dmi_check_system(const struct dmi_system_id *list) { @@ -854,6 +844,8 @@ EXPORT_SYMBOL(dmi_check_system); * * Walk the blacklist table until the first match is found. Return the * pointer to the matching entry or NULL if there's no match. + * + * dmi_scan_machine must be called before this function is called. */ const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list) { diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index e22957665808..60a8f1363a10 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -669,10 +669,10 @@ edd_get_pci_dev(struct edd_device *edev) struct edd_info *info = edd_dev_get_info(edev); if (edd_dev_is_type(edev, "PCI") || edd_dev_is_type(edev, "XPRS")) { - return pci_get_bus_and_slot(info->params.interface_path.pci.bus, - PCI_DEVFN(info->params.interface_path.pci.slot, - info->params.interface_path.pci. - function)); + return pci_get_domain_bus_and_slot(0, + info->params.interface_path.pci.bus, + PCI_DEVFN(info->params.interface_path.pci.slot, + info->params.interface_path.pci.function)); } return NULL; } diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index 14042a64bdd5..6bc8e6640d71 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c @@ -719,8 +719,9 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header, * executes only devices which are in domain 0. Furthermore, the * iBFT spec doesn't have a domain id field :-( */ - pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8, - (nic->pci_bdf & 0xff)); + pci_dev = pci_get_domain_bus_and_slot(0, + (nic->pci_bdf & 0xff00) >> 8, + (nic->pci_bdf & 0xff)); if (pci_dev) { rc = sysfs_create_link(&boot_kobj->kobj, &pci_dev->dev.kobj, "device"); diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index 8b25d31e8401..c80ec1d03274 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -59,7 +59,10 @@ bool psci_tos_resident_on(int cpu) return cpu == resident_cpu; } -struct psci_operations psci_ops; +struct psci_operations psci_ops = { + .conduit = PSCI_CONDUIT_NONE, + .smccc_version = SMCCC_VERSION_1_0, +}; typedef unsigned long (psci_fn)(unsigned long, unsigned long, unsigned long, unsigned long); @@ -210,6 +213,22 @@ static unsigned long psci_migrate_info_up_cpu(void) 0, 0, 0); } +static void set_conduit(enum psci_conduit conduit) +{ + switch (conduit) { + case PSCI_CONDUIT_HVC: + invoke_psci_fn = __invoke_psci_fn_hvc; + break; + case PSCI_CONDUIT_SMC: + invoke_psci_fn = __invoke_psci_fn_smc; + break; + default: + WARN(1, "Unexpected PSCI conduit %d\n", conduit); + } + + psci_ops.conduit = conduit; +} + static int get_set_conduit_method(struct device_node *np) { const char *method; @@ -222,9 +241,9 @@ static int get_set_conduit_method(struct device_node *np) } if (!strcmp("hvc", method)) { - invoke_psci_fn = __invoke_psci_fn_hvc; + set_conduit(PSCI_CONDUIT_HVC); } else if (!strcmp("smc", method)) { - invoke_psci_fn = __invoke_psci_fn_smc; + set_conduit(PSCI_CONDUIT_SMC); } else { pr_warn("invalid \"method\" property: %s\n", method); return -EINVAL; @@ -493,6 +512,31 @@ static void __init psci_init_migrate(void) pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid); } +static void __init psci_init_smccc(void) +{ + u32 ver = ARM_SMCCC_VERSION_1_0; + int feature; + + feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID); + + if (feature != PSCI_RET_NOT_SUPPORTED) { + u32 ret; + ret = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0); + if (ret == ARM_SMCCC_VERSION_1_1) { + psci_ops.smccc_version = SMCCC_VERSION_1_1; + ver = ret; + } + } + + /* + * Conveniently, the SMCCC and PSCI versions are encoded the + * same way. No, this isn't accidental. + */ + pr_info("SMC Calling Convention v%d.%d\n", + PSCI_VERSION_MAJOR(ver), PSCI_VERSION_MINOR(ver)); + +} + static void __init psci_0_2_set_functions(void) { pr_info("Using standard PSCI v0.2 function IDs\n"); @@ -541,6 +585,7 @@ static int __init psci_probe(void) psci_init_migrate(); if (PSCI_VERSION_MAJOR(ver) >= 1) { + psci_init_smccc(); psci_init_cpu_suspend(); psci_init_system_suspend(); } @@ -654,9 +699,9 @@ int __init psci_acpi_init(void) pr_info("probing for conduit method from ACPI.\n"); if (acpi_psci_use_hvc()) - invoke_psci_fn = __invoke_psci_fn_hvc; + set_conduit(PSCI_CONDUIT_HVC); else - invoke_psci_fn = __invoke_psci_fn_smc; + set_conduit(PSCI_CONDUIT_SMC); return psci_probe(); } diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index deb483064f53..a41b572eeeb1 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -694,10 +694,8 @@ static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp) */ fw_cfg_cmdline_dev = platform_device_register_simple("fw_cfg", PLATFORM_DEVID_NONE, res, processed); - if (IS_ERR(fw_cfg_cmdline_dev)) - return PTR_ERR(fw_cfg_cmdline_dev); - return 0; + return PTR_ERR_OR_ZERO(fw_cfg_cmdline_dev); } static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp) |