diff options
369 files changed, 6441 insertions, 2556 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index b18dd1779029..f1997e9da61f 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -349,7 +349,11 @@ prototypes: locking rules: inode->i_lock may block fl_copy_lock: yes no -fl_release_private: maybe no +fl_release_private: maybe maybe[1] + +[1]: ->fl_release_private for flock or POSIX locks is currently allowed +to block. Leases however can still be freed while the i_lock is held and +so fl_release_private called on a lease should not block. ----------------------- lock_manager_operations --------------------------- prototypes: diff --git a/Documentation/laptops/00-INDEX b/Documentation/laptops/00-INDEX index d399ae1fc724..a3b4f209e562 100644 --- a/Documentation/laptops/00-INDEX +++ b/Documentation/laptops/00-INDEX @@ -18,3 +18,5 @@ sonypi.txt - info on Linux Sony Programmable I/O Device support. thinkpad-acpi.txt - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver. +toshiba_haps.txt + - information on the Toshiba HDD Active Protection Sensor driver. diff --git a/Documentation/laptops/toshiba_haps.txt b/Documentation/laptops/toshiba_haps.txt new file mode 100644 index 000000000000..11dbcfdc9e7a --- /dev/null +++ b/Documentation/laptops/toshiba_haps.txt @@ -0,0 +1,76 @@ +Kernel driver toshiba_haps +Toshiba HDD Active Protection Sensor +==================================== + +Author: Azael Avalos <coproscefalo@gmail.com> + + +0. Contents +----------- + +1. Description +2. Interface +3. Accelerometer axes +4. Supported devices +5. Usage + + +1. Description +-------------- + +This driver provides support for the accelerometer found in various Toshiba +laptops, being called "Toshiba HDD Protection - Shock Sensor" officialy, +and detects laptops automatically with this device. +On Windows, Toshiba provided software monitors this device and provides +automatic HDD protection (head unload) on sudden moves or harsh vibrations, +however, this driver only provides a notification via a sysfs file to let +userspace tools or daemons act accordingly, as well as providing a sysfs +file to set the desired protection level or sensor sensibility. + + +2. Interface +------------ + +This device comes with 3 methods: +_STA - Checks existence of the device, returning Zero if the device does not + exists or is not supported. +PTLV - Sets the desired protection level. +RSSS - Shuts down the HDD protection interface for a few seconds, + then restores normal operation. + +Note: +The presence of Solid State Drives (SSD) can make this driver to fail loading, +given the fact that such drives have no movable parts, and thus, not requiring +any "protection" as well as failing during the evaluation of the _STA method +found under this device. + + +3. Accelerometer axes +--------------------- + +This device does not report any axes, however, to query the sensor position +a couple HCI (Hardware Configuration Interface) calls (0x6D and 0xA6) are +provided to query such information, handled by the kernel module toshiba_acpi +since kernel version 3.15. + + +4. Supported devices +-------------------- + +This driver binds itself to the ACPI device TOS620A, and any Toshiba laptop +with this device is supported, given the fact that they have the presence of +conventional HDD and not only SSD, or a combination of both HDD and SSD. + + +5. Usage +-------- + +The sysfs files under /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS620A:00/ are: +protection_level - The protection_level is readable and writeable, and + provides a way to let userspace query the current protection + level, as well as set the desired protection level, the + available protection levels are: + 0 - Disabled | 1 - Low | 2 - Medium | 3 - High +reset_protection - The reset_protection entry is writeable only, being "1" + the only parameter it accepts, it is used to trigger + a reset of the protection interface. diff --git a/MAINTAINERS b/MAINTAINERS index 2f85f55c8fb8..aefa94841ff3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7059,6 +7059,7 @@ F: drivers/scsi/pmcraid.* PMC SIERRA PM8001 DRIVER M: xjtuwjp@gmail.com M: lindar_liu@usish.com +L: pmchba@pmcs.com L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/pm8001/ @@ -10016,7 +10017,7 @@ F: arch/x86/ X86 PLATFORM DRIVERS M: Matthew Garrett <matthew.garrett@nebula.com> L: platform-driver-x86@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git +T: git git://cavan.codon.org.uk/platform-drivers-x86.git S: Maintained F: drivers/platform/x86/ @@ -1,7 +1,7 @@ VERSION = 3 -PATCHLEVEL = 16 +PATCHLEVEL = 17 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = -rc1 NAME = Shuffling Zombie Juror # *DOCUMENTATION* diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h index 886cab456e1b..c842a89b1190 100644 --- a/arch/sparc/include/uapi/asm/unistd.h +++ b/arch/sparc/include/uapi/asm/unistd.h @@ -413,8 +413,9 @@ #define __NR_renameat2 345 #define __NR_seccomp 346 #define __NR_getrandom 347 +#define __NR_memfd_create 348 -#define NR_syscalls 348 +#define NR_syscalls 349 /* Bitmask values returned from kern_features system call. */ #define KERN_FEATURE_MIXED_MODE_STACK 0x00000001 diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 539babf00bb2..b36365f49478 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -432,6 +432,11 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm, node->full_name); return; } + + if (ofpci_verbose) + printk(" Bridge bus range [%u --> %u]\n", + busrange[0], busrange[1]); + ranges = of_get_property(node, "ranges", &len); simba = 0; if (ranges == NULL) { @@ -451,6 +456,10 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm, pci_bus_insert_busn_res(bus, busrange[0], busrange[1]); bus->bridge_ctl = 0; + if (ofpci_verbose) + printk(" Bridge ranges[%p] simba[%d]\n", + ranges, simba); + /* parse ranges property, or cook one up by hand for Simba */ /* PCI #address-cells == 3 and #size-cells == 2 always */ res = &dev->resource[PCI_BRIDGE_RESOURCES]; @@ -468,10 +477,29 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm, } i = 1; for (; len >= 32; len -= 32, ranges += 8) { + u64 start; + + if (ofpci_verbose) + printk(" RAW Range[%08x:%08x:%08x:%08x:%08x:%08x:" + "%08x:%08x]\n", + ranges[0], ranges[1], ranges[2], ranges[3], + ranges[4], ranges[5], ranges[6], ranges[7]); + flags = pci_parse_of_flags(ranges[0]); size = GET_64BIT(ranges, 6); if (flags == 0 || size == 0) continue; + + /* On PCI-Express systems, PCI bridges that have no devices downstream + * have a bogus size value where the first 32-bit cell is 0xffffffff. + * This results in a bogus range where start + size overflows. + * + * Just skip these otherwise the kernel will complain when the resource + * tries to be claimed. + */ + if (size >> 32 == 0xffffffff) + continue; + if (flags & IORESOURCE_IO) { res = bus->resource[0]; if (res->flags) { @@ -490,8 +518,13 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm, } res->flags = flags; - region.start = GET_64BIT(ranges, 1); + region.start = start = GET_64BIT(ranges, 1); region.end = region.start + size - 1; + + if (ofpci_verbose) + printk(" Using flags[%08x] start[%016llx] size[%016llx]\n", + flags, start, size); + pcibios_bus_to_resource(dev->bus, res, ®ion); } after_ranges: @@ -584,6 +617,36 @@ static void pci_bus_register_of_sysfs(struct pci_bus *bus) pci_bus_register_of_sysfs(child_bus); } +static void pci_claim_bus_resources(struct pci_bus *bus) +{ + struct pci_bus *child_bus; + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *r = &dev->resource[i]; + + if (r->parent || !r->start || !r->flags) + continue; + + if (ofpci_verbose) + printk("PCI: Claiming %s: " + "Resource %d: %016llx..%016llx [%x]\n", + pci_name(dev), i, + (unsigned long long)r->start, + (unsigned long long)r->end, + (unsigned int)r->flags); + + pci_claim_resource(dev, i); + } + } + + list_for_each_entry(child_bus, &bus->children, node) + pci_claim_bus_resources(child_bus); +} + struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, struct device *parent) { @@ -614,6 +677,8 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, pci_bus_add_devices(bus); pci_bus_register_of_sysfs(bus); + pci_claim_bus_resources(bus); + return bus; } diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 217893e18d78..6a873c344bc0 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -86,4 +86,4 @@ sys_call_table: /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime /*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev /*340*/ .long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr -/*345*/ .long sys_renameat2, sys_seccomp, sys_getrandom +/*345*/ .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index d93b49d1b420..d9151b6490d8 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -87,7 +87,7 @@ sys_call_table32: /*330*/ .word compat_sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev /*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr - .word sys32_renameat2, sys_seccomp, sys_getrandom + .word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create #endif /* CONFIG_COMPAT */ @@ -166,4 +166,4 @@ sys_call_table: /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev /*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr - .word sys_renameat2, sys_seccomp, sys_getrandom + .word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index eac9e92fe181..e21331ce368f 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h @@ -149,6 +149,9 @@ #define MSR_CORE_C1_RES 0x00000660 +#define MSR_CC6_DEMOTION_POLICY_CONFIG 0x00000668 +#define MSR_MC6_DEMOTION_POLICY_CONFIG 0x00000669 + #define MSR_AMD64_MC0_MASK 0xc0010044 #define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x)) diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index cfc6f9dfcd90..0939f86f543d 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -945,7 +945,7 @@ static struct intel_uncore_type *snbep_pci_uncores[] = { NULL, }; -static DEFINE_PCI_DEVICE_TABLE(snbep_uncore_pci_ids) = { +static const struct pci_device_id snbep_uncore_pci_ids[] = { { /* Home Agent */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA), .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_HA, 0), @@ -1510,7 +1510,7 @@ static struct intel_uncore_type *ivt_pci_uncores[] = { NULL, }; -static DEFINE_PCI_DEVICE_TABLE(ivt_uncore_pci_ids) = { +static const struct pci_device_id ivt_uncore_pci_ids[] = { { /* Home Agent 0 */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe30), .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_HA, 0), @@ -1985,7 +1985,7 @@ static struct intel_uncore_type *snb_pci_uncores[] = { NULL, }; -static DEFINE_PCI_DEVICE_TABLE(snb_uncore_pci_ids) = { +static const struct pci_device_id snb_uncore_pci_ids[] = { { /* IMC */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SNB_IMC), .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0), @@ -1993,7 +1993,7 @@ static DEFINE_PCI_DEVICE_TABLE(snb_uncore_pci_ids) = { { /* end: all zeroes */ }, }; -static DEFINE_PCI_DEVICE_TABLE(ivb_uncore_pci_ids) = { +static const struct pci_device_id ivb_uncore_pci_ids[] = { { /* IMC */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_IMC), .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0), @@ -2001,7 +2001,7 @@ static DEFINE_PCI_DEVICE_TABLE(ivb_uncore_pci_ids) = { { /* end: all zeroes */ }, }; -static DEFINE_PCI_DEVICE_TABLE(hsw_uncore_pci_ids) = { +static const struct pci_device_id hsw_uncore_pci_ids[] = { { /* IMC */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC), .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0), diff --git a/arch/x86/kernel/iosf_mbi.c b/arch/x86/kernel/iosf_mbi.c index d30acdc1229d..9030e83db6ee 100644 --- a/arch/x86/kernel/iosf_mbi.c +++ b/arch/x86/kernel/iosf_mbi.c @@ -202,7 +202,7 @@ static int iosf_mbi_probe(struct pci_dev *pdev, return 0; } -static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = { +static const struct pci_device_id iosf_mbi_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BAYTRAIL) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_QUARK_X1000) }, { 0, }, diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 48bcf38a0ea8..1c162e7be045 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -540,12 +540,12 @@ static int acpi_battery_get_state(struct acpi_battery *battery) */ if (battery->capacity_now > battery->full_charge_capacity && battery->full_charge_capacity != ACPI_BATTERY_VALUE_UNKNOWN) { - battery->capacity_now = battery->full_charge_capacity; if (battery->capacity_now != battery->design_capacity) printk_once(KERN_WARNING FW_BUG "battery: reported current charge level (%d) " "is higher than reported maximum charge level (%d).\n", battery->capacity_now, battery->full_charge_capacity); + battery->capacity_now = battery->full_charge_capacity; } if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 4fcbd670415c..d9f71581b79b 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -120,6 +120,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, unsigned int cpu = (unsigned long)hcpu; struct acpi_processor *pr = per_cpu(processors, cpu); struct acpi_device *device; + action &= ~CPU_TASKS_FROZEN; /* * CPU_STARTING and CPU_DYING must not sleep. Return here since diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5d592e17d760..0a817ad24f16 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -353,7 +353,8 @@ static int acpi_scan_hot_remove(struct acpi_device *device) unsigned long long sta; acpi_status status; - if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) { + if (device->handler && device->handler->hotplug.demand_offline + && !acpi_force_hot_remove) { if (!acpi_scan_is_offline(device, true)) return -EBUSY; } else { diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 295f3afbbef5..db1e9560d8a7 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -4632,7 +4632,7 @@ static void mtip_pci_shutdown(struct pci_dev *pdev) } /* Table of device ids supported by this driver. */ -static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = { +static const struct pci_device_id mtip_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320H_DEVICE_ID) }, { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320M_DEVICE_ID) }, { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320S_DEVICE_ID) }, diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c index a8de2eec6ff3..820b4009d5f7 100644 --- a/drivers/block/rsxx/core.c +++ b/drivers/block/rsxx/core.c @@ -1137,7 +1137,7 @@ static const struct pci_error_handlers rsxx_err_handler = { .slot_reset = rsxx_slot_reset, }; -static DEFINE_PCI_DEVICE_TABLE(rsxx_pci_ids) = { +static const struct pci_device_id rsxx_pci_ids[] = { {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS70_FLASH)}, {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS80_FLASH)}, {0,}, diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index f0a089df85cc..8fcdcfb4b472 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c @@ -4766,7 +4766,7 @@ static const struct block_device_operations skd_blockdev_ops = { ***************************************************************************** */ -static DEFINE_PCI_DEVICE_TABLE(skd_pci_tbl) = { +static const struct pci_device_id skd_pci_tbl[] = { { PCI_VENDOR_ID_STEC, PCI_DEVICE_ID_S1120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, { 0 } /* terminate list */ diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 0027137daa56..2e3139eda93b 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -116,6 +116,7 @@ static int probe_common(struct virtio_device *vdev) .cleanup = virtio_cleanup, .priv = (unsigned long)vi, .name = vi->name, + .quality = 1000, }; vdev->priv = vi; diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 1f4d4e315057..a46c223c2506 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -24,6 +24,7 @@ #include <linux/cpufreq.h> #include <linux/cpumask.h> #include <linux/export.h> +#include <linux/module.h> #include <linux/mutex.h> #include <linux/of_platform.h> #include <linux/pm_opp.h> @@ -593,3 +594,7 @@ void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops) arm_bL_ops = NULL; } EXPORT_SYMBOL_GPL(bL_cpufreq_unregister); + +MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>"); +MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c index 8d9d59108906..4550f6976768 100644 --- a/drivers/cpufreq/arm_big_little_dt.c +++ b/drivers/cpufreq/arm_big_little_dt.c @@ -114,4 +114,4 @@ module_platform_driver(generic_bL_platdrv); MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>"); MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 86beda9f950b..0d2172b07765 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -137,7 +137,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) * not yet registered, we should try defering probe. */ if (PTR_ERR(cpu_reg) == -EPROBE_DEFER) { - dev_err(cpu_dev, "cpu0 regulator not ready, retry\n"); + dev_dbg(cpu_dev, "cpu0 regulator not ready, retry\n"); ret = -EPROBE_DEFER; goto out_put_node; } diff --git a/drivers/cpufreq/cpufreq_opp.c b/drivers/cpufreq/cpufreq_opp.c index c0c6f4a4eccf..f7a32d2326c6 100644 --- a/drivers/cpufreq/cpufreq_opp.c +++ b/drivers/cpufreq/cpufreq_opp.c @@ -60,7 +60,7 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev, goto out; } - freq_table = kzalloc(sizeof(*freq_table) * (max_opps + 1), GFP_KERNEL); + freq_table = kcalloc(sizeof(*freq_table), (max_opps + 1), GFP_ATOMIC); if (!freq_table) { ret = -ENOMEM; goto out; diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c index e5122f1bfe78..c1320528b9d0 100644 --- a/drivers/cpufreq/integrator-cpufreq.c +++ b/drivers/cpufreq/integrator-cpufreq.c @@ -92,7 +92,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, * Bind to the specified CPU. When this call returns, * we should be running on the right CPU. */ - set_cpus_allowed(current, cpumask_of_cpu(cpu)); + set_cpus_allowed_ptr(current, cpumask_of(cpu)); BUG_ON(cpu != smp_processor_id()); /* get current setting */ @@ -118,7 +118,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, freqs.new = icst_hz(&cclk_params, vco) / 1000; if (freqs.old == freqs.new) { - set_cpus_allowed(current, cpus_allowed); + set_cpus_allowed_ptr(current, &cpus_allowed); return 0; } @@ -141,7 +141,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, /* * Restore the CPUs allowed mask. */ - set_cpus_allowed(current, cpus_allowed); + set_cpus_allowed_ptr(current, &cpus_allowed); cpufreq_freq_transition_end(policy, &freqs, 0); @@ -157,7 +157,7 @@ static unsigned int integrator_get(unsigned int cpu) cpus_allowed = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); + set_cpus_allowed_ptr(current, cpumask_of(cpu)); BUG_ON(cpu != smp_processor_id()); /* detect memory etc. */ @@ -173,7 +173,7 @@ static unsigned int integrator_get(unsigned int cpu) current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */ - set_cpus_allowed(current, cpus_allowed); + set_cpus_allowed_ptr(current, &cpus_allowed); return current_freq; } diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index 8635eec96da5..5fc96d5d656b 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -324,8 +324,8 @@ static int __init speedstep_init(void) return -ENODEV; } - pr_debug("signature:0x%.8ulx, command:0x%.8ulx, " - "event:0x%.8ulx, perf_level:0x%.8ulx.\n", + pr_debug("signature:0x%.8x, command:0x%.8x, " + "event:0x%.8x, perf_level:0x%.8x.\n", ist_info.signature, ist_info.command, ist_info.event, ist_info.perf_level); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index ae5a42595e1c..34db2fb3ef1e 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -31,7 +31,8 @@ * The default values do not overflow. */ #define BUCKETS 12 -#define INTERVALS 8 +#define INTERVAL_SHIFT 3 +#define INTERVALS (1UL << INTERVAL_SHIFT) #define RESOLUTION 1024 #define DECAY 8 #define MAX_INTERESTING 50000 @@ -133,15 +134,12 @@ struct menu_device { #define LOAD_INT(x) ((x) >> FSHIFT) #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) -static int get_loadavg(void) +static inline int get_loadavg(unsigned long load) { - unsigned long this = this_cpu_load(); - - - return LOAD_INT(this) * 10 + LOAD_FRAC(this) / 10; + return LOAD_INT(load) * 10 + LOAD_FRAC(load) / 10; } -static inline int which_bucket(unsigned int duration) +static inline int which_bucket(unsigned int duration, unsigned long nr_iowaiters) { int bucket = 0; @@ -151,7 +149,7 @@ static inline int which_bucket(unsigned int duration) * This allows us to calculate * E(duration)|iowait */ - if (nr_iowait_cpu(smp_processor_id())) + if (nr_iowaiters) bucket = BUCKETS/2; if (duration < 10) @@ -174,16 +172,16 @@ static inline int which_bucket(unsigned int duration) * to be, the higher this multiplier, and thus the higher * the barrier to go to an expensive C state. */ -static inline int performance_multiplier(void) +static inline int performance_multiplier(unsigned long nr_iowaiters, unsigned long load) { int mult = 1; /* for higher loadavg, we are more reluctant */ - mult += 2 * get_loadavg(); + mult += 2 * get_loadavg(load); /* for IO wait tasks (per cpu!) we add 5x each */ - mult += 10 * nr_iowait_cpu(smp_processor_id()); + mult += 10 * nr_iowaiters; return mult; } @@ -227,7 +225,10 @@ again: max = value; } } - do_div(avg, divisor); + if (divisor == INTERVALS) + avg >>= INTERVAL_SHIFT; + else + do_div(avg, divisor); /* Then try to determine standard deviation */ stddev = 0; @@ -238,7 +239,11 @@ again: stddev += diff * diff; } } - do_div(stddev, divisor); + if (divisor == INTERVALS) + stddev >>= INTERVAL_SHIFT; + else + do_div(stddev, divisor); + /* * The typical interval is obtained when standard deviation is small * or standard deviation is small compared to the average interval. @@ -288,7 +293,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); int i; unsigned int interactivity_req; - struct timespec t; + unsigned long nr_iowaiters, cpu_load; if (data->needs_update) { menu_update(drv, dev); @@ -302,12 +307,10 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) return 0; /* determine the expected residency time, round up */ - t = ktime_to_timespec(tick_nohz_get_sleep_length()); - data->next_timer_us = - t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC; - + data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length()); - data->bucket = which_bucket(data->next_timer_us); + get_iowait_load(&nr_iowaiters, &cpu_load); + data->bucket = which_bucket(data->next_timer_us, nr_iowaiters); /* * Force the result of multiplication to be 64 bits even if both @@ -325,7 +328,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * duration / latency ratio. Adjust the latency limit if * necessary. */ - interactivity_req = data->predicted_us / performance_multiplier(); + interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load); if (latency_req > interactivity_req) latency_req = interactivity_req; diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c index 180cc87b4dbb..7f89c946adfe 100644 --- a/drivers/crypto/ccp/ccp-pci.c +++ b/drivers/crypto/ccp/ccp-pci.c @@ -320,7 +320,7 @@ static int ccp_pci_resume(struct pci_dev *pdev) } #endif -static DEFINE_PCI_DEVICE_TABLE(ccp_pci_table) = { +static const struct pci_device_id ccp_pci_table[] = { { PCI_VDEVICE(AMD, 0x1537), }, /* Last entry must be zero */ { 0, } diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index f8665f9c3e03..fd89ca982748 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -253,12 +253,12 @@ config EDAC_I7300 Clarksboro MCH (Intel 7300 chipset). config EDAC_SBRIDGE - tristate "Intel Sandy-Bridge Integrated MC" + tristate "Intel Sandy-Bridge/Ivy-Bridge/Haswell Integrated MC" depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL depends on PCI_MMCONFIG help Support for error detection and correction the Intel - Sandy Bridge Integrated Memory Controller. + Sandy Bridge, Ivy Bridge and Haswell Integrated Memory Controllers. config EDAC_MPC85XX tristate "Freescale MPC83xx / MPC85xx" diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 01fae8289cf0..a6cd36100663 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -108,7 +108,9 @@ static const char * const mem_types[] = { [MEM_RDDR2] = "Registered-DDR2", [MEM_XDR] = "XDR", [MEM_DDR3] = "Unbuffered-DDR3", - [MEM_RDDR3] = "Registered-DDR3" + [MEM_RDDR3] = "Registered-DDR3", + [MEM_DDR4] = "Unbuffered-DDR4", + [MEM_RDDR4] = "Registered-DDR4" }; static const char * const dev_types[] = { diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index deea0dc9999b..0034c4844428 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -99,6 +99,7 @@ static const u32 ibridge_dram_rule[] = { #define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3) #define INTERLEAVE_MODE(reg) GET_BITFIELD(reg, 1, 1) #define DRAM_RULE_ENABLE(reg) GET_BITFIELD(reg, 0, 0) +#define A7MODE(reg) GET_BITFIELD(reg, 26, 26) static char *get_dram_attr(u32 reg) { @@ -164,6 +165,8 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg, #define TOLM 0x80 #define TOHM 0x84 +#define HASWELL_TOHM_0 0xd4 +#define HASWELL_TOHM_1 0xd8 #define GET_TOLM(reg) ((GET_BITFIELD(reg, 0, 3) << 28) | 0x3ffffff) #define GET_TOHM(reg) ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff) @@ -176,8 +179,6 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg, #define SAD_CONTROL 0xf4 -#define NODE_ID(reg) GET_BITFIELD(reg, 0, 2) - /* Device 14 function 0 */ static const u32 tad_dram_rule[] = { @@ -235,7 +236,6 @@ static const u32 rir_way_limit[] = { #define IS_RIR_VALID(reg) GET_BITFIELD(reg, 31, 31) #define RIR_WAY(reg) GET_BITFIELD(reg, 28, 29) -#define RIR_LIMIT(reg) ((GET_BITFIELD(reg, 1, 10) << 29)| 0x1fffffff) #define MAX_RIR_WAY 8 @@ -279,8 +279,6 @@ static const u32 correrrthrsld[] = { #define IB_RANK_CFG_A 0x0320 -#define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11) - /* * sbridge structs */ @@ -291,6 +289,7 @@ static const u32 correrrthrsld[] = { enum type { SANDY_BRIDGE, IVY_BRIDGE, + HASWELL, }; struct sbridge_pvt; @@ -300,11 +299,15 @@ struct sbridge_info { u32 rankcfgr; u64 (*get_tolm)(struct sbridge_pvt *pvt); u64 (*get_tohm)(struct sbridge_pvt *pvt); + u64 (*rir_limit)(u32 reg); const u32 *dram_rule; const u32 *interleave_list; const struct interleave_pkg *interleave_pkg; u8 max_sad; u8 max_interleave; + u8 (*get_node_id)(struct sbridge_pvt *pvt); + enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt); + struct pci_dev *pci_vtd; }; struct sbridge_channel { @@ -313,9 +316,7 @@ struct sbridge_channel { }; struct pci_id_descr { - int dev; - int func; - int dev_id; + int dev_id; int optional; }; @@ -338,6 +339,7 @@ struct sbridge_pvt { struct pci_dev *pci_sad0, *pci_sad1; struct pci_dev *pci_ha0, *pci_ha1; struct pci_dev *pci_br0, *pci_br1; + struct pci_dev *pci_ha1_ta; struct pci_dev *pci_tad[NUM_CHANNELS]; struct sbridge_dev *sbridge_dev; @@ -362,31 +364,29 @@ struct sbridge_pvt { u64 tolm, tohm; }; -#define PCI_DESCR(device, function, device_id, opt) \ - .dev = (device), \ - .func = (function), \ - .dev_id = (device_id), \ +#define PCI_DESCR(device_id, opt) \ + .dev_id = (device_id), \ .optional = opt static const struct pci_id_descr pci_dev_descr_sbridge[] = { /* Processor Home Agent */ - { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) }, /* Memory controller */ - { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) }, - { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) }, - { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) }, - { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) }, - { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) }, - { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) }, - { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) }, /* System Address Decoder */ - { PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) }, - { PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) }, /* Broadcast Registers */ - { PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) }, }; #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) } @@ -423,34 +423,34 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = { static const struct pci_id_descr pci_dev_descr_ibridge[] = { /* Processor Home Agent */ - { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) }, /* Memory controller */ - { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) }, - { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) }, - { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) }, - { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) }, - { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) }, - { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) }, /* System Address Decoder */ - { PCI_DESCR(22, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) }, /* Broadcast Registers */ - { PCI_DESCR(22, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) }, - { PCI_DESCR(22, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) }, /* Optional, mode 2HA */ - { PCI_DESCR(28, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) }, #if 0 - { PCI_DESCR(29, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) }, - { PCI_DESCR(29, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) }, #endif - { PCI_DESCR(29, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) }, - { PCI_DESCR(29, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) }, - { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) }, - { PCI_DESCR(17, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) }, }; static const struct pci_id_table pci_dev_descr_ibridge_table[] = { @@ -458,12 +458,80 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { {0,} /* 0 terminated list. */ }; +/* Haswell support */ +/* EN processor: + * - 1 IMC + * - 3 DDR3 channels, 2 DPC per channel + * EP processor: + * - 1 or 2 IMC + * - 4 DDR4 channels, 3 DPC per channel + * EP 4S processor: + * - 2 IMC + * - 4 DDR4 channels, 3 DPC per channel + * EX processor: + * - 2 IMC + * - each IMC interfaces with a SMI 2 channel + * - each SMI channel interfaces with a scalable memory buffer + * - each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC + */ +#define HASWELL_DDRCRCLKCONTROLS 0xa10 +#define HASWELL_HASYSDEFEATURE2 0x84 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1 0x2f60 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA 0x2fa8 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL 0x2f71 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA 0x2f68 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL 0x2f79 +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1 0x2fab +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2 0x2fac +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3 0x2fad +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 0x2f6a +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1 0x2f6b +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd +static const struct pci_id_descr pci_dev_descr_haswell[] = { + /* first item must be the HA */ + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) }, + + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1) }, + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1) }, +}; + +static const struct pci_id_table pci_dev_descr_haswell_table[] = { + PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell), + {0,} /* 0 terminated list. */ +}; + /* * pci_device_id table for which devices we are looking for */ static const struct pci_device_id sbridge_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)}, {0,} /* 0 terminated list. */ }; @@ -472,13 +540,17 @@ static const struct pci_device_id sbridge_pci_tbl[] = { Ancillary status routines ****************************************************************************/ -static inline int numrank(u32 mtr) +static inline int numrank(enum type type, u32 mtr) { int ranks = (1 << RANK_CNT_BITS(mtr)); + int max = 4; - if (ranks > 4) { - edac_dbg(0, "Invalid number of ranks: %d (max = 4) raw value = %x (%04x)\n", - ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr); + if (type == HASWELL) + max = 8; + + if (ranks > max) { + edac_dbg(0, "Invalid number of ranks: %d (max = %i) raw value = %x (%04x)\n", + ranks, max, (unsigned int)RANK_CNT_BITS(mtr), mtr); return -EINVAL; } @@ -588,10 +660,107 @@ static u64 ibridge_get_tohm(struct sbridge_pvt *pvt) return GET_TOHM(reg); } +static u64 rir_limit(u32 reg) +{ + return ((u64)GET_BITFIELD(reg, 1, 10) << 29) | 0x1fffffff; +} + +static enum mem_type get_memory_type(struct sbridge_pvt *pvt) +{ + u32 reg; + enum mem_type mtype; + + if (pvt->pci_ddrio) { + pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr, + ®); + if (GET_BITFIELD(reg, 11, 11)) + /* FIXME: Can also be LRDIMM */ + mtype = MEM_RDDR3; + else + mtype = MEM_DDR3; + } else + mtype = MEM_UNKNOWN; + + return mtype; +} + +static enum mem_type haswell_get_memory_type(struct sbridge_pvt *pvt) +{ + u32 reg; + bool registered = false; + enum mem_type mtype = MEM_UNKNOWN; + + if (!pvt->pci_ddrio) + goto out; + + pci_read_config_dword(pvt->pci_ddrio, + HASWELL_DDRCRCLKCONTROLS, ®); + /* Is_Rdimm */ + if (GET_BITFIELD(reg, 16, 16)) + registered = true; + + pci_read_config_dword(pvt->pci_ta, MCMTR, ®); + if (GET_BITFIELD(reg, 14, 14)) { + if (registered) + mtype = MEM_RDDR4; + else + mtype = MEM_DDR4; + } else { + if (registered) + mtype = MEM_RDDR3; + else + mtype = MEM_DDR3; + } + +out: + return mtype; +} + +static u8 get_node_id(struct sbridge_pvt *pvt) +{ + u32 reg; + pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, ®); + return GET_BITFIELD(reg, 0, 2); +} + +static u8 haswell_get_node_id(struct sbridge_pvt *pvt) +{ + u32 reg; + + pci_read_config_dword(pvt->pci_sad1, SAD_CONTROL, ®); + return GET_BITFIELD(reg, 0, 3); +} + +static u64 haswell_get_tolm(struct sbridge_pvt *pvt) +{ + u32 reg; + + pci_read_config_dword(pvt->info.pci_vtd, TOLM, ®); + return (GET_BITFIELD(reg, 26, 31) << 26) | 0x1ffffff; +} + +static u64 haswell_get_tohm(struct sbridge_pvt *pvt) +{ + u64 rc; + u32 reg; + + pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_0, ®); + rc = GET_BITFIELD(reg, 26, 31); + pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, ®); + rc = ((reg << 6) | rc) << 26; + + return rc | 0x1ffffff; +} + +static u64 haswell_rir_limit(u32 reg) +{ + return (((u64)GET_BITFIELD(reg, 1, 11) + 1) << 29) - 1; +} + static inline u8 sad_pkg_socket(u8 pkg) { /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */ - return (pkg >> 3) | (pkg & 0x3); + return ((pkg >> 3) << 2) | (pkg & 0x3); } static inline u8 sad_pkg_ha(u8 pkg) @@ -602,44 +771,43 @@ static inline u8 sad_pkg_ha(u8 pkg) /**************************************************************************** Memory check routines ****************************************************************************/ -static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot, - unsigned func) +static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id) { - struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus); - int i; - - if (!sbridge_dev) - return NULL; - - for (i = 0; i < sbridge_dev->n_devs; i++) { - if (!sbridge_dev->pdev[i]) - continue; + struct pci_dev *pdev = NULL; - if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot && - PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) { - edac_dbg(1, "Associated %02x.%02x.%d with %p\n", - bus, slot, func, sbridge_dev->pdev[i]); - return sbridge_dev->pdev[i]; - } - } + do { + pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev); + if (pdev && pdev->bus->number == bus) + break; + } while (pdev); - return NULL; + return pdev; } /** * check_if_ecc_is_active() - Checks if ECC is active - * bus: Device bus + * @bus: Device bus + * @type: Memory controller type + * returns: 0 in case ECC is active, -ENODEV if it can't be determined or + * disabled */ -static int check_if_ecc_is_active(const u8 bus) +static int check_if_ecc_is_active(const u8 bus, enum type type) { struct pci_dev *pdev = NULL; - u32 mcmtr; + u32 mcmtr, id; + + if (type == IVY_BRIDGE) + id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA; + else if (type == HASWELL) + id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA; + else + id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA; - pdev = get_pdev_slot_func(bus, 15, 0); + pdev = get_pdev_same_bus(bus, id); if (!pdev) { sbridge_printk(KERN_ERR, "Couldn't find PCI device " - "%2x.%02d.%d!!!\n", - bus, 15, 0); + "%04x:%04x! on bus %02d\n", + PCI_VENDOR_ID_INTEL, id, bus); return -ENODEV; } @@ -661,11 +829,14 @@ static int get_dimm_config(struct mem_ctl_info *mci) enum edac_type mode; enum mem_type mtype; - pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); + if (pvt->info.type == HASWELL) + pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, ®); + else + pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); + pvt->sbridge_dev->source_id = SOURCE_ID(reg); - pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, ®); - pvt->sbridge_dev->node_id = NODE_ID(reg); + pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt); edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", pvt->sbridge_dev->mc, pvt->sbridge_dev->node_id, @@ -698,24 +869,18 @@ static int get_dimm_config(struct mem_ctl_info *mci) pvt->is_close_pg = false; } - if (pvt->pci_ddrio) { - pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr, - ®); - if (IS_RDIMM_ENABLED(reg)) { - /* FIXME: Can also be LRDIMM */ - edac_dbg(0, "Memory is registered\n"); - mtype = MEM_RDDR3; - } else { - edac_dbg(0, "Memory is unregistered\n"); - mtype = MEM_DDR3; - } - } else { + mtype = pvt->info.get_memory_type(pvt); + if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4) + edac_dbg(0, "Memory is registered\n"); + else if (mtype == MEM_UNKNOWN) edac_dbg(0, "Cannot determine memory type\n"); - mtype = MEM_UNKNOWN; - } + else + edac_dbg(0, "Memory is unregistered\n"); - /* On all supported DDR3 DIMM types, there are 8 banks available */ - banks = 8; + if (mtype == MEM_DDR4 || MEM_RDDR4) + banks = 16; + else + banks = 8; for (i = 0; i < NUM_CHANNELS; i++) { u32 mtr; @@ -729,11 +894,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) if (IS_DIMM_PRESENT(mtr)) { pvt->channel[i].dimms++; - ranks = numrank(mtr); + ranks = numrank(pvt->info.type, mtr); rows = numrow(mtr); cols = numcol(mtr); - /* DDR3 has 8 I/O banks */ size = ((u64)rows * cols * banks * ranks) >> (20 - 3); npages = MiB_TO_PAGES(size); @@ -744,7 +908,17 @@ static int get_dimm_config(struct mem_ctl_info *mci) dimm->nr_pages = npages; dimm->grain = 32; - dimm->dtype = (banks == 8) ? DEV_X8 : DEV_X4; + switch (banks) { + case 16: + dimm->dtype = DEV_X16; + break; + case 8: + dimm->dtype = DEV_X8; + break; + case 4: + dimm->dtype = DEV_X4; + break; + } dimm->mtype = mtype; dimm->edac_mode = mode; snprintf(dimm->label, sizeof(dimm->label), @@ -887,7 +1061,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) if (!IS_RIR_VALID(reg)) continue; - tmp_mb = RIR_LIMIT(reg) >> 20; + tmp_mb = pvt->info.rir_limit(reg) >> 20; rir_way = 1 << RIR_WAY(reg); mb = div_u64_rem(tmp_mb, 1000, &kb); edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", @@ -936,11 +1110,11 @@ static int get_memory_error_data(struct mem_ctl_info *mci, struct mem_ctl_info *new_mci; struct sbridge_pvt *pvt = mci->pvt_info; struct pci_dev *pci_ha; - int n_rir, n_sads, n_tads, sad_way, sck_xch; + int n_rir, n_sads, n_tads, sad_way, sck_xch; int sad_interl, idx, base_ch; - int interleave_mode; + int interleave_mode, shiftup = 0; unsigned sad_interleave[pvt->info.max_interleave]; - u32 reg; + u32 reg, dram_rule; u8 ch_way, sck_way, pkg, sad_ha = 0; u32 tad_offset; u32 rir_way; @@ -987,8 +1161,9 @@ static int get_memory_error_data(struct mem_ctl_info *mci, sprintf(msg, "Can't discover the memory socket"); return -EINVAL; } - *area_type = get_dram_attr(reg); - interleave_mode = INTERLEAVE_MODE(reg); + dram_rule = reg; + *area_type = get_dram_attr(dram_rule); + interleave_mode = INTERLEAVE_MODE(dram_rule); pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads], ®); @@ -1033,6 +1208,36 @@ static int get_memory_error_data(struct mem_ctl_info *mci, *socket = sad_interleave[idx]; edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", idx, sad_way, *socket); + } else if (pvt->info.type == HASWELL) { + int bits, a7mode = A7MODE(dram_rule); + + if (a7mode) { + /* A7 mode swaps P9 with P6 */ + bits = GET_BITFIELD(addr, 7, 8) << 1; + bits |= GET_BITFIELD(addr, 9, 9); + } else + bits = GET_BITFIELD(addr, 7, 9); + + if (interleave_mode) { + /* interleave mode will XOR {8,7,6} with {18,17,16} */ + idx = GET_BITFIELD(addr, 16, 18); + idx ^= bits; + } else + idx = bits; + + pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx); + *socket = sad_pkg_socket(pkg); + sad_ha = sad_pkg_ha(pkg); + + if (a7mode) { + /* MCChanShiftUpEnable */ + pci_read_config_dword(pvt->pci_ha0, + HASWELL_HASYSDEFEATURE2, ®); + shiftup = GET_BITFIELD(reg, 22, 22); + } + + edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %i, shiftup: %i\n", + idx, *socket, sad_ha, shiftup); } else { /* Ivy Bridge's SAD mode doesn't support XOR interleave mode */ idx = (addr >> 6) & 7; @@ -1090,7 +1295,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, if (ch_way == 3) idx = addr >> 6; else - idx = addr >> (6 + sck_way); + idx = (addr >> (6 + sck_way + shiftup)) & 0x3; idx = idx % ch_way; /* @@ -1181,7 +1386,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, if (!IS_RIR_VALID(reg)) continue; - limit = RIR_LIMIT(reg); + limit = pvt->info.rir_limit(reg); mb = div_u64_rem(limit >> 20, 1000, &kb); edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", n_rir, @@ -1197,6 +1402,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, return -EINVAL; } rir_way = RIR_WAY(reg); + if (pvt->is_close_pg) idx = (ch_addr >> 6); else @@ -1259,13 +1465,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev, { struct sbridge_dev *sbridge_dev; const struct pci_id_descr *dev_descr = &table->descr[devno]; - struct pci_dev *pdev = NULL; u8 bus = 0; sbridge_printk(KERN_DEBUG, - "Seeking for: dev %02x.%d PCI ID %04x:%04x\n", - dev_descr->dev, dev_descr->func, + "Seeking for: PCI ID %04x:%04x\n", PCI_VENDOR_ID_INTEL, dev_descr->dev_id); pdev = pci_get_device(PCI_VENDOR_ID_INTEL, @@ -1280,12 +1484,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev, if (dev_descr->optional) return 0; + /* if the HA wasn't found */ if (devno == 0) return -ENODEV; sbridge_printk(KERN_INFO, - "Device not found: dev %02x.%d PCI ID %04x:%04x\n", - dev_descr->dev, dev_descr->func, + "Device not found: %04x:%04x\n", PCI_VENDOR_ID_INTEL, dev_descr->dev_id); /* End of list, leave */ @@ -1305,9 +1509,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, if (sbridge_dev->pdev[devno]) { sbridge_printk(KERN_ERR, - "Duplicated device for " - "dev %02x:%d.%d PCI ID %04x:%04x\n", - bus, dev_descr->dev, dev_descr->func, + "Duplicated device for %04x:%04x\n", PCI_VENDOR_ID_INTEL, dev_descr->dev_id); pci_dev_put(pdev); return -ENODEV; @@ -1315,30 +1517,15 @@ static int sbridge_get_onedevice(struct pci_dev **prev, sbridge_dev->pdev[devno] = pdev; - /* Sanity check */ - if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev || - PCI_FUNC(pdev->devfn) != dev_descr->func)) { - sbridge_printk(KERN_ERR, - "Device PCI ID %04x:%04x " - "has dev %02x:%d.%d instead of dev %02x:%02x.%d\n", - PCI_VENDOR_ID_INTEL, dev_descr->dev_id, - bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - bus, dev_descr->dev, dev_descr->func); - return -ENODEV; - } - /* Be sure that the device is enabled */ if (unlikely(pci_enable_device(pdev) < 0)) { sbridge_printk(KERN_ERR, - "Couldn't enable " - "dev %02x:%d.%d PCI ID %04x:%04x\n", - bus, dev_descr->dev, dev_descr->func, + "Couldn't enable %04x:%04x\n", PCI_VENDOR_ID_INTEL, dev_descr->dev_id); return -ENODEV; } - edac_dbg(0, "Detected dev %02x:%d.%d PCI ID %04x:%04x\n", - bus, dev_descr->dev, dev_descr->func, + edac_dbg(0, "Detected %04x:%04x\n", PCI_VENDOR_ID_INTEL, dev_descr->dev_id); /* @@ -1355,10 +1542,9 @@ static int sbridge_get_onedevice(struct pci_dev **prev, /* * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's - * device/functions we want to reference for this driver. - * Need to 'get' device 16 func 1 and func 2. + * devices we want to reference for this driver. * @num_mc: pointer to the memory controllers count, to be incremented in case - * of success. + * of success. * @table: model specific table * * returns 0 in case of success or error code @@ -1396,79 +1582,51 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, { struct sbridge_pvt *pvt = mci->pvt_info; struct pci_dev *pdev; - int i, func, slot; + int i; for (i = 0; i < sbridge_dev->n_devs; i++) { pdev = sbridge_dev->pdev[i]; if (!pdev) continue; - slot = PCI_SLOT(pdev->devfn); - func = PCI_FUNC(pdev->devfn); - switch (slot) { - case 12: - switch (func) { - case 6: - pvt->pci_sad0 = pdev; - break; - case 7: - pvt->pci_sad1 = pdev; - break; - default: - goto error; - } + + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0: + pvt->pci_sad0 = pdev; break; - case 13: - switch (func) { - case 6: - pvt->pci_br0 = pdev; - break; - default: - goto error; - } + case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1: + pvt->pci_sad1 = pdev; break; - case 14: - switch (func) { - case 0: - pvt->pci_ha0 = pdev; - break; - default: - goto error; - } + case PCI_DEVICE_ID_INTEL_SBRIDGE_BR: + pvt->pci_br0 = pdev; break; - case 15: - switch (func) { - case 0: - pvt->pci_ta = pdev; - break; - case 1: - pvt->pci_ras = pdev; - break; - case 2: - case 3: - case 4: - case 5: - pvt->pci_tad[func - 2] = pdev; - break; - default: - goto error; - } + case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0: + pvt->pci_ha0 = pdev; break; - case 17: - switch (func) { - case 0: - pvt->pci_ddrio = pdev; - break; - default: - goto error; - } + case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA: + pvt->pci_ta = pdev; + break; + case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS: + pvt->pci_ras = pdev; + break; + case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0: + case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1: + case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2: + case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3: + { + int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0; + pvt->pci_tad[id] = pdev; + } + break; + case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO: + pvt->pci_ddrio = pdev; break; default: goto error; } - edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n", + edac_dbg(0, "Associated PCI %02x:%02x, bus %d with dev = %p\n", + pdev->vendor, pdev->device, sbridge_dev->bus, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev); } @@ -1488,9 +1646,8 @@ enodev: return -ENODEV; error: - sbridge_printk(KERN_ERR, "Device %d, function %d " - "is out of the expected range\n", - slot, func); + sbridge_printk(KERN_ERR, "Unexpected device %02x:%02x\n", + PCI_VENDOR_ID_INTEL, pdev->device); return -EINVAL; } @@ -1499,7 +1656,7 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, { struct sbridge_pvt *pvt = mci->pvt_info; struct pci_dev *pdev, *tmp; - int i, func, slot; + int i; bool mode_2ha = false; tmp = pci_get_device(PCI_VENDOR_ID_INTEL, @@ -1513,79 +1670,60 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, pdev = sbridge_dev->pdev[i]; if (!pdev) continue; - slot = PCI_SLOT(pdev->devfn); - func = PCI_FUNC(pdev->devfn); - switch (slot) { - case 14: - if (func == 0) { - pvt->pci_ha0 = pdev; - break; - } - goto error; - case 15: - switch (func) { - case 0: - pvt->pci_ta = pdev; - break; - case 1: - pvt->pci_ras = pdev; - break; - case 4: - case 5: - /* if we have 2 HAs active, channels 2 and 3 - * are in other device */ - if (mode_2ha) - break; - /* fall through */ - case 2: - case 3: - pvt->pci_tad[func - 2] = pdev; + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0: + pvt->pci_ha0 = pdev; + break; + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: + pvt->pci_ta = pdev; + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS: + pvt->pci_ras = pdev; + break; + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3: + /* if we have 2 HAs active, channels 2 and 3 + * are in other device */ + if (mode_2ha) break; - default: - goto error; - } + /* fall through */ + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1: + { + int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0; + pvt->pci_tad[id] = pdev; + } break; - case 17: - if (func == 4) { + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0: + pvt->pci_ddrio = pdev; + break; + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0: + if (!mode_2ha) pvt->pci_ddrio = pdev; - break; - } else if (func == 0) { - if (!mode_2ha) - pvt->pci_ddrio = pdev; - break; - } - goto error; - case 22: - switch (func) { - case 0: - pvt->pci_sad0 = pdev; - break; - case 1: - pvt->pci_br0 = pdev; - break; - case 2: - pvt->pci_br1 = pdev; - break; - default: - goto error; - } break; - case 28: - if (func == 0) { - pvt->pci_ha1 = pdev; - break; - } - goto error; - case 29: + case PCI_DEVICE_ID_INTEL_IBRIDGE_SAD: + pvt->pci_sad0 = pdev; + break; + case PCI_DEVICE_ID_INTEL_IBRIDGE_BR0: + pvt->pci_br0 = pdev; + break; + case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1: + pvt->pci_br1 = pdev; + break; + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1: + pvt->pci_ha1 = pdev; + break; + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0: + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1: + { + int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 2; + /* we shouldn't have this device if we have just one * HA present */ WARN_ON(!mode_2ha); - if (func == 2 || func == 3) { - pvt->pci_tad[func] = pdev; - break; - } - goto error; + pvt->pci_tad[id] = pdev; + } + break; default: goto error; } @@ -1614,11 +1752,111 @@ enodev: error: sbridge_printk(KERN_ERR, - "Device %d, function %d is out of the expected range\n", - slot, func); + "Unexpected device %02x:%02x\n", PCI_VENDOR_ID_INTEL, + pdev->device); return -EINVAL; } +static int haswell_mci_bind_devs(struct mem_ctl_info *mci, + struct sbridge_dev *sbridge_dev) +{ + struct sbridge_pvt *pvt = mci->pvt_info; + struct pci_dev *pdev, *tmp; + int i; + bool mode_2ha = false; + + tmp = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, NULL); + if (tmp) { + mode_2ha = true; + pci_dev_put(tmp); + } + + /* there's only one device per system; not tied to any bus */ + if (pvt->info.pci_vtd == NULL) + /* result will be checked later */ + pvt->info.pci_vtd = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC, + NULL); + + for (i = 0; i < sbridge_dev->n_devs; i++) { + pdev = sbridge_dev->pdev[i]; + if (!pdev) + continue; + + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0: + pvt->pci_sad0 = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1: + pvt->pci_sad1 = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0: + pvt->pci_ha0 = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA: + pvt->pci_ta = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL: + pvt->pci_ras = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0: + pvt->pci_tad[0] = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1: + pvt->pci_tad[1] = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2: + if (!mode_2ha) + pvt->pci_tad[2] = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3: + if (!mode_2ha) + pvt->pci_tad[3] = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0: + pvt->pci_ddrio = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: + pvt->pci_ha1 = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA: + pvt->pci_ha1_ta = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0: + if (mode_2ha) + pvt->pci_tad[2] = pdev; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1: + if (mode_2ha) + pvt->pci_tad[3] = pdev; + break; + default: + break; + } + + edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n", + sbridge_dev->bus, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + pdev); + } + + /* Check if everything were registered */ + if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 || + !pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd) + goto enodev; + + for (i = 0; i < NUM_CHANNELS; i++) { + if (!pvt->pci_tad[i]) + goto enodev; + } + return 0; + +enodev: + sbridge_printk(KERN_ERR, "Some needed devices are missing\n"); + return -ENODEV; +} + /**************************************************************************** Error check routines ****************************************************************************/ @@ -1736,6 +1974,9 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, * EDAC core should be handling the channel mask, in order to point * to the group of dimm's where the error may be happening. */ + if (!pvt->is_lockstep && !pvt->is_mirrored && !pvt->is_close_pg) + channel = first_channel; + snprintf(msg, sizeof(msg), "%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", overflow ? " OVERFLOW" : "", @@ -1865,10 +2106,6 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, "%u APIC %x\n", mce->cpuvendor, mce->cpuid, mce->time, mce->socketid, mce->apicid); - /* Only handle if it is the right mc controller */ - if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc) - return NOTIFY_DONE; - smp_rmb(); if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { smp_wmb(); @@ -1932,7 +2169,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) int rc; /* Check the number of active and not disabled channels */ - rc = check_if_ecc_is_active(sbridge_dev->bus); + rc = check_if_ecc_is_active(sbridge_dev->bus, type); if (unlikely(rc < 0)) return rc; @@ -1971,11 +2208,15 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) mci->edac_check = sbridge_check_error; pvt->info.type = type; - if (type == IVY_BRIDGE) { + switch (type) { + case IVY_BRIDGE: pvt->info.rankcfgr = IB_RANK_CFG_A; pvt->info.get_tolm = ibridge_get_tolm; pvt->info.get_tohm = ibridge_get_tohm; pvt->info.dram_rule = ibridge_dram_rule; + pvt->info.get_memory_type = get_memory_type; + pvt->info.get_node_id = get_node_id; + pvt->info.rir_limit = rir_limit; pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); pvt->info.interleave_list = ibridge_interleave_list; pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); @@ -1986,11 +2227,15 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) rc = ibridge_mci_bind_devs(mci, sbridge_dev); if (unlikely(rc < 0)) goto fail0; - } else { + break; + case SANDY_BRIDGE: pvt->info.rankcfgr = SB_RANK_CFG_A; pvt->info.get_tolm = sbridge_get_tolm; pvt->info.get_tohm = sbridge_get_tohm; pvt->info.dram_rule = sbridge_dram_rule; + pvt->info.get_memory_type = get_memory_type; + pvt->info.get_node_id = get_node_id; + pvt->info.rir_limit = rir_limit; pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule); pvt->info.interleave_list = sbridge_interleave_list; pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); @@ -2001,8 +2246,27 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) rc = sbridge_mci_bind_devs(mci, sbridge_dev); if (unlikely(rc < 0)) goto fail0; - } + break; + case HASWELL: + /* rankcfgr isn't used */ + pvt->info.get_tolm = haswell_get_tolm; + pvt->info.get_tohm = haswell_get_tohm; + pvt->info.dram_rule = ibridge_dram_rule; + pvt->info.get_memory_type = haswell_get_memory_type; + pvt->info.get_node_id = haswell_get_node_id; + pvt->info.rir_limit = haswell_rir_limit; + pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); + pvt->info.interleave_list = ibridge_interleave_list; + pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); + pvt->info.interleave_pkg = ibridge_interleave_pkg; + mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx); + /* Store pci devices at mci for faster access */ + rc = haswell_mci_bind_devs(mci, sbridge_dev); + if (unlikely(rc < 0)) + goto fail0; + break; + } /* Get dimm basic config and the memory layout */ get_dimm_config(mci); @@ -2037,10 +2301,10 @@ fail0: static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int rc; + int rc = -ENODEV; u8 mc, num_mc = 0; struct sbridge_dev *sbridge_dev; - enum type type; + enum type type = SANDY_BRIDGE; /* get the pci devices we want to reserve for our use */ mutex_lock(&sbridge_edac_lock); @@ -2054,12 +2318,19 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) } probed++; - if (pdev->device == PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA) { + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table); type = IVY_BRIDGE; - } else { + break; + case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA: rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table); type = SANDY_BRIDGE; + break; + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0: + rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table); + type = HASWELL; + break; } if (unlikely(rc < 0)) goto fail0; @@ -2068,6 +2339,7 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { edac_dbg(0, "Registering MC#%d (%d of %d)\n", mc, mc + 1, num_mc); + sbridge_dev->mc = mc++; rc = sbridge_register_mci(sbridge_dev, type); if (unlikely(rc < 0)) diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 44074fbcf7ff..f19682a93c24 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -51,7 +51,7 @@ static struct drm_driver driver; .subdevice = PCI_ANY_ID, \ .driver_data = (unsigned long) info } -static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { +static const struct pci_device_id pciidlist[] = { AST_VGA_DEVICE(PCI_CHIP_AST2000, NULL), AST_VGA_DEVICE(PCI_CHIP_AST2100, NULL), /* AST_VGA_DEVICE(PCI_CHIP_AST1180, NULL), - don't bind to 1180 for now */ diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index f5e0ead974a6..9738e9b14708 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -177,7 +177,7 @@ static void bochs_pci_remove(struct pci_dev *pdev) drm_put_dev(dev); } -static DEFINE_PCI_DEVICE_TABLE(bochs_pci_tbl) = { +static const struct pci_device_id bochs_pci_tbl[] = { { .vendor = 0x1234, .device = 0x1111, diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 4516b052cc67..919c73b94447 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -29,7 +29,7 @@ module_param_named(modeset, cirrus_modeset, int, 0400); static struct drm_driver driver; /* only bind to the cirrus chip in qemu */ -static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { +static const struct pci_device_id pciidlist[] = { { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0, 0, 0 }, {0,} diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index e6f5c620a0a2..54f73f50571a 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -674,7 +674,7 @@ failed_connector: kfree(gma_encoder); } -static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = { +static const struct pci_device_id hdmi_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) }, { 0 } }; diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 6e8fe9ec02b5..eec993f93b1a 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -54,7 +54,7 @@ static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); * PowerVR SGX545 - Cedartrail - Intel GMA 3650, Intel Atom D2550, D2700, * N2800 */ -static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { +static const struct pci_device_id pciidlist[] = { { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, #if defined(CONFIG_DRM_GMA600) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index f15ea3c4a90a..2d75d6df0789 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -28,7 +28,7 @@ module_param_named(modeset, mgag200_modeset, int, 0400); static struct drm_driver driver; -static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { +static const struct pci_device_id pciidlist[] = { { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A }, { PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B }, { PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV }, diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 6e936634d65c..a3fd92029a14 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -38,7 +38,7 @@ #include "qxl_object.h" extern int qxl_max_ioctls; -static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { +static const struct pci_device_id pciidlist[] = { { 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0 }, { 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_OTHER << 8, diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 3e388ec31da8..f0db7eca9023 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1416,6 +1416,7 @@ static void wacom_remove(struct hid_device *hdev) kfree(wacom); } +#ifdef CONFIG_PM static int wacom_resume(struct hid_device *hdev) { struct wacom *wacom = hid_get_drvdata(hdev); @@ -1436,6 +1437,7 @@ static int wacom_reset_resume(struct hid_device *hdev) { return wacom_resume(hdev); } +#endif /* CONFIG_PM */ static struct hid_driver wacom_driver = { .name = "wacom", diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4d140bbbe100..9b7ee7e427df 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -89,6 +89,7 @@ struct idle_cpu { * Indicate which enable bits to clear here. */ unsigned long auto_demotion_disable_flags; + bool byt_auto_demotion_disable_flag; bool disable_promotion_to_c1e; }; @@ -442,6 +443,66 @@ static struct cpuidle_state hsw_cstates[] = { { .enter = NULL } }; +static struct cpuidle_state bdw_cstates[] = { + { + .name = "C1-BDW", + .desc = "MWAIT 0x00", + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 2, + .target_residency = 2, + .enter = &intel_idle }, + { + .name = "C1E-BDW", + .desc = "MWAIT 0x01", + .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 10, + .target_residency = 20, + .enter = &intel_idle }, + { + .name = "C3-BDW", + .desc = "MWAIT 0x10", + .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 40, + .target_residency = 100, + .enter = &intel_idle }, + { + .name = "C6-BDW", + .desc = "MWAIT 0x20", + .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 133, + .target_residency = 400, + .enter = &intel_idle }, + { + .name = "C7s-BDW", + .desc = "MWAIT 0x32", + .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 166, + .target_residency = 500, + .enter = &intel_idle }, + { + .name = "C8-BDW", + .desc = "MWAIT 0x40", + .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 300, + .target_residency = 900, + .enter = &intel_idle }, + { + .name = "C9-BDW", + .desc = "MWAIT 0x50", + .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 600, + .target_residency = 1800, + .enter = &intel_idle }, + { + .name = "C10-BDW", + .desc = "MWAIT 0x60", + .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 2600, + .target_residency = 7700, + .enter = &intel_idle }, + { + .enter = NULL } +}; static struct cpuidle_state atom_cstates[] = { { @@ -613,6 +674,7 @@ static const struct idle_cpu idle_cpu_snb = { static const struct idle_cpu idle_cpu_byt = { .state_table = byt_cstates, .disable_promotion_to_c1e = true, + .byt_auto_demotion_disable_flag = true, }; static const struct idle_cpu idle_cpu_ivb = { @@ -630,6 +692,11 @@ static const struct idle_cpu idle_cpu_hsw = { .disable_promotion_to_c1e = true, }; +static const struct idle_cpu idle_cpu_bdw = { + .state_table = bdw_cstates, + .disable_promotion_to_c1e = true, +}; + static const struct idle_cpu idle_cpu_avn = { .state_table = avn_cstates, .disable_promotion_to_c1e = true, @@ -658,7 +725,10 @@ static const struct x86_cpu_id intel_idle_ids[] = { ICPU(0x3f, idle_cpu_hsw), ICPU(0x45, idle_cpu_hsw), ICPU(0x46, idle_cpu_hsw), - ICPU(0x4D, idle_cpu_avn), + ICPU(0x4d, idle_cpu_avn), + ICPU(0x3d, idle_cpu_bdw), + ICPU(0x4f, idle_cpu_bdw), + ICPU(0x56, idle_cpu_bdw), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); @@ -814,6 +884,11 @@ static int __init intel_idle_cpuidle_driver_init(void) if (icpu->auto_demotion_disable_flags) on_each_cpu(auto_demotion_disable, NULL, 1); + if (icpu->byt_auto_demotion_disable_flag) { + wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0); + wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0); + } + if (icpu->disable_promotion_to_c1e) /* each-cpu is redundant */ on_each_cpu(c1e_promotion_disable, NULL, 1); diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 8d3c78ddc906..729da39c49ed 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -1222,7 +1222,7 @@ static int qib_init_one(struct pci_dev *, const struct pci_device_id *); #define DRIVER_LOAD_MSG "Intel " QIB_DRV_NAME " loaded: " #define PFX QIB_DRV_NAME ": " -static DEFINE_PCI_DEVICE_TABLE(qib_pci_tbl) = { +static const struct pci_device_id qib_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_QLOGIC_IB_6120) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7220) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7322) }, diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c index fb6d026f92cd..0d0f98695d53 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_main.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c @@ -490,7 +490,7 @@ out: /* Start of PCI section */ -static DEFINE_PCI_DEVICE_TABLE(usnic_ib_pci_ids) = { +static const struct pci_device_id usnic_ib_pci_ids[] = { {PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)}, {0,} }; diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index d398f1321f14..c30204f2fa30 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -237,6 +237,31 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) EXPORT_SYMBOL(input_mt_report_pointer_emulation); /** + * input_mt_drop_unused() - Inactivate slots not seen in this frame + * @dev: input device with allocated MT slots + * + * Lift all slots not seen since the last call to this function. + */ +void input_mt_drop_unused(struct input_dev *dev) +{ + struct input_mt *mt = dev->mt; + int i; + + if (!mt) + return; + + for (i = 0; i < mt->num_slots; i++) { + if (!input_mt_is_used(mt, &mt->slots[i])) { + input_mt_slot(dev, i); + input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); + } + } + + mt->frame++; +} +EXPORT_SYMBOL(input_mt_drop_unused); + +/** * input_mt_sync_frame() - synchronize mt frame * @dev: input device with allocated MT slots * @@ -247,27 +272,18 @@ EXPORT_SYMBOL(input_mt_report_pointer_emulation); void input_mt_sync_frame(struct input_dev *dev) { struct input_mt *mt = dev->mt; - struct input_mt_slot *s; bool use_count = false; if (!mt) return; - if (mt->flags & INPUT_MT_DROP_UNUSED) { - for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { - if (input_mt_is_used(mt, s)) - continue; - input_mt_slot(dev, s - mt->slots); - input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); - } - } + if (mt->flags & INPUT_MT_DROP_UNUSED) + input_mt_drop_unused(dev); if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT)) use_count = true; input_mt_report_pointer_emulation(dev, use_count); - - mt->frame++; } EXPORT_SYMBOL(input_mt_sync_frame); diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 9135606c8649..ab0fdcd36e18 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -158,7 +158,7 @@ static unsigned int get_time_pit(void) #define GET_TIME(x) rdtscl(x) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "TSC" -#elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_TILE) +#elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_TILE) #define GET_TIME(x) do { x = get_cycles(); } while (0) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "get_cycles" diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 603fe0dd3682..177602cf7079 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -95,7 +95,8 @@ #define XTYPE_XBOX 0 #define XTYPE_XBOX360 1 #define XTYPE_XBOX360W 2 -#define XTYPE_UNKNOWN 3 +#define XTYPE_XBOXONE 3 +#define XTYPE_UNKNOWN 4 static bool dpad_to_buttons; module_param(dpad_to_buttons, bool, S_IRUGO); @@ -121,6 +122,7 @@ static const struct xpad_device { { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, + { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, @@ -231,10 +233,12 @@ static const signed short xpad_abs_triggers[] = { -1 }; -/* Xbox 360 has a vendor-specific class, so we cannot match it with only +/* + * Xbox 360 has a vendor-specific class, so we cannot match it with only * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we * match against vendor id as well. Wired Xbox 360 devices have protocol 1, - * wireless controllers have protocol 129. */ + * wireless controllers have protocol 129. + */ #define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ .idVendor = (vend), \ @@ -245,9 +249,20 @@ static const signed short xpad_abs_triggers[] = { { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } +/* The Xbox One controller uses subclass 71 and protocol 208. */ +#define XPAD_XBOXONE_VENDOR_PROTOCOL(vend, pr) \ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ + .idVendor = (vend), \ + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ + .bInterfaceSubClass = 71, \ + .bInterfaceProtocol = (pr) +#define XPAD_XBOXONE_VENDOR(vend) \ + { XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) } + static struct usb_device_id xpad_table[] = { { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ + XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */ XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ @@ -278,12 +293,10 @@ struct usb_xpad { struct urb *bulk_out; unsigned char *bdata; -#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS) struct urb *irq_out; /* urb for interrupt out report */ unsigned char *odata; /* output data */ dma_addr_t odata_dma; struct mutex odata_mutex; -#endif #if defined(CONFIG_JOYSTICK_XPAD_LEDS) struct xpad_led *led; @@ -470,6 +483,105 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha xpad360_process_packet(xpad, cmd, &data[4]); } +/* + * xpadone_process_buttons + * + * Process a button update packet from an Xbox one controller. + */ +static void xpadone_process_buttons(struct usb_xpad *xpad, + struct input_dev *dev, + unsigned char *data) +{ + /* menu/view buttons */ + input_report_key(dev, BTN_START, data[4] & 0x04); + input_report_key(dev, BTN_SELECT, data[4] & 0x08); + + /* buttons A,B,X,Y */ + input_report_key(dev, BTN_A, data[4] & 0x10); + input_report_key(dev, BTN_B, data[4] & 0x20); + input_report_key(dev, BTN_X, data[4] & 0x40); + input_report_key(dev, BTN_Y, data[4] & 0x80); + + /* digital pad */ + if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { + /* dpad as buttons (left, right, up, down) */ + input_report_key(dev, BTN_TRIGGER_HAPPY1, data[5] & 0x04); + input_report_key(dev, BTN_TRIGGER_HAPPY2, data[5] & 0x08); + input_report_key(dev, BTN_TRIGGER_HAPPY3, data[5] & 0x01); + input_report_key(dev, BTN_TRIGGER_HAPPY4, data[5] & 0x02); + } else { + input_report_abs(dev, ABS_HAT0X, + !!(data[5] & 0x08) - !!(data[5] & 0x04)); + input_report_abs(dev, ABS_HAT0Y, + !!(data[5] & 0x02) - !!(data[5] & 0x01)); + } + + /* TL/TR */ + input_report_key(dev, BTN_TL, data[5] & 0x10); + input_report_key(dev, BTN_TR, data[5] & 0x20); + + /* stick press left/right */ + input_report_key(dev, BTN_THUMBL, data[5] & 0x40); + input_report_key(dev, BTN_THUMBR, data[5] & 0x80); + + if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { + /* left stick */ + input_report_abs(dev, ABS_X, + (__s16) le16_to_cpup((__le16 *)(data + 10))); + input_report_abs(dev, ABS_Y, + ~(__s16) le16_to_cpup((__le16 *)(data + 12))); + + /* right stick */ + input_report_abs(dev, ABS_RX, + (__s16) le16_to_cpup((__le16 *)(data + 14))); + input_report_abs(dev, ABS_RY, + ~(__s16) le16_to_cpup((__le16 *)(data + 16))); + } + + /* triggers left/right */ + if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { + input_report_key(dev, BTN_TL2, + (__u16) le16_to_cpup((__le16 *)(data + 6))); + input_report_key(dev, BTN_TR2, + (__u16) le16_to_cpup((__le16 *)(data + 8))); + } else { + input_report_abs(dev, ABS_Z, + (__u16) le16_to_cpup((__le16 *)(data + 6))); + input_report_abs(dev, ABS_RZ, + (__u16) le16_to_cpup((__le16 *)(data + 8))); + } + + input_sync(dev); +} + +/* + * xpadone_process_packet + * + * Completes a request by converting the data into events for the + * input subsystem. This version is for the Xbox One controller. + * + * The report format was gleaned from + * https://github.com/kylelemons/xbox/blob/master/xbox.go + */ + +static void xpadone_process_packet(struct usb_xpad *xpad, + u16 cmd, unsigned char *data) +{ + struct input_dev *dev = xpad->dev; + + switch (data[0]) { + case 0x20: + xpadone_process_buttons(xpad, dev, data); + break; + + case 0x07: + /* the xbox button has its own special report */ + input_report_key(dev, BTN_MODE, data[4] & 0x01); + input_sync(dev); + break; + } +} + static void xpad_irq_in(struct urb *urb) { struct usb_xpad *xpad = urb->context; @@ -502,6 +614,9 @@ static void xpad_irq_in(struct urb *urb) case XTYPE_XBOX360W: xpad360w_process_packet(xpad, 0, xpad->idata); break; + case XTYPE_XBOXONE: + xpadone_process_packet(xpad, 0, xpad->idata); + break; default: xpad_process_packet(xpad, 0, xpad->idata); } @@ -535,7 +650,6 @@ static void xpad_bulk_out(struct urb *urb) } } -#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS) static void xpad_irq_out(struct urb *urb) { struct usb_xpad *xpad = urb->context; @@ -573,6 +687,7 @@ exit: static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) { struct usb_endpoint_descriptor *ep_irq_out; + int ep_irq_out_idx; int error; if (xpad->xtype == XTYPE_UNKNOWN) @@ -593,7 +708,10 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) goto fail2; } - ep_irq_out = &intf->cur_altsetting->endpoint[1].desc; + /* Xbox One controller has in/out endpoints swapped. */ + ep_irq_out_idx = xpad->xtype == XTYPE_XBOXONE ? 0 : 1; + ep_irq_out = &intf->cur_altsetting->endpoint[ep_irq_out_idx].desc; + usb_fill_int_urb(xpad->irq_out, xpad->udev, usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress), xpad->odata, XPAD_PKT_LEN, @@ -621,11 +739,6 @@ static void xpad_deinit_output(struct usb_xpad *xpad) xpad->odata, xpad->odata_dma); } } -#else -static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; } -static void xpad_deinit_output(struct usb_xpad *xpad) {} -static void xpad_stop_output(struct usb_xpad *xpad) {} -#endif #ifdef CONFIG_JOYSTICK_XPAD_FF static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) @@ -692,7 +805,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect static int xpad_init_ff(struct usb_xpad *xpad) { - if (xpad->xtype == XTYPE_UNKNOWN) + if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE) return 0; input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); @@ -801,6 +914,14 @@ static int xpad_open(struct input_dev *dev) if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) return -EIO; + if (xpad->xtype == XTYPE_XBOXONE) { + /* Xbox one controller needs to be initialized. */ + xpad->odata[0] = 0x05; + xpad->odata[1] = 0x20; + xpad->irq_out->transfer_buffer_length = 2; + return usb_submit_urb(xpad->irq_out, GFP_KERNEL); + } + return 0; } @@ -816,6 +937,7 @@ static void xpad_close(struct input_dev *dev) static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) { + struct usb_xpad *xpad = input_get_drvdata(input_dev); set_bit(abs, input_dev->absbit); switch (abs) { @@ -827,7 +949,10 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) break; case ABS_Z: case ABS_RZ: /* the triggers (if mapped to axes) */ - input_set_abs_params(input_dev, abs, 0, 255, 0, 0); + if (xpad->xtype == XTYPE_XBOXONE) + input_set_abs_params(input_dev, abs, 0, 1023, 0, 0); + else + input_set_abs_params(input_dev, abs, 0, 255, 0, 0); break; case ABS_HAT0X: case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */ @@ -842,6 +967,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id struct usb_xpad *xpad; struct input_dev *input_dev; struct usb_endpoint_descriptor *ep_irq_in; + int ep_irq_in_idx; int i, error; for (i = 0; xpad_device[i].idVendor; i++) { @@ -850,6 +976,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id break; } + if (xpad_device[i].xtype == XTYPE_XBOXONE && + intf->cur_altsetting->desc.bInterfaceNumber != 0) { + /* + * The Xbox One controller lists three interfaces all with the + * same interface class, subclass and protocol. Differentiate by + * interface number. + */ + return -ENODEV; + } + xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); input_dev = input_allocate_device(); if (!xpad || !input_dev) { @@ -920,7 +1056,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id __set_bit(xpad_common_btn[i], input_dev->keybit); /* set up model-specific ones */ - if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) { + if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W || + xpad->xtype == XTYPE_XBOXONE) { for (i = 0; xpad360_btn[i] >= 0; i++) __set_bit(xpad360_btn[i], input_dev->keybit); } else { @@ -933,7 +1070,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id __set_bit(xpad_btn_pad[i], input_dev->keybit); } else { for (i = 0; xpad_abs_pad[i] >= 0; i++) - xpad_set_up_abs(input_dev, xpad_abs_pad[i]); + xpad_set_up_abs(input_dev, xpad_abs_pad[i]); } if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { @@ -956,7 +1093,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id if (error) goto fail5; - ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; + /* Xbox One controller has in/out endpoints swapped. */ + ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0; + ep_irq_in = &intf->cur_altsetting->endpoint[ep_irq_in_idx].desc; + usb_fill_int_urb(xpad->irq_in, udev, usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), xpad->idata, XPAD_PKT_LEN, xpad_irq_in, diff --git a/drivers/input/keyboard/cap1106.c b/drivers/input/keyboard/cap1106.c index f7d7a0d4ab4e..180b184ab90f 100644 --- a/drivers/input/keyboard/cap1106.c +++ b/drivers/input/keyboard/cap1106.c @@ -64,7 +64,7 @@ struct cap1106_priv { struct input_dev *idev; /* config */ - unsigned int keycodes[CAP1106_NUM_CHN]; + unsigned short keycodes[CAP1106_NUM_CHN]; }; static const struct reg_default cap1106_reg_defaults[] = { @@ -272,6 +272,12 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client, for (i = 0; i < CAP1106_NUM_CHN; i++) __set_bit(priv->keycodes[i], priv->idev->keybit); + __clear_bit(KEY_RESERVED, priv->idev->keybit); + + priv->idev->keycode = priv->keycodes; + priv->idev->keycodesize = sizeof(priv->keycodes[0]); + priv->idev->keycodemax = ARRAY_SIZE(priv->keycodes); + priv->idev->id.vendor = CAP1106_MANUFACTURER_ID; priv->idev->id.product = CAP1106_PRODUCT_ID; priv->idev->id.version = rev; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index ef9e0b8a9aa7..e8573c68f77e 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -117,6 +117,9 @@ void synaptics_reset(struct psmouse *psmouse) } #ifdef CONFIG_MOUSE_PS2_SYNAPTICS + +static bool cr48_profile_sensor; + struct min_max_quirk { const char * const *pnp_ids; int x_min, x_max, y_min, y_max; @@ -1152,6 +1155,42 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse, priv->agm_pending = false; } +static void synaptics_profile_sensor_process(struct psmouse *psmouse, + struct synaptics_hw_state *sgm, + int num_fingers) +{ + struct input_dev *dev = psmouse->dev; + struct synaptics_data *priv = psmouse->private; + struct synaptics_hw_state *hw[2] = { sgm, &priv->agm }; + struct input_mt_pos pos[2]; + int slot[2], nsemi, i; + + nsemi = clamp_val(num_fingers, 0, 2); + + for (i = 0; i < nsemi; i++) { + pos[i].x = hw[i]->x; + pos[i].y = synaptics_invert_y(hw[i]->y); + } + + input_mt_assign_slots(dev, slot, pos, nsemi); + + for (i = 0; i < nsemi; i++) { + input_mt_slot(dev, slot[i]); + input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); + input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x); + input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y); + input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z); + } + + input_mt_drop_unused(dev); + input_mt_report_pointer_emulation(dev, false); + input_mt_report_finger_count(dev, num_fingers); + + synaptics_report_buttons(psmouse, sgm); + + input_sync(dev); +} + /* * called for each full received packet from the touchpad */ @@ -1215,6 +1254,11 @@ static void synaptics_process_packet(struct psmouse *psmouse) finger_width = 0; } + if (cr48_profile_sensor) { + synaptics_profile_sensor_process(psmouse, &hw, num_fingers); + return; + } + if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) synaptics_report_semi_mt_data(dev, &hw, &priv->agm, num_fingers); @@ -1360,6 +1404,9 @@ static void set_input_params(struct psmouse *psmouse, set_abs_position_params(dev, priv, ABS_X, ABS_Y); input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); + if (cr48_profile_sensor) + input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); + if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { set_abs_position_params(dev, priv, ABS_MT_POSITION_X, ABS_MT_POSITION_Y); @@ -1371,11 +1418,16 @@ static void set_input_params(struct psmouse *psmouse, __set_bit(BTN_TOOL_QUADTAP, dev->keybit); __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { - /* Non-image sensors with AGM use semi-mt */ - __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); - input_mt_init_slots(dev, 2, 0); set_abs_position_params(dev, priv, ABS_MT_POSITION_X, ABS_MT_POSITION_Y); + /* + * Profile sensor in CR-48 tracks contacts reasonably well, + * other non-image sensors with AGM use semi-mt. + */ + input_mt_init_slots(dev, 2, + INPUT_MT_POINTER | + (cr48_profile_sensor ? + INPUT_MT_TRACK : INPUT_MT_SEMI_MT)); } if (SYN_CAP_PALMDETECT(priv->capabilities)) @@ -1577,10 +1629,24 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = { { } }; +static const struct dmi_system_id __initconst cr48_dmi_table[] = { +#if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + /* Cr-48 Chromebook (Codename Mario) */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "IEC"), + DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), + }, + }, +#endif + { } +}; + void __init synaptics_module_init(void) { impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); broken_olpc_ec = dmi_check_system(olpc_dmi_table); + cr48_profile_sensor = dmi_check_system(cr48_dmi_table); } static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 03b85711cb70..db178ed2b47e 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -359,7 +359,6 @@ static int mxt_bootloader_read(struct mxt_data *data, msg.buf = val; ret = i2c_transfer(data->client->adapter, &msg, 1); - if (ret == 1) { ret = 0; } else { @@ -414,6 +413,7 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) case 0x5b: bootloader = appmode - 0x26; break; + default: dev_err(&data->client->dev, "Appmode i2c address 0x%02x not found\n", @@ -425,20 +425,20 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) return 0; } -static int mxt_probe_bootloader(struct mxt_data *data, bool retry) +static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address) { struct device *dev = &data->client->dev; - int ret; + int error; u8 val; bool crc_failure; - ret = mxt_lookup_bootloader_address(data, retry); - if (ret) - return ret; + error = mxt_lookup_bootloader_address(data, alt_address); + if (error) + return error; - ret = mxt_bootloader_read(data, &val, 1); - if (ret) - return ret; + error = mxt_bootloader_read(data, &val, 1); + if (error) + return error; /* Check app crc fail mode */ crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL; @@ -1064,6 +1064,137 @@ static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off) return crc; } +static int mxt_prepare_cfg_mem(struct mxt_data *data, + const struct firmware *cfg, + unsigned int data_pos, + unsigned int cfg_start_ofs, + u8 *config_mem, + size_t config_mem_size) +{ + struct device *dev = &data->client->dev; + struct mxt_object *object; + unsigned int type, instance, size, byte_offset; + int offset; + int ret; + int i; + u16 reg; + u8 val; + + while (data_pos < cfg->size) { + /* Read type, instance, length */ + ret = sscanf(cfg->data + data_pos, "%x %x %x%n", + &type, &instance, &size, &offset); + if (ret == 0) { + /* EOF */ + break; + } else if (ret != 3) { + dev_err(dev, "Bad format: failed to parse object\n"); + return -EINVAL; + } + data_pos += offset; + + object = mxt_get_object(data, type); + if (!object) { + /* Skip object */ + for (i = 0; i < size; i++) { + ret = sscanf(cfg->data + data_pos, "%hhx%n", + &val, &offset); + if (ret != 1) { + dev_err(dev, "Bad format in T%d at %d\n", + type, i); + return -EINVAL; + } + data_pos += offset; + } + continue; + } + + if (size > mxt_obj_size(object)) { + /* + * Either we are in fallback mode due to wrong + * config or config from a later fw version, + * or the file is corrupt or hand-edited. + */ + dev_warn(dev, "Discarding %zu byte(s) in T%u\n", + size - mxt_obj_size(object), type); + } else if (mxt_obj_size(object) > size) { + /* + * If firmware is upgraded, new bytes may be added to + * end of objects. It is generally forward compatible + * to zero these bytes - previous behaviour will be + * retained. However this does invalidate the CRC and + * will force fallback mode until the configuration is + * updated. We warn here but do nothing else - the + * malloc has zeroed the entire configuration. + */ + dev_warn(dev, "Zeroing %zu byte(s) in T%d\n", + mxt_obj_size(object) - size, type); + } + + if (instance >= mxt_obj_instances(object)) { + dev_err(dev, "Object instances exceeded!\n"); + return -EINVAL; + } + + reg = object->start_address + mxt_obj_size(object) * instance; + + for (i = 0; i < size; i++) { + ret = sscanf(cfg->data + data_pos, "%hhx%n", + &val, + &offset); + if (ret != 1) { + dev_err(dev, "Bad format in T%d at %d\n", + type, i); + return -EINVAL; + } + data_pos += offset; + + if (i > mxt_obj_size(object)) + continue; + + byte_offset = reg + i - cfg_start_ofs; + + if (byte_offset >= 0 && byte_offset < config_mem_size) { + *(config_mem + byte_offset) = val; + } else { + dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n", + reg, object->type, byte_offset); + return -EINVAL; + } + } + } + + return 0; +} + +static int mxt_upload_cfg_mem(struct mxt_data *data, unsigned int cfg_start, + u8 *config_mem, size_t config_mem_size) +{ + unsigned int byte_offset = 0; + int error; + + /* Write configuration as blocks */ + while (byte_offset < config_mem_size) { + unsigned int size = config_mem_size - byte_offset; + + if (size > MXT_MAX_BLOCK_WRITE) + size = MXT_MAX_BLOCK_WRITE; + + error = __mxt_write_reg(data->client, + cfg_start + byte_offset, + size, config_mem + byte_offset); + if (error) { + dev_err(&data->client->dev, + "Config write error, ret=%d\n", error); + return error; + } + + byte_offset += size; + } + + return 0; +} + /* * mxt_update_cfg - download configuration to chip * @@ -1087,26 +1218,20 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) { struct device *dev = &data->client->dev; struct mxt_info cfg_info; - struct mxt_object *object; int ret; int offset; int data_pos; - int byte_offset; int i; int cfg_start_ofs; u32 info_crc, config_crc, calculated_crc; u8 *config_mem; size_t config_mem_size; - unsigned int type, instance, size; - u8 val; - u16 reg; mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1); if (strncmp(cfg->data, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) { dev_err(dev, "Unrecognised config file\n"); - ret = -EINVAL; - goto release; + return -EINVAL; } data_pos = strlen(MXT_CFG_MAGIC); @@ -1118,8 +1243,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) &offset); if (ret != 1) { dev_err(dev, "Bad format\n"); - ret = -EINVAL; - goto release; + return -EINVAL; } data_pos += offset; @@ -1127,30 +1251,26 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) if (cfg_info.family_id != data->info.family_id) { dev_err(dev, "Family ID mismatch!\n"); - ret = -EINVAL; - goto release; + return -EINVAL; } if (cfg_info.variant_id != data->info.variant_id) { dev_err(dev, "Variant ID mismatch!\n"); - ret = -EINVAL; - goto release; + return -EINVAL; } /* Read CRCs */ ret = sscanf(cfg->data + data_pos, "%x%n", &info_crc, &offset); if (ret != 1) { dev_err(dev, "Bad format: failed to parse Info CRC\n"); - ret = -EINVAL; - goto release; + return -EINVAL; } data_pos += offset; ret = sscanf(cfg->data + data_pos, "%x%n", &config_crc, &offset); if (ret != 1) { dev_err(dev, "Bad format: failed to parse Config CRC\n"); - ret = -EINVAL; - goto release; + return -EINVAL; } data_pos += offset; @@ -1166,8 +1286,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) } else if (config_crc == data->config_crc) { dev_dbg(dev, "Config CRC 0x%06X: OK\n", data->config_crc); - ret = 0; - goto release; + return 0; } else { dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n", data->config_crc, config_crc); @@ -1186,93 +1305,13 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) config_mem = kzalloc(config_mem_size, GFP_KERNEL); if (!config_mem) { dev_err(dev, "Failed to allocate memory\n"); - ret = -ENOMEM; - goto release; + return -ENOMEM; } - while (data_pos < cfg->size) { - /* Read type, instance, length */ - ret = sscanf(cfg->data + data_pos, "%x %x %x%n", - &type, &instance, &size, &offset); - if (ret == 0) { - /* EOF */ - break; - } else if (ret != 3) { - dev_err(dev, "Bad format: failed to parse object\n"); - ret = -EINVAL; - goto release_mem; - } - data_pos += offset; - - object = mxt_get_object(data, type); - if (!object) { - /* Skip object */ - for (i = 0; i < size; i++) { - ret = sscanf(cfg->data + data_pos, "%hhx%n", - &val, - &offset); - data_pos += offset; - } - continue; - } - - if (size > mxt_obj_size(object)) { - /* - * Either we are in fallback mode due to wrong - * config or config from a later fw version, - * or the file is corrupt or hand-edited. - */ - dev_warn(dev, "Discarding %zu byte(s) in T%u\n", - size - mxt_obj_size(object), type); - } else if (mxt_obj_size(object) > size) { - /* - * If firmware is upgraded, new bytes may be added to - * end of objects. It is generally forward compatible - * to zero these bytes - previous behaviour will be - * retained. However this does invalidate the CRC and - * will force fallback mode until the configuration is - * updated. We warn here but do nothing else - the - * malloc has zeroed the entire configuration. - */ - dev_warn(dev, "Zeroing %zu byte(s) in T%d\n", - mxt_obj_size(object) - size, type); - } - - if (instance >= mxt_obj_instances(object)) { - dev_err(dev, "Object instances exceeded!\n"); - ret = -EINVAL; - goto release_mem; - } - - reg = object->start_address + mxt_obj_size(object) * instance; - - for (i = 0; i < size; i++) { - ret = sscanf(cfg->data + data_pos, "%hhx%n", - &val, - &offset); - if (ret != 1) { - dev_err(dev, "Bad format in T%d\n", type); - ret = -EINVAL; - goto release_mem; - } - data_pos += offset; - - if (i > mxt_obj_size(object)) - continue; - - byte_offset = reg + i - cfg_start_ofs; - - if ((byte_offset >= 0) - && (byte_offset <= config_mem_size)) { - *(config_mem + byte_offset) = val; - } else { - dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n", - reg, object->type, byte_offset); - ret = -EINVAL; - goto release_mem; - } - } - } + ret = mxt_prepare_cfg_mem(data, cfg, data_pos, cfg_start_ofs, + config_mem, config_mem_size); + if (ret) + goto release_mem; /* Calculate crc of the received configs (not the raw config file) */ if (data->T7_address < cfg_start_ofs) { @@ -1286,28 +1325,14 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) data->T7_address - cfg_start_ofs, config_mem_size); - if (config_crc > 0 && (config_crc != calculated_crc)) + if (config_crc > 0 && config_crc != calculated_crc) dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n", calculated_crc, config_crc); - /* Write configuration as blocks */ - byte_offset = 0; - while (byte_offset < config_mem_size) { - size = config_mem_size - byte_offset; - - if (size > MXT_MAX_BLOCK_WRITE) - size = MXT_MAX_BLOCK_WRITE; - - ret = __mxt_write_reg(data->client, - cfg_start_ofs + byte_offset, - size, config_mem + byte_offset); - if (ret != 0) { - dev_err(dev, "Config write error, ret=%d\n", ret); - goto release_mem; - } - - byte_offset += size; - } + ret = mxt_upload_cfg_mem(data, cfg_start_ofs, + config_mem, config_mem_size); + if (ret) + goto release_mem; mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE); @@ -1319,8 +1344,6 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) release_mem: kfree(config_mem); -release: - release_firmware(cfg); return ret; } @@ -1422,10 +1445,12 @@ static int mxt_get_object_table(struct mxt_data *data) switch (object->type) { case MXT_GEN_MESSAGE_T5: - if (data->info.family_id == 0x80) { + if (data->info.family_id == 0x80 && + data->info.version < 0x20) { /* - * On mXT224 read and discard unused CRC byte - * otherwise DMA reads are misaligned + * On mXT224 firmware versions prior to V2.0 + * read and discard unused CRC byte otherwise + * DMA reads are misaligned. */ data->T5_msg_size = mxt_obj_size(object); } else { @@ -1433,6 +1458,7 @@ static int mxt_get_object_table(struct mxt_data *data) data->T5_msg_size = mxt_obj_size(object) - 1; } data->T5_address = object->start_address; + break; case MXT_GEN_COMMAND_T6: data->T6_reportid = min_id; data->T6_address = object->start_address; @@ -1638,46 +1664,45 @@ static int mxt_configure_objects(struct mxt_data *data, static void mxt_config_cb(const struct firmware *cfg, void *ctx) { mxt_configure_objects(ctx, cfg); + release_firmware(cfg); } static int mxt_initialize(struct mxt_data *data) { struct i2c_client *client = data->client; + int recovery_attempts = 0; int error; - bool alt_bootloader_addr = false; - bool retry = false; -retry_info: - error = mxt_get_info(data); - if (error) { -retry_bootloader: - error = mxt_probe_bootloader(data, alt_bootloader_addr); + while (1) { + error = mxt_get_info(data); + if (!error) + break; + + /* Check bootloader state */ + error = mxt_probe_bootloader(data, false); if (error) { - if (alt_bootloader_addr) { + dev_info(&client->dev, "Trying alternate bootloader address\n"); + error = mxt_probe_bootloader(data, true); + if (error) { /* Chip is not in appmode or bootloader mode */ return error; } + } - dev_info(&client->dev, "Trying alternate bootloader address\n"); - alt_bootloader_addr = true; - goto retry_bootloader; - } else { - if (retry) { - dev_err(&client->dev, "Could not recover from bootloader mode\n"); - /* - * We can reflash from this state, so do not - * abort init - */ - data->in_bootloader = true; - return 0; - } - - /* Attempt to exit bootloader into app mode */ - mxt_send_bootloader_cmd(data, false); - msleep(MXT_FW_RESET_TIME); - retry = true; - goto retry_info; + /* OK, we are in bootloader, see if we can recover */ + if (++recovery_attempts > 1) { + dev_err(&client->dev, "Could not recover from bootloader mode\n"); + /* + * We can reflash from this state, so do not + * abort initialization. + */ + data->in_bootloader = true; + return 0; } + + /* Attempt to exit bootloader into app mode */ + mxt_send_bootloader_cmd(data, false); + msleep(MXT_FW_RESET_TIME); } /* Get object table information */ @@ -1687,13 +1712,18 @@ retry_bootloader: return error; } - mxt_acquire_irq(data); + error = mxt_acquire_irq(data); if (error) goto err_free_object_table; - request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, - &data->client->dev, GFP_KERNEL, data, - mxt_config_cb); + error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, + &client->dev, GFP_KERNEL, data, + mxt_config_cb); + if (error) { + dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", + error); + goto err_free_object_table; + } return 0; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 5a6d50c004d7..8857d5b9be71 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -262,7 +262,6 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, case M06: wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; - wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; wrbuf[2] = value; wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; return edt_ft5x06_ts_readwrite(tsdata->client, 4, diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c index f70546a3a7cc..6ada1b36685b 100644 --- a/drivers/mmc/host/dw_mmc-pci.c +++ b/drivers/mmc/host/dw_mmc-pci.c @@ -102,7 +102,7 @@ static int dw_mci_pci_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(dw_mci_pci_pmops, dw_mci_pci_suspend, dw_mci_pci_resume); -static DEFINE_PCI_DEVICE_TABLE(dw_mci_pci_id) = { +static const struct pci_device_id dw_mci_pci_id[] = { { PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) }, {} }; diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index cbc44f53755a..7bb292e59559 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -144,7 +144,7 @@ static void com20020pci_remove(struct pci_dev *pdev) free_netdev(dev); } -static DEFINE_PCI_DEVICE_TABLE(com20020pci_id_table) = { +static const struct pci_device_id com20020pci_id_table[] = { { 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index 5d11e0e4225b..7be393c96b1a 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -270,7 +270,8 @@ static struct c_can_pci_data c_can_pch = { PCI_DEVICE(_vend, _dev), \ .driver_data = (unsigned long)&_driverdata, \ } -static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = { + +static const struct pci_device_id c_can_pci_tbl[] = { C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN, c_can_sta2x11), C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN, diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 6472562efedc..a67eb01f3028 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -194,7 +194,7 @@ static const struct can_bittiming_const pch_can_bittiming_const = { .brp_inc = 1, }; -static DEFINE_PCI_DEVICE_TABLE(pch_pci_tbl) = { +static const struct pci_device_id pch_pci_tbl[] = { {PCI_VENDOR_ID_INTEL, 0x8818, PCI_ANY_ID, PCI_ANY_ID,}, {0,} }; diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c index fd13dbf07d9c..7481c324a476 100644 --- a/drivers/net/can/sja1000/ems_pci.c +++ b/drivers/net/can/sja1000/ems_pci.c @@ -101,7 +101,7 @@ struct ems_pci_card { #define EMS_PCI_BASE_SIZE 4096 /* size of controller area */ -static DEFINE_PCI_DEVICE_TABLE(ems_pci_tbl) = { +static const struct pci_device_id ems_pci_tbl[] = { /* CPC-PCI v1 */ {PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,}, /* CPC-PCI v2 */ diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c index 23b8e1324e25..8ff3424d5147 100644 --- a/drivers/net/can/sja1000/kvaser_pci.c +++ b/drivers/net/can/sja1000/kvaser_pci.c @@ -107,7 +107,7 @@ struct kvaser_pci { #define KVASER_PCI_VENDOR_ID2 0x1a07 /* the PCI device and vendor IDs */ #define KVASER_PCI_DEVICE_ID2 0x0008 -static DEFINE_PCI_DEVICE_TABLE(kvaser_pci_tbl) = { +static const struct pci_device_id kvaser_pci_tbl[] = { {KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,}, {KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,}, { 0,} diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index 564933ae218c..7a85590fefb9 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -77,7 +77,7 @@ static const u16 peak_pci_icr_masks[PEAK_PCI_CHAN_MAX] = { 0x02, 0x01, 0x40, 0x80 }; -static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = { +static const struct pci_device_id peak_pci_tbl[] = { {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c index ec39b7cb2287..8836a7485c81 100644 --- a/drivers/net/can/sja1000/plx_pci.c +++ b/drivers/net/can/sja1000/plx_pci.c @@ -247,7 +247,7 @@ static struct plx_pci_card_info plx_pci_card_info_elcus = { /* based on PLX9030 */ }; -static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = { +static const struct pci_device_id plx_pci_tbl[] = { { /* Adlink PCI-7841/cPCI-7841 */ ADLINK_PCI_VENDOR_ID, ADLINK_PCI_DEVICE_ID, diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 61477b8e8d24..059c7414e303 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -375,7 +375,7 @@ static struct vortex_chip_info { }; -static DEFINE_PCI_DEVICE_TABLE(vortex_pci_tbl) = { +static const struct pci_device_id vortex_pci_tbl[] = { { 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C590 }, { 0x10B7, 0x5920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C592 }, { 0x10B7, 0x5970, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C597 }, diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c index e13b04624ded..48775b88bac7 100644 --- a/drivers/net/ethernet/3com/typhoon.c +++ b/drivers/net/ethernet/3com/typhoon.c @@ -203,7 +203,7 @@ static struct typhoon_card_info typhoon_card_info[] = { * bit 8 indicates if this is a (0) copper or (1) fiber card * bits 12-16 indicate card type: (0) client and (1) server */ -static DEFINE_PCI_DEVICE_TABLE(typhoon_pci_tbl) = { +static const struct pci_device_id typhoon_pci_tbl[] = { { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990, PCI_ANY_ID, PCI_ANY_ID, 0, 0,TYPHOON_TX }, { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_TX_95, diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c index f395c967262e..89c8d9fc97de 100644 --- a/drivers/net/ethernet/8390/ne2k-pci.c +++ b/drivers/net/ethernet/8390/ne2k-pci.c @@ -135,7 +135,7 @@ static struct { }; -static DEFINE_PCI_DEVICE_TABLE(ne2k_pci_tbl) = { +static const struct pci_device_id ne2k_pci_tbl[] = { { 0x10ec, 0x8029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RealTek_RTL_8029 }, { 0x1050, 0x0940, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940 }, { 0x11f6, 0x1401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Compex_RL2000 }, diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index 40dbbf740331..ac7288240d55 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c @@ -285,7 +285,7 @@ enum chipset { CH_6915 = 0, }; -static DEFINE_PCI_DEVICE_TABLE(starfire_pci_tbl) = { +static const struct pci_device_id starfire_pci_tbl[] = { { PCI_VDEVICE(ADAPTEC, 0x6915), CH_6915 }, { 0, } }; diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c index 9a6991be9749..b68074803de3 100644 --- a/drivers/net/ethernet/alteon/acenic.c +++ b/drivers/net/ethernet/alteon/acenic.c @@ -131,7 +131,7 @@ #define PCI_DEVICE_ID_SGI_ACENIC 0x0009 #endif -static DEFINE_PCI_DEVICE_TABLE(acenic_pci_tbl) = { +static const struct pci_device_id acenic_pci_tbl[] = { { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_COPPER, diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index 4a8fdc4721d5..e2e3aaf501a2 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -61,7 +61,7 @@ static const char *const version = /* * PCI device identifiers for "new style" Linux PCI Device Drivers */ -static DEFINE_PCI_DEVICE_TABLE(pcnet32_pci_tbl) = { +static const struct pci_device_id pcnet32_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), }, diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index af7c40ac1455..e1a8f4e19983 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -581,7 +581,11 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( struct xgene_enet_desc_ring *ring; struct xgene_enet_pdata *pdata = netdev_priv(ndev); struct device *dev = ndev_to_dev(ndev); - u32 size; + int size; + + size = xgene_enet_get_ring_size(dev, cfgsize); + if (size < 0) + return NULL; ring = devm_kzalloc(dev, sizeof(struct xgene_enet_desc_ring), GFP_KERNEL); @@ -593,7 +597,6 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( ring->cfgsize = cfgsize; ring->id = ring_id; - size = xgene_enet_get_ring_size(dev, cfgsize); ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma, GFP_KERNEL); if (!ring->desc_addr) { diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 49faa97a30c3..e398eda07298 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -1527,7 +1527,7 @@ static const struct pci_error_handlers alx_err_handlers = { .resume = alx_pci_error_resume, }; -static DEFINE_PCI_DEVICE_TABLE(alx_pci_tbl) = { +static const struct pci_device_id alx_pci_tbl[] = { { PCI_VDEVICE(ATTANSIC, ALX_DEV_ID_AR8161), .driver_data = ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG }, { PCI_VDEVICE(ATTANSIC, ALX_DEV_ID_E2200), diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index e11bf18fbbd1..72fb86b9aa24 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -34,7 +34,7 @@ char atl1c_driver_version[] = ATL1C_DRV_VERSION; * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = { +static const struct pci_device_id atl1c_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)}, {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)}, {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)}, diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 316e0c3fe048..2326579f9454 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -35,7 +35,7 @@ char atl1e_driver_version[] = DRV_VERSION; * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static DEFINE_PCI_DEVICE_TABLE(atl1e_pci_tbl) = { +static const struct pci_device_id atl1e_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)}, {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1066)}, /* required last entry */ diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index 1546d550ac97..2c8f398aeda9 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -235,7 +235,7 @@ static void atl1_check_options(struct atl1_adapter *adapter) /* * atl1_pci_tbl - PCI Device ID Table */ -static DEFINE_PCI_DEVICE_TABLE(atl1_pci_tbl) = { +static const struct pci_device_id atl1_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)}, /* required last entry */ {0,} diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index c194bc687c30..84a09e8ddd9c 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -65,7 +65,7 @@ MODULE_VERSION(ATL2_DRV_VERSION); /* * atl2_pci_tbl - PCI Device ID Table */ -static DEFINE_PCI_DEVICE_TABLE(atl2_pci_tbl) = { +static const struct pci_device_id atl2_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2)}, /* required last entry */ {0,} diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index ca5a20a48b14..4a7028d65912 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -105,7 +105,7 @@ MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value"); #ifdef CONFIG_B44_PCI -static DEFINE_PCI_DEVICE_TABLE(b44_pci_tbl) = { +static const struct pci_device_id b44_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B0) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1) }, diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index e64c963fe775..2fee73b878c2 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -120,7 +120,7 @@ static struct { { "Broadcom NetXtreme II BCM5716 1000Base-SX" }, }; -static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = { +static const struct pci_device_id bnx2_pci_tbl[] = { { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 3871ec49cc4d..c13364b6cc19 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -249,7 +249,7 @@ static struct { #define PCI_DEVICE_ID_NX2_57811_VF CHIP_NUM_57811_VF #endif -static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = { +static const struct pci_device_id bnx2x_pci_tbl[] = { { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 }, { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 }, { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E }, diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index a3dd5dc64f4c..3ac5d23454a8 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -237,7 +237,7 @@ MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); #define TG3_DRV_DATA_FLAG_10_100_ONLY 0x0001 #define TG3_DRV_DATA_FLAG_5705_10_100 0x0002 -static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { +static const struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)}, @@ -14093,8 +14093,9 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, spin_lock_bh(&tp->lock); if (!tp->hw_stats) { + *stats = tp->net_stats_prev; spin_unlock_bh(&tp->lock); - return &tp->net_stats_prev; + return stats; } tg3_get_nstats(tp, stats); @@ -15926,7 +15927,7 @@ static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp) return TG3_RX_RET_MAX_SIZE_5705; } -static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = { +static const struct pci_device_id tg3_write_reorder_chipsets[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE) }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8385_0) }, @@ -17185,7 +17186,7 @@ static int tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, #define TEST_BUFFER_SIZE 0x2000 -static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = { +static const struct pci_device_id tg3_dma_wait_state_chipsets[] = { { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_PCI15) }, { }, }; diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index 556aab75f490..ff8cae5e2535 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -3836,7 +3836,7 @@ bnad_pci_remove(struct pci_dev *pdev) free_netdev(netdev); } -static DEFINE_PCI_DEVICE_TABLE(bnad_pci_id_table) = { +static const struct pci_device_id bnad_pci_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROCADE, PCI_DEVICE_ID_BROCADE_CT), diff --git a/drivers/net/ethernet/chelsio/cxgb/subr.c b/drivers/net/ethernet/chelsio/cxgb/subr.c index 816719314cc8..ea0f8741d7cf 100644 --- a/drivers/net/ethernet/chelsio/cxgb/subr.c +++ b/drivers/net/ethernet/chelsio/cxgb/subr.c @@ -522,7 +522,7 @@ static const struct board_info t1_board[] = { }; -DEFINE_PCI_DEVICE_TABLE(t1_pci_tbl) = { +const struct pci_device_id t1_pci_tbl[] = { CH_DEVICE(8, 0, CH_BRD_T110_1CU), CH_DEVICE(8, 1, CH_BRD_T110_1CU), CH_DEVICE(7, 0, CH_BRD_N110_1F), diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 5d9cce053cc9..db76f7040455 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -85,7 +85,7 @@ enum { #define CH_DEVICE(devid, idx) \ { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx } -static DEFINE_PCI_DEVICE_TABLE(cxgb3_pci_tbl) = { +static const struct pci_device_id cxgb3_pci_tbl[] = { CH_DEVICE(0x20, 0), /* PE9000 */ CH_DEVICE(0x21, 1), /* T302E */ CH_DEVICE(0x22, 2), /* T310E */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index a62d3f468c52..1afee70ce856 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -212,7 +212,7 @@ struct filter_entry { #define CH_DEVICE(devid, data) { PCI_VDEVICE(CHELSIO, devid), (data) } -static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = { +static const struct pci_device_id cxgb4_pci_tbl[] = { CH_DEVICE(0xa000, 0), /* PE10K */ CH_DEVICE(0x4001, -1), CH_DEVICE(0x4002, -1), diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index d8d28e82ade1..2102a4c91737 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -2910,7 +2910,7 @@ static void cxgb4vf_pci_shutdown(struct pci_dev *pdev) #define CH_DEVICE(devid, idx) \ { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx } -static DEFINE_PCI_DEVICE_TABLE(cxgb4vf_pci_tbl) = { +static const struct pci_device_id cxgb4vf_pci_tbl[] = { CH_DEVICE(0xb000, 0), /* PE10K FPGA */ CH_DEVICE(0x4800, 0), /* T440-dbg */ CH_DEVICE(0x4801, 0), /* T420-cr */ diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 9348febc0743..c8832bc1c5f7 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -67,7 +67,7 @@ #define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */ /* Supported devices */ -static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = { +static const struct pci_device_id enic_id_table[] = { { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) }, { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) }, { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) }, diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c index 38148b0e3a95..a02ecc4f9002 100644 --- a/drivers/net/ethernet/dec/tulip/de2104x.c +++ b/drivers/net/ethernet/dec/tulip/de2104x.c @@ -340,7 +340,7 @@ static void de21041_media_timer (unsigned long data); static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media); -static DEFINE_PCI_DEVICE_TABLE(de_pci_tbl) = { +static const struct pci_device_id de_pci_tbl[] = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS, diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index 7091fa6ed096..cf8b6ff21613 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -2328,7 +2328,7 @@ static void de4x5_pci_remove(struct pci_dev *pdev) pci_disable_device (pdev); } -static DEFINE_PCI_DEVICE_TABLE(de4x5_pci_tbl) = { +static const struct pci_device_id de4x5_pci_tbl[] = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS, diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c index 53f0c618045c..322213d901d5 100644 --- a/drivers/net/ethernet/dec/tulip/dmfe.c +++ b/drivers/net/ethernet/dec/tulip/dmfe.c @@ -2096,7 +2096,7 @@ static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * db) -static DEFINE_PCI_DEVICE_TABLE(dmfe_pci_tbl) = { +static const struct pci_device_id dmfe_pci_tbl[] = { { 0x1282, 0x9132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9132_ID }, { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9102_ID }, { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9100_ID }, diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index 861660841ce2..3b42556f7f8d 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@ -207,7 +207,7 @@ struct tulip_chip_table tulip_tbl[] = { }; -static DEFINE_PCI_DEVICE_TABLE(tulip_pci_tbl) = { +static const struct pci_device_id tulip_pci_tbl[] = { { 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 }, { 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21143 }, { 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 }, @@ -1294,7 +1294,7 @@ static const struct net_device_ops tulip_netdev_ops = { #endif }; -DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = { +const struct pci_device_id early_486_chipsets[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) }, { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) }, { }, diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c index 80afec335a11..4061f9b22812 100644 --- a/drivers/net/ethernet/dec/tulip/uli526x.c +++ b/drivers/net/ethernet/dec/tulip/uli526x.c @@ -1768,7 +1768,7 @@ static u16 phy_read_1bit(struct uli526x_board_info *db) } -static DEFINE_PCI_DEVICE_TABLE(uli526x_pci_tbl) = { +static const struct pci_device_id uli526x_pci_tbl[] = { { 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5261_ID }, { 0x10B9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5263_ID }, { 0, } diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c index 62fe512bb216..6aa887e0e1cb 100644 --- a/drivers/net/ethernet/dec/tulip/winbond-840.c +++ b/drivers/net/ethernet/dec/tulip/winbond-840.c @@ -219,7 +219,7 @@ enum chip_capability_flags { CanHaveMII=1, HasBrokenTx=2, AlwaysFDX=4, FDXOnNoMII=8, }; -static DEFINE_PCI_DEVICE_TABLE(w840_pci_tbl) = { +static const struct pci_device_id w840_pci_tbl[] = { { 0x1050, 0x0840, PCI_ANY_ID, 0x8153, 0, 0, 0 }, { 0x1050, 0x0840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { 0x11f6, 0x2011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c index 6204cdfe43a6..0e721cedfa67 100644 --- a/drivers/net/ethernet/dec/tulip/xircom_cb.c +++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c @@ -137,7 +137,7 @@ static int link_status(struct xircom_private *card); -static DEFINE_PCI_DEVICE_TABLE(xircom_pci_table) = { +static const struct pci_device_id xircom_pci_table[] = { { PCI_VDEVICE(XIRCOM, 0x0003), }, {0,}, }; diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h index 7d07a0f5320d..23c07b007069 100644 --- a/drivers/net/ethernet/dlink/dl2k.h +++ b/drivers/net/ethernet/dlink/dl2k.h @@ -408,7 +408,7 @@ struct netdev_private { driver_data Data private to the driver. */ -static DEFINE_PCI_DEVICE_TABLE(rio_pci_tbl) = { +static const struct pci_device_id rio_pci_tbl[] = { {0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, }, {0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, }, { } diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c index 433c1e185442..a28a2e583f0f 100644 --- a/drivers/net/ethernet/dlink/sundance.c +++ b/drivers/net/ethernet/dlink/sundance.c @@ -199,7 +199,7 @@ IVc. Errata #define USE_IO_OPS 1 #endif -static DEFINE_PCI_DEVICE_TABLE(sundance_pci_tbl) = { +static const struct pci_device_id sundance_pci_tbl[] = { { 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 }, { 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 }, { 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 }, diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 9cdeda54674a..93ff8ef39352 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -39,7 +39,7 @@ static ushort rx_frag_size = 2048; module_param(rx_frag_size, ushort, S_IRUGO); MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); -static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { +static const struct pci_device_id be_dev_ids[] = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c index 4b22a9579f85..b1b9ebafb354 100644 --- a/drivers/net/ethernet/fealnx.c +++ b/drivers/net/ethernet/fealnx.c @@ -1936,7 +1936,7 @@ static int netdev_close(struct net_device *dev) return 0; } -static DEFINE_PCI_DEVICE_TABLE(fealnx_pci_tbl) = { +static const struct pci_device_id fealnx_pci_tbl[] = { {0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, {0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c index 37860096f744..ed7916f6fbcf 100644 --- a/drivers/net/ethernet/hp/hp100.c +++ b/drivers/net/ethernet/hp/hp100.c @@ -208,7 +208,7 @@ MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl); #endif #ifdef CONFIG_PCI -static DEFINE_PCI_DEVICE_TABLE(hp100_pci_tbl) = { +static const struct pci_device_id hp100_pci_tbl[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2970A, PCI_ANY_ID, PCI_ANY_ID,}, diff --git a/drivers/net/ethernet/ibm/ehea/Makefile b/drivers/net/ethernet/ibm/ehea/Makefile index 775d9969b5c2..cd473e295242 100644 --- a/drivers/net/ethernet/ibm/ehea/Makefile +++ b/drivers/net/ethernet/ibm/ehea/Makefile @@ -1,6 +1,6 @@ # # Makefile for the eHEA ethernet device driver for IBM eServer System p # -ehea-y = ehea_main.o ehea_phyp.o ehea_qmr.o ehea_ethtool.o ehea_phyp.o +ehea-y = ehea_main.o ehea_phyp.o ehea_qmr.o ehea_ethtool.o obj-$(CONFIG_EHEA) += ehea.o diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c index 5727779a7df2..ff2903652f4b 100644 --- a/drivers/net/ethernet/icplus/ipg.c +++ b/drivers/net/ethernet/icplus/ipg.c @@ -95,7 +95,7 @@ static const char * const ipg_brand_name[] = { "D-Link NIC IP1000A" }; -static DEFINE_PCI_DEVICE_TABLE(ipg_pci_tbl) = { +static const struct pci_device_id ipg_pci_tbl[] = { { PCI_VDEVICE(SUNDANCE, 0x1023), 0 }, { PCI_VDEVICE(SUNDANCE, 0x2021), 1 }, { PCI_VDEVICE(DLINK, 0x9021), 2 }, diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 9d979d7debef..781065eb5431 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -208,7 +208,7 @@ MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); #define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static DEFINE_PCI_DEVICE_TABLE(e100_id_table) = { +static const struct pci_device_id e100_id_table[] = { INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 660971f304b2..cbc330b301cd 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -46,7 +46,7 @@ static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation * Macro expands to... * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} */ -static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { +static const struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x1000), INTEL_E1000_ETHERNET_DEVICE(0x1001), INTEL_E1000_ETHERNET_DEVICE(0x1004), diff --git a/drivers/net/ethernet/intel/e1000e/manage.c b/drivers/net/ethernet/intel/e1000e/manage.c index 58856032298d..06edfca1a35e 100644 --- a/drivers/net/ethernet/intel/e1000e/manage.c +++ b/drivers/net/ethernet/intel/e1000e/manage.c @@ -47,7 +47,7 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length) * e1000_mng_enable_host_if - Checks host interface is enabled * @hw: pointer to the HW structure * - * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND + * Returns 0 upon success, else -E1000_ERR_HOST_INTERFACE_COMMAND * * This function checks whether the HOST IF is enabled for command operation * and also checks whether the previous command is completed. It busy waits @@ -78,7 +78,7 @@ static s32 e1000_mng_enable_host_if(struct e1000_hw *hw) } if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { - e_dbg("Previous command timeout failed .\n"); + e_dbg("Previous command timeout failed.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 6938fc1ad877..5d01db1d789b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -33,6 +33,7 @@ #include <scsi/fc/fc_fcoe.h> #include <scsi/libfc.h> #include <scsi/libfcoe.h> +#include <uapi/linux/dcbnl.h> #include "i40e.h" #include "i40e_fcoe.h" diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 51bc03072ed3..eddec6ba095b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -65,7 +65,7 @@ static int i40e_veb_get_bw_info(struct i40e_veb *veb); * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static DEFINE_PCI_DEVICE_TABLE(i40e_pci_tbl) = { +static const struct pci_device_id i40e_pci_tbl[] = { {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_XL710), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_QEMU), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_A), 0}, @@ -4415,13 +4415,13 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) switch (vsi->back->hw.phy.link_info.link_speed) { case I40E_LINK_SPEED_40GB: - strncpy(speed, "40 Gbps", SPEED_SIZE); + strlcpy(speed, "40 Gbps", SPEED_SIZE); break; case I40E_LINK_SPEED_10GB: - strncpy(speed, "10 Gbps", SPEED_SIZE); + strlcpy(speed, "10 Gbps", SPEED_SIZE); break; case I40E_LINK_SPEED_1GB: - strncpy(speed, "1000 Mbps", SPEED_SIZE); + strlcpy(speed, "1000 Mbps", SPEED_SIZE); break; default: break; @@ -4429,16 +4429,16 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) switch (vsi->back->hw.fc.current_mode) { case I40E_FC_FULL: - strncpy(fc, "RX/TX", FC_SIZE); + strlcpy(fc, "RX/TX", FC_SIZE); break; case I40E_FC_TX_PAUSE: - strncpy(fc, "TX", FC_SIZE); + strlcpy(fc, "TX", FC_SIZE); break; case I40E_FC_RX_PAUSE: - strncpy(fc, "RX", FC_SIZE); + strlcpy(fc, "RX", FC_SIZE); break; default: - strncpy(fc, "None", FC_SIZE); + strlcpy(fc, "None", FC_SIZE); break; } @@ -5839,7 +5839,7 @@ static void i40e_send_version(struct i40e_pf *pf) dv.minor_version = DRV_VERSION_MINOR; dv.build_version = DRV_VERSION_BUILD; dv.subbuild_version = 0; - strncpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string)); + strlcpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string)); i40e_aq_send_driver_version(&pf->hw, &dv, NULL); } @@ -6293,7 +6293,7 @@ static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi, bool alloc_qvectors) if (alloc_qvectors) { /* allocate memory for q_vector pointers */ - size = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors; + size = sizeof(struct i40e_q_vector *) * vsi->num_q_vectors; vsi->q_vectors = kzalloc(size, GFP_KERNEL); if (!vsi->q_vectors) { ret = -ENOMEM; diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 97bda3dffd49..25c4f9a3011f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -251,9 +251,9 @@ i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, * * Writes a 16 bit words buffer to the Shadow RAM using the admin command. **/ -i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, - u32 offset, u16 words, void *data, - bool last_command) +static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, + u32 offset, u16 words, void *data, + bool last_command) { i40e_status ret_code = I40E_ERR_NVM; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index ab15f4d07e41..38429fae4fcf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -49,7 +49,7 @@ static const char i40evf_copyright[] = * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static DEFINE_PCI_DEVICE_TABLE(i40evf_pci_tbl) = { +static const struct pci_device_id i40evf_pci_tbl[] = { {PCI_VDEVICE(INTEL, I40E_DEV_ID_VF), 0}, /* required last entry */ {0, } diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index d608599e123a..63c807c9b21c 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -2853,7 +2853,7 @@ static const struct pci_error_handlers igbvf_err_handler = { .resume = igbvf_io_resume, }; -static DEFINE_PCI_DEVICE_TABLE(igbvf_pci_tbl) = { +static const struct pci_device_id igbvf_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_VF), board_vf }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_VF), board_i350_vf }, { } /* terminate list */ diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index 60801273915c..055961b0f24b 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -53,7 +53,7 @@ MODULE_PARM_DESC(copybreak, * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static DEFINE_PCI_DEVICE_TABLE(ixgb_pci_tbl) = { +static const struct pci_device_id ixgb_pci_tbl[] = { {PCI_VENDOR_ID_INTEL, IXGB_DEVICE_ID_82597EX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_INTEL, IXGB_DEVICE_ID_82597EX_CX4, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 5384ed30298a..87bd53fdd209 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -84,7 +84,7 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = { * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { +static const struct pci_device_id ixgbe_pci_tbl[] = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598), board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT), board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT), board_82598 }, diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 75467f83772c..c22a00c3621a 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -76,7 +76,7 @@ static const struct ixgbevf_info *ixgbevf_info_tbl[] = { * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static DEFINE_PCI_DEVICE_TABLE(ixgbevf_pci_tbl) = { +static const struct pci_device_id ixgbevf_pci_tbl[] = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF), board_82599_vf }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF), board_X540_vf }, /* required last entry */ diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index b78378cea5e3..4a1be34d7214 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -3334,7 +3334,7 @@ static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume); #define JME_PM_OPS NULL #endif -static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { +static const struct pci_device_id jme_pci_tbl[] = { { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) }, { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) }, { } diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index e912b6887d40..24b242277ea1 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -82,7 +82,7 @@ static int debug = -1; /* defaults above */ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -static DEFINE_PCI_DEVICE_TABLE(skge_id_table) = { +static const struct pci_device_id skge_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x1700) }, /* 3Com 3C940 */ { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x80EB) }, /* 3Com 3C940B */ #ifdef CONFIG_SKGE_GENESIS diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 59915144aabb..dba48a5ce7ab 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -101,7 +101,7 @@ static int legacy_pme = 0; module_param(legacy_pme, int, 0); MODULE_PARM_DESC(legacy_pme, "Legacy power management"); -static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = { +static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E01) }, /* SK-9E21M */ diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 0158689906fd..7e2d5d57c598 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -2732,7 +2732,7 @@ int mlx4_restart_one(struct pci_dev *pdev) return __mlx4_init_one(pdev, pci_dev_data); } -static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = { +static const struct pci_device_id mlx4_pci_table[] = { /* MT25408 "Hermon" SDR */ { PCI_VDEVICE(MELLANOX, 0x6340), MLX4_PCI_DEV_FORCE_SENSE_PORT }, /* MT25408 "Hermon" DDR */ diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index cd5f106306d9..f1ebed6c63b1 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -7221,7 +7221,7 @@ static int pcidev_suspend(struct pci_dev *pdev, pm_message_t state) static char pcidev_name[] = "ksz884xp"; -static DEFINE_PCI_DEVICE_TABLE(pcidev_table) = { +static const struct pci_device_id pcidev_table[] = { { PCI_VENDOR_ID_MICREL_KS, 0x8841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_MICREL_KS, 0x8842, diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 69c26f04d8ce..9e7e3f1dce3e 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -873,6 +873,10 @@ static int myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type) return -ENOMEM; dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); + if (unlikely(pci_dma_mapping_error(mgp->pdev, dmatest_bus))) { + __free_page(dmatest_page); + return -ENOMEM; + } /* Run a small DMA test. * The magic multipliers to the length tell the firmware @@ -1294,6 +1298,7 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, int bytes, int watchdog) { struct page *page; + dma_addr_t bus; int idx; #if MYRI10GE_ALLOC_SIZE > 4096 int end_offset; @@ -1318,11 +1323,21 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, rx->watchdog_needed = 1; return; } + + bus = pci_map_page(mgp->pdev, page, 0, + MYRI10GE_ALLOC_SIZE, + PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) { + __free_pages(page, MYRI10GE_ALLOC_ORDER); + if (rx->fill_cnt - rx->cnt < 16) + rx->watchdog_needed = 1; + return; + } + rx->page = page; rx->page_offset = 0; - rx->bus = pci_map_page(mgp->pdev, page, 0, - MYRI10GE_ALLOC_SIZE, - PCI_DMA_FROMDEVICE); + rx->bus = bus; + } rx->info[idx].page = rx->page; rx->info[idx].page_offset = rx->page_offset; @@ -2764,6 +2779,35 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src, mb(); } +static void myri10ge_unmap_tx_dma(struct myri10ge_priv *mgp, + struct myri10ge_tx_buf *tx, int idx) +{ + unsigned int len; + int last_idx; + + /* Free any DMA resources we've alloced and clear out the skb slot */ + last_idx = (idx + 1) & tx->mask; + idx = tx->req & tx->mask; + do { + len = dma_unmap_len(&tx->info[idx], len); + if (len) { + if (tx->info[idx].skb != NULL) + pci_unmap_single(mgp->pdev, + dma_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + else + pci_unmap_page(mgp->pdev, + dma_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + dma_unmap_len_set(&tx->info[idx], len, 0); + tx->info[idx].skb = NULL; + } + idx = (idx + 1) & tx->mask; + } while (idx != last_idx); +} + /* * Transmit a packet. We need to split the packet so that a single * segment does not cross myri10ge->tx_boundary, so this makes segment @@ -2787,7 +2831,7 @@ static netdev_tx_t myri10ge_xmit(struct sk_buff *skb, u32 low; __be32 high_swapped; unsigned int len; - int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments; + int idx, avail, frag_cnt, frag_idx, count, mss, max_segments; u16 pseudo_hdr_offset, cksum_offset, queue; int cum_len, seglen, boundary, rdma_count; u8 flags, odd_flag; @@ -2884,9 +2928,12 @@ again: /* map the skb for DMA */ len = skb_headlen(skb); + bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); + if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) + goto drop; + idx = tx->req & tx->mask; tx->info[idx].skb = skb; - bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); dma_unmap_addr_set(&tx->info[idx], bus, bus); dma_unmap_len_set(&tx->info[idx], len, len); @@ -2985,12 +3032,16 @@ again: break; /* map next fragment for DMA */ - idx = (count + tx->req) & tx->mask; frag = &skb_shinfo(skb)->frags[frag_idx]; frag_idx++; len = skb_frag_size(frag); bus = skb_frag_dma_map(&mgp->pdev->dev, frag, 0, len, DMA_TO_DEVICE); + if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) { + myri10ge_unmap_tx_dma(mgp, tx, idx); + goto drop; + } + idx = (count + tx->req) & tx->mask; dma_unmap_addr_set(&tx->info[idx], bus, bus); dma_unmap_len_set(&tx->info[idx], len, len); } @@ -3021,31 +3072,8 @@ again: return NETDEV_TX_OK; abort_linearize: - /* Free any DMA resources we've alloced and clear out the skb - * slot so as to not trip up assertions, and to avoid a - * double-free if linearizing fails */ + myri10ge_unmap_tx_dma(mgp, tx, idx); - last_idx = (idx + 1) & tx->mask; - idx = tx->req & tx->mask; - tx->info[idx].skb = NULL; - do { - len = dma_unmap_len(&tx->info[idx], len); - if (len) { - if (tx->info[idx].skb != NULL) - pci_unmap_single(mgp->pdev, - dma_unmap_addr(&tx->info[idx], - bus), len, - PCI_DMA_TODEVICE); - else - pci_unmap_page(mgp->pdev, - dma_unmap_addr(&tx->info[idx], - bus), len, - PCI_DMA_TODEVICE); - dma_unmap_len_set(&tx->info[idx], len, 0); - tx->info[idx].skb = NULL; - } - idx = (idx + 1) & tx->mask; - } while (idx != last_idx); if (skb_is_gso(skb)) { netdev_err(mgp->dev, "TSO but wanted to linearize?!?!?\n"); goto drop; @@ -4214,7 +4242,7 @@ static void myri10ge_remove(struct pci_dev *pdev) #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 0x0008 #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9 0x0009 -static DEFINE_PCI_DEVICE_TABLE(myri10ge_pci_tbl) = { +static const struct pci_device_id myri10ge_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)}, {PCI_DEVICE (PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9)}, diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c index 291fba8b9f07..b83f7c0fcf99 100644 --- a/drivers/net/ethernet/natsemi/natsemi.c +++ b/drivers/net/ethernet/natsemi/natsemi.c @@ -247,7 +247,7 @@ static struct { { "NatSemi DP8381[56]", 0, 24 }, }; -static DEFINE_PCI_DEVICE_TABLE(natsemi_pci_tbl) = { +static const struct pci_device_id natsemi_pci_tbl[] = { { PCI_VENDOR_ID_NS, 0x0020, 0x12d9, 0x000c, 0, 0, 0 }, { PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { } /* terminate list */ diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index 19bb8244b9e3..2552e550a78c 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -2260,7 +2260,7 @@ static void ns83820_remove_one(struct pci_dev *pci_dev) free_netdev(ndev); } -static DEFINE_PCI_DEVICE_TABLE(ns83820_pci_tbl) = { +static const struct pci_device_id ns83820_pci_tbl[] = { { 0x100b, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, .driver_data = 0, }, { 0, }, }; diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index be587647c706..f5e4b820128b 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -471,7 +471,7 @@ module_param_array(rts_frm_len, uint, NULL, 0); * S2IO device table. * This table lists all the devices that this driver supports. */ -static DEFINE_PCI_DEVICE_TABLE(s2io_tbl) = { +static const struct pci_device_id s2io_tbl[] = { {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI, diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 2eda153cb1e0..4f40d7b8629e 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -63,7 +63,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("Neterion's X3100 Series 10GbE PCIe I/O" "Virtualized Server Adapter"); -static DEFINE_PCI_DEVICE_TABLE(vxge_id_table) = { +static const struct pci_device_id vxge_id_table[] = { {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_TITAN_WIN, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_TITAN_UNI, PCI_ANY_ID, diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 9afc536c5734..925b296d8ab8 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -6185,7 +6185,7 @@ static void nv_shutdown(struct pci_dev *pdev) #define nv_shutdown NULL #endif /* CONFIG_PM */ -static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = { +static const struct pci_device_id pci_tbl[] = { { /* nForce Ethernet Controller */ PCI_DEVICE(0x10DE, 0x01C3), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 73e66838cfef..3b98b263bad0 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -2743,7 +2743,7 @@ static struct pch_gbe_privdata pch_gbe_minnow_privdata = { .platform_init = pch_gbe_minnow_platform_init, }; -static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = { +static const struct pci_device_id pch_gbe_pcidev_id[] = { {.vendor = PCI_VENDOR_ID_INTEL, .device = PCI_DEVICE_ID_INTEL_IOH1_GBE, .subvendor = PCI_VENDOR_ID_CIRCUITCO, diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c index 9a997e4c3e08..319d9d40f922 100644 --- a/drivers/net/ethernet/packetengines/hamachi.c +++ b/drivers/net/ethernet/packetengines/hamachi.c @@ -1911,7 +1911,7 @@ static void hamachi_remove_one(struct pci_dev *pdev) } } -static DEFINE_PCI_DEVICE_TABLE(hamachi_pci_tbl) = { +static const struct pci_device_id hamachi_pci_tbl[] = { { 0x1318, 0x0911, PCI_ANY_ID, PCI_ANY_ID, }, { 0, } }; diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c index 69a8dc095072..2d6b148528dd 100644 --- a/drivers/net/ethernet/packetengines/yellowfin.c +++ b/drivers/net/ethernet/packetengines/yellowfin.c @@ -236,7 +236,7 @@ static const struct pci_id_info pci_id_tbl[] = { { } }; -static DEFINE_PCI_DEVICE_TABLE(yellowfin_pci_tbl) = { +static const struct pci_device_id yellowfin_pci_tbl[] = { { 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { } diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index 9abf70d74b31..30d934d66356 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -1871,7 +1871,7 @@ static void pasemi_mac_remove(struct pci_dev *pdev) free_netdev(netdev); } -static DEFINE_PCI_DEVICE_TABLE(pasemi_mac_pci_tbl) = { +static const struct pci_device_id pasemi_mac_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) }, { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) }, { }, diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 5bf05818a12c..1159031f885b 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -99,7 +99,7 @@ static int netxen_nic_set_mac(struct net_device *netdev, void *p); {PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \ .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} -static DEFINE_PCI_DEVICE_TABLE(netxen_pci_tbl) = { +static const struct pci_device_id netxen_pci_tbl[] = { ENTRY(PCI_DEVICE_ID_NX2031_10GXSR), ENTRY(PCI_DEVICE_ID_NX2031_10GCX4), ENTRY(PCI_DEVICE_ID_NX2031_4GCU), diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index b5d6bc1a8b00..c2f09af5c25b 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -65,7 +65,7 @@ static int msi; module_param(msi, int, 0); MODULE_PARM_DESC(msi, "Turn on Message Signaled Interrupts."); -static DEFINE_PCI_DEVICE_TABLE(ql3xxx_pci_tbl) = { +static const struct pci_device_id ql3xxx_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3022_DEVICE_ID)}, {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3032_DEVICE_ID)}, /* required last entry */ diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 59846daf1379..cf08b2de071e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -108,7 +108,7 @@ static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter) {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} -static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = { +static const struct pci_device_id qlcnic_pci_tbl[] = { ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X), ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X), ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE834X), diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index d836ace52277..188626e2a861 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -86,7 +86,7 @@ MODULE_PARM_DESC(qlge_force_coredump, "Option to allow force of firmware core dump. " "Default is OFF - Do not allow."); -static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = { +static const struct pci_device_id qlge_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)}, /* required last entry */ diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c index cd045ecb9816..9a37247cf4b8 100644 --- a/drivers/net/ethernet/rdc/r6040.c +++ b/drivers/net/ethernet/rdc/r6040.c @@ -1254,7 +1254,7 @@ static void r6040_remove_one(struct pci_dev *pdev) } -static DEFINE_PCI_DEVICE_TABLE(r6040_pci_tbl) = { +static const struct pci_device_id r6040_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_RDC, 0x6040) }, { 0 } }; diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c index 2e5df148af4c..007b38cce69a 100644 --- a/drivers/net/ethernet/realtek/8139too.c +++ b/drivers/net/ethernet/realtek/8139too.c @@ -234,7 +234,7 @@ static const struct { }; -static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { +static const struct pci_device_id rtl8139_pci_tbl[] = { {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 9887bcb45b84..91652e7235e4 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -291,7 +291,7 @@ enum cfg_version { RTL_CFG_2 }; -static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { +static const struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 4cebe9d37816..b2cc590dd1dd 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2642,7 +2642,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) **************************************************************************/ /* PCI device ID table */ -static DEFINE_PCI_DEVICE_TABLE(efx_pci_table) = { +static const struct pci_device_id efx_pci_table[] = { {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0), .driver_data = (unsigned long) &falcon_a1_nic_type}, diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 7984ad05357d..7a254da85dd7 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -1384,7 +1384,7 @@ static void ioc3_remove_one(struct pci_dev *pdev) */ } -static DEFINE_PCI_DEVICE_TABLE(ioc3_pci_tbl) = { +static const struct pci_device_id ioc3_pci_tbl[] = { { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID }, { 0 } }; diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c index 7daa7d433099..7426f8b21252 100644 --- a/drivers/net/ethernet/silan/sc92031.c +++ b/drivers/net/ethernet/silan/sc92031.c @@ -1561,7 +1561,7 @@ out: return 0; } -static DEFINE_PCI_DEVICE_TABLE(sc92031_pci_device_id_table) = { +static const struct pci_device_id sc92031_pci_device_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) }, { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) }, { PCI_DEVICE(0x1088, 0x2031) }, diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c index a86339903b9b..27be6c869315 100644 --- a/drivers/net/ethernet/sis/sis190.c +++ b/drivers/net/ethernet/sis/sis190.c @@ -330,7 +330,7 @@ static const struct { { "SiS 191 PCI Gigabit Ethernet adapter" }, }; -static DEFINE_PCI_DEVICE_TABLE(sis190_pci_tbl) = { +static const struct pci_device_id sis190_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 }, { 0, }, diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 7bea17c41dc9..fd812d2e5e1c 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -106,7 +106,8 @@ static const char * card_names[] = { "SiS 900 PCI Fast Ethernet", "SiS 7016 PCI Fast Ethernet" }; -static DEFINE_PCI_DEVICE_TABLE(sis900_pci_tbl) = { + +static const struct pci_device_id sis900_pci_tbl[] = { {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_900}, {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7016, diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c index 8ae1f8a7bf38..443f1da9fc9e 100644 --- a/drivers/net/ethernet/smsc/epic100.c +++ b/drivers/net/ethernet/smsc/epic100.c @@ -173,7 +173,7 @@ static const struct epic_chip_info pci_id_tbl[] = { }; -static DEFINE_PCI_DEVICE_TABLE(epic_pci_tbl) = { +static const struct pci_device_id epic_pci_tbl[] = { { 0x10B8, 0x0005, 0x1092, 0x0AB4, 0, 0, SMSC_83C170_0 }, { 0x10B8, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C170 }, { 0x10B8, 0x0006, PCI_ANY_ID, PCI_ANY_ID, diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c index d3b967aff9e0..4a90cdae5444 100644 --- a/drivers/net/ethernet/smsc/smsc9420.c +++ b/drivers/net/ethernet/smsc/smsc9420.c @@ -83,7 +83,7 @@ struct smsc9420_pdata { int last_carrier; }; -static DEFINE_PCI_DEVICE_TABLE(smsc9420_id_table) = { +static const struct pci_device_id smsc9420_id_table[] = { { PCI_VENDOR_ID_9420, PCI_DEVICE_ID_9420, PCI_ANY_ID, PCI_ANY_ID, }, { 0, } }; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 291608924849..655a23bbc451 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -170,7 +170,7 @@ static int stmmac_pci_resume(struct pci_dev *pdev) #define STMMAC_VENDOR_ID 0x700 #define STMMAC_DEVICE_ID 0x1108 -static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = { +static const struct pci_device_id stmmac_id_table[] = { {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)}, {} diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index b9ac20f42651..37f87ff28f03 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -229,7 +229,7 @@ static u16 link_modes[] = { CAS_BMCR_SPEED1000|BMCR_FULLDPLX /* 5 : 1000bt full duplex */ }; -static DEFINE_PCI_DEVICE_TABLE(cas_pci_tbl) = { +static const struct pci_device_id cas_pci_tbl[] = { { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_CASSINI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SATURN, diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index db8ffde491b5..8216be46540f 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -59,7 +59,7 @@ static void writeq(u64 val, void __iomem *reg) } #endif -static DEFINE_PCI_DEVICE_TABLE(niu_pci_tbl) = { +static const struct pci_device_id niu_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_SUN, 0xabcd)}, {} }; diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index 102a66fc54a2..f7415b6bf141 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -85,7 +85,7 @@ MODULE_LICENSE("GPL"); #define GEM_MODULE_NAME "gem" -static DEFINE_PCI_DEVICE_TABLE(gem_pci_tbl) = { +static const struct pci_device_id gem_pci_tbl[] = { { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_GEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c index 0dbf46f08ed5..72c8525d5457 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c @@ -3172,7 +3172,7 @@ static void happy_meal_pci_remove(struct pci_dev *pdev) free_netdev(net_dev); } -static DEFINE_PCI_DEVICE_TABLE(happymeal_pci_ids) = { +static const struct pci_device_id happymeal_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL) }, { } /* Terminating entry */ }; diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index d813bfb1a847..23c89ab5a6ad 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -32,6 +32,11 @@ MODULE_DESCRIPTION("Sun LDOM virtual network driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); +/* Heuristic for the number of times to exponentially backoff and + * retry sending an LDC trigger when EAGAIN is encountered + */ +#define VNET_MAX_RETRIES 10 + /* Ordered from largest major to lowest */ static struct vio_version vnet_versions[] = { { .major = 1, .minor = 0 }, @@ -260,6 +265,7 @@ static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr, .state = vio_dring_state, }; int err, delay; + int retries = 0; hdr.seq = dr->snd_nxt; delay = 1; @@ -272,6 +278,13 @@ static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr, udelay(delay); if ((delay <<= 1) > 128) delay = 128; + if (retries++ > VNET_MAX_RETRIES) { + pr_info("ECONNRESET %x:%x:%x:%x:%x:%x\n", + port->raddr[0], port->raddr[1], + port->raddr[2], port->raddr[3], + port->raddr[4], port->raddr[5]); + err = -ECONNRESET; + } } while (err == -EAGAIN); return err; @@ -475,8 +488,9 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf) return 0; } -static void maybe_tx_wakeup(struct vnet *vp) +static void maybe_tx_wakeup(unsigned long param) { + struct vnet *vp = (struct vnet *)param; struct net_device *dev = vp->dev; netif_tx_lock(dev); @@ -573,8 +587,13 @@ static void vnet_event(void *arg, int event) break; } spin_unlock(&vio->lock); + /* Kick off a tasklet to wake the queue. We cannot call + * maybe_tx_wakeup directly here because we could deadlock on + * netif_tx_lock() with dev_watchdog() + */ if (unlikely(tx_wakeup && err != -ECONNRESET)) - maybe_tx_wakeup(port->vp); + tasklet_schedule(&port->vp->vnet_tx_wakeup); + local_irq_restore(flags); } @@ -593,6 +612,7 @@ static int __vnet_tx_trigger(struct vnet_port *port) .end_idx = (u32) -1, }; int err, delay; + int retries = 0; hdr.seq = dr->snd_nxt; delay = 1; @@ -605,6 +625,8 @@ static int __vnet_tx_trigger(struct vnet_port *port) udelay(delay); if ((delay <<= 1) > 128) delay = 128; + if (retries++ > VNET_MAX_RETRIES) + break; } while (err == -EAGAIN); return err; @@ -691,7 +713,15 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) memset(tx_buf+VNET_PACKET_SKIP+skb->len, 0, len - skb->len); } - d->hdr.ack = VIO_ACK_ENABLE; + /* We don't rely on the ACKs to free the skb in vnet_start_xmit(), + * thus it is safe to not set VIO_ACK_ENABLE for each transmission: + * the protocol itself does not require it as long as the peer + * sends a VIO_SUBTYPE_ACK for VIO_DRING_STOPPED. + * + * An ACK for every packet in the ring is expensive as the + * sending of LDC messages is slow and affects performance. + */ + d->hdr.ack = VIO_ACK_DISABLE; d->size = len; d->ncookies = port->tx_bufs[dr->prod].ncookies; for (i = 0; i < d->ncookies; i++) @@ -1046,6 +1076,7 @@ static struct vnet *vnet_new(const u64 *local_mac) vp = netdev_priv(dev); spin_lock_init(&vp->lock); + tasklet_init(&vp->vnet_tx_wakeup, maybe_tx_wakeup, (unsigned long)vp); vp->dev = dev; INIT_LIST_HEAD(&vp->port_list); @@ -1105,6 +1136,7 @@ static void vnet_cleanup(void) vp = list_first_entry(&vnet_list, struct vnet, list); list_del(&vp->list); dev = vp->dev; + tasklet_kill(&vp->vnet_tx_wakeup); /* vio_unregister_driver() should have cleaned up port_list */ BUG_ON(!list_empty(&vp->port_list)); unregister_netdev(dev); diff --git a/drivers/net/ethernet/sun/sunvnet.h b/drivers/net/ethernet/sun/sunvnet.h index d347a5bf24b0..de5c2c64996f 100644 --- a/drivers/net/ethernet/sun/sunvnet.h +++ b/drivers/net/ethernet/sun/sunvnet.h @@ -1,6 +1,8 @@ #ifndef _SUNVNET_H #define _SUNVNET_H +#include <linux/interrupt.h> + #define DESC_NCOOKIES(entry_size) \ ((entry_size) - sizeof(struct vio_net_desc)) @@ -78,6 +80,8 @@ struct vnet { struct list_head list; u64 local_mac; + + struct tasklet_struct vnet_tx_wakeup; }; #endif /* _SUNVNET_H */ diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index 38da73a2a886..6ab36d9ff2ab 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -66,7 +66,7 @@ #include "tehuti.h" -static DEFINE_PCI_DEVICE_TABLE(bdx_pci_tbl) = { +static const struct pci_device_id bdx_pci_tbl[] = { { PCI_VDEVICE(TEHUTI, 0x3009), }, { PCI_VDEVICE(TEHUTI, 0x3010), }, { PCI_VDEVICE(TEHUTI, 0x3014), }, diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index 6078342fe3f2..f2ff0074aac9 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -116,7 +116,7 @@ static struct board { TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */ }; -static DEFINE_PCI_DEVICE_TABLE(tlan_pci_tbl) = { +static const struct pci_device_id tlan_pci_tbl[] = { { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100, diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c index 0282d0161859..3e38f67c6011 100644 --- a/drivers/net/ethernet/toshiba/spider_net.c +++ b/drivers/net/ethernet/toshiba/spider_net.c @@ -73,7 +73,7 @@ MODULE_PARM_DESC(tx_descriptors, "number of descriptors used " \ char spider_net_driver_name[] = "spidernet"; -static DEFINE_PCI_DEVICE_TABLE(spider_net_pci_tbl) = { +static const struct pci_device_id spider_net_pci_tbl[] = { { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SPIDER_NET, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { 0, } diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c index fef5573dbfca..45ac38d29ed8 100644 --- a/drivers/net/ethernet/toshiba/tc35815.c +++ b/drivers/net/ethernet/toshiba/tc35815.c @@ -65,7 +65,7 @@ static const struct { { "TOSHIBA TC35815/TX4939" }, }; -static DEFINE_PCI_DEVICE_TABLE(tc35815_pci_tbl) = { +static const struct pci_device_id tc35815_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815CF), .driver_data = TC35815CF }, {PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_NWU), .driver_data = TC35815_NWU }, {PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939), .driver_data = TC35815_TX4939 }, diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 2d72f96a9e2c..68c5260cc322 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -273,7 +273,7 @@ enum rhine_quirks { /* Beware of PCI posted writes */ #define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0) -static DEFINE_PCI_DEVICE_TABLE(rhine_pci_tbl) = { +static const struct pci_device_id rhine_pci_tbl[] = { { 0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, }, /* VT86C100A */ { 0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, }, /* VT6102 */ { 0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, }, /* 6105{,L,LOM} */ diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index de08e86db209..f5fbc12d3e10 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -381,7 +381,7 @@ static struct velocity_info_tbl chip_info_table[] = { * device driver. Used for hotplug autoloading. */ -static DEFINE_PCI_DEVICE_TABLE(velocity_pci_id_table) = { +static const struct pci_device_id velocity_pci_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) }, { } }; diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 36f4459520c3..fda5891835d4 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1170,7 +1170,6 @@ static struct platform_driver temac_of_driver = { .probe = temac_of_probe, .remove = temac_of_remove, .driver = { - .owner = THIS_MODULE, .name = "xilinx_temac", .of_match_table = temac_of_match, }, diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 30e8608ff050..c8fd94133ecd 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1645,7 +1645,6 @@ static struct platform_driver axienet_of_driver = { .probe = axienet_of_probe, .remove = axienet_of_remove, .driver = { - .owner = THIS_MODULE, .name = "xilinx_axienet", .of_match_table = axienet_of_match, }, diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 782bb9373cd8..28dbbdc393eb 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -1245,7 +1245,6 @@ MODULE_DEVICE_TABLE(of, xemaclite_of_match); static struct platform_driver xemaclite_of_driver = { .driver = { .name = DRIVER_NAME, - .owner = THIS_MODULE, .of_match_table = xemaclite_of_match, }, .probe = xemaclite_of_probe, diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c index 6eb849a56da5..c44eaf019dea 100644 --- a/drivers/net/fddi/defxx.c +++ b/drivers/net/fddi/defxx.c @@ -3664,7 +3664,7 @@ static int __maybe_unused dfx_dev_unregister(struct device *); static int dfx_pci_register(struct pci_dev *, const struct pci_device_id *); static void dfx_pci_unregister(struct pci_dev *); -static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = { +static const struct pci_device_id dfx_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) }, { } }; diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c index d5f58121b2e2..51acc6d86e91 100644 --- a/drivers/net/fddi/skfp/skfddi.c +++ b/drivers/net/fddi/skfp/skfddi.c @@ -149,7 +149,7 @@ extern void mac_drv_rx_mode(struct s_smc *smc, int mode); extern void mac_drv_clear_rx_queue(struct s_smc *smc); extern void enable_tx_irq(struct s_smc *smc, u_short queue); -static DEFINE_PCI_DEVICE_TABLE(skfddi_pci_tbl) = { +static const struct pci_device_id skfddi_pci_tbl[] = { { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ }; diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c index e580583f196d..95c0b45a68fb 100644 --- a/drivers/net/hippi/rrunner.c +++ b/drivers/net/hippi/rrunner.c @@ -1668,7 +1668,7 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } } -static DEFINE_PCI_DEVICE_TABLE(rr_pci_tbl) = { +static const struct pci_device_id rr_pci_tbl[] = { { PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, PCI_ANY_ID, PCI_ANY_ID, }, { 0,} diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 768dfe9a9315..a87a82ca111f 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -184,7 +184,7 @@ #define CONFIG0H_DMA_ON_NORX CONFIG0H_DMA_OFF| OBOE_CONFIG0H_ENDMAC #define CONFIG0H_DMA_ON CONFIG0H_DMA_ON_NORX | OBOE_CONFIG0H_ENRX -static DEFINE_PCI_DEVICE_TABLE(toshoboe_pci_tbl) = { +static const struct pci_device_id toshoboe_pci_tbl[] = { { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIRD01, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ @@ -1755,17 +1755,4 @@ static struct pci_driver donauboe_pci_driver = { .resume = toshoboe_wakeup }; -static int __init -donauboe_init (void) -{ - return pci_register_driver(&donauboe_pci_driver); -} - -static void __exit -donauboe_cleanup (void) -{ - pci_unregister_driver(&donauboe_pci_driver); -} - -module_init(donauboe_init); -module_exit(donauboe_cleanup); +module_pci_driver(donauboe_pci_driver); diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index 998bb89ede71..36e004288ea7 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -115,7 +115,7 @@ static void iodelay(int udelay) } } -static DEFINE_PCI_DEVICE_TABLE(via_pci_tbl) = { +static const struct pci_device_id via_pci_tbl[] = { { PCI_VENDOR_ID_VIA, 0x8231, PCI_ANY_ID, PCI_ANY_ID,0,0,0 }, { PCI_VENDOR_ID_VIA, 0x3109, PCI_ANY_ID, PCI_ANY_ID,0,0,1 }, { PCI_VENDOR_ID_VIA, 0x3074, PCI_ANY_ID, PCI_ANY_ID,0,0,2 }, diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index 58ef59469dd0..a04af9d0f8f9 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -58,7 +58,7 @@ MODULE_LICENSE("GPL"); static /* const */ char drivername[] = DRIVER_NAME; -static DEFINE_PCI_DEVICE_TABLE(vlsi_irda_table) = { +static const struct pci_device_id vlsi_irda_table[] = { { .class = PCI_CLASS_WIRELESS_IRDA << 8, .class_mask = PCI_CLASS_SUBCLASS_MASK << 8, diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index ef8a5c20236a..60e4ca01ccbb 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -45,10 +45,9 @@ struct macvlan_port { struct sk_buff_head bc_queue; struct work_struct bc_work; bool passthru; + int count; }; -#define MACVLAN_PORT_IS_EMPTY(port) list_empty(&port->vlans) - struct macvlan_skb_cb { const struct macvlan_dev *src; }; @@ -667,7 +666,8 @@ static void macvlan_uninit(struct net_device *dev) free_percpu(vlan->pcpu_stats); - if (MACVLAN_PORT_IS_EMPTY(port)) + port->count -= 1; + if (!port->count) macvlan_port_destroy(port->dev); } @@ -1020,12 +1020,13 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, vlan->flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]); if (vlan->mode == MACVLAN_MODE_PASSTHRU) { - if (!MACVLAN_PORT_IS_EMPTY(port)) + if (port->count) return -EINVAL; port->passthru = true; eth_hw_addr_inherit(dev, lowerdev); } + port->count += 1; err = register_netdevice(dev); if (err < 0) goto destroy_port; @@ -1043,7 +1044,8 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, unregister_netdev: unregister_netdevice(dev); destroy_port: - if (MACVLAN_PORT_IS_EMPTY(port)) + port->count -= 1; + if (!port->count) macvlan_port_destroy(lowerdev); return err; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index d0db371c30a7..d6e90c72c257 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -36,7 +36,7 @@ char vmxnet3_driver_name[] = "vmxnet3"; * PCI Device ID Table * Last entry must be all 0s */ -static DEFINE_PCI_DEVICE_TABLE(vmxnet3_pciid_table) = { +static const struct pci_device_id vmxnet3_pciid_table[] = { {PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_VMXNET3)}, {0} }; diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 288610df205c..08223569cebd 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -2039,7 +2039,7 @@ static int __init dscc4_setup(char *str) __setup("dscc4.setup=", dscc4_setup); #endif -static DEFINE_PCI_DEVICE_TABLE(dscc4_pci_tbl) = { +static const struct pci_device_id dscc4_pci_tbl[] = { { PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_DSCC4, PCI_ANY_ID, PCI_ANY_ID, }, { 0,} diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 1f041271f7fe..44541dbc5c28 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -531,7 +531,7 @@ do { \ /* * PCI ID lookup table */ -static DEFINE_PCI_DEVICE_TABLE(fst_pci_dev_id) = { +static const struct pci_device_id fst_pci_dev_id[] = { {PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T2P, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FST_TYPE_T2P}, diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index b2fe9bb89633..bea0f313a7a8 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -76,7 +76,7 @@ static int LMC_PKT_BUF_SZ = 1542; -static DEFINE_PCI_DEVICE_TABLE(lmc_pci_tbl) = { +static const struct pci_device_id lmc_pci_tbl[] = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, PCI_VENDOR_ID_LMC, PCI_ANY_ID }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c index 5b72f7f8c516..db363856e0b5 100644 --- a/drivers/net/wan/pc300too.c +++ b/drivers/net/wan/pc300too.c @@ -477,7 +477,7 @@ static int pc300_pci_init_one(struct pci_dev *pdev, -static DEFINE_PCI_DEVICE_TABLE(pc300_pci_tbl) = { +static const struct pci_device_id pc300_pci_tbl[] = { { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_2, PCI_ANY_ID, diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index fe4e3ece3c42..e8455621390e 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -414,7 +414,7 @@ static int pci200_pci_init_one(struct pci_dev *pdev, -static DEFINE_PCI_DEVICE_TABLE(pci200_pci_tbl) = { +static const struct pci_device_id pci200_pci_tbl[] = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 }, { 0, } diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 1287c3eb33c2..e73f13857846 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -808,7 +808,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev, return 0; } -static DEFINE_PCI_DEVICE_TABLE(wanxl_pci_tbl) = { +static const struct pci_device_id wanxl_pci_tbl[] = { { PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL200, PCI_ANY_ID, diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index f35f93c31b09..17fcaabb2687 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -41,7 +41,7 @@ static unsigned int rx_ring_size __read_mostly = 16; module_param(tx_ring_size, uint, 0); module_param(rx_ring_size, uint, 0); -static DEFINE_PCI_DEVICE_TABLE(adm8211_pci_id_table) = { +static const struct pci_device_id adm8211_pci_id_table[] = { /* ADMtek ADM8211 */ { PCI_DEVICE(0x10B7, 0x6000) }, /* 3Com 3CRSHPW796 */ { PCI_DEVICE(0x1200, 0x8201) }, /* ? */ diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index b39807579a8a..e71a2ce7a448 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -57,7 +57,7 @@ #define DRV_NAME "airo" #ifdef CONFIG_PCI -static DEFINE_PCI_DEVICE_TABLE(card_ids) = { +static const struct pci_device_id card_ids[] = { { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, }, { 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID }, { 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, }, diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 0ffff205478d..3376963a4862 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -63,7 +63,7 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)"); #define QCA988X_2_0_DEVICE_ID (0x003c) -static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = { +static const struct pci_device_id ath10k_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ {0} }; diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index f77ef36acf87..48a6a69b57bc 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -53,7 +53,7 @@ #define ATH_POLARITY(data) ((data) & 0xff) /* Devices we match on for LED config info (typically laptops) */ -static DEFINE_PCI_DEVICE_TABLE(ath5k_led_devices) = { +static const struct pci_device_id ath5k_led_devices[] = { /* AR5211 */ { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, /* HP Compaq nc6xx, nc4000, nx6000 */ diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index 859db7c34f87..c6156cc38940 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c @@ -28,7 +28,7 @@ #include "reg.h" /* Known PCI ids */ -static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { +static const struct pci_device_id ath5k_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 7a2b2c5caced..c018dea0b2e8 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -23,7 +23,7 @@ #include <linux/module.h> #include "ath9k.h" -static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { +static const struct pci_device_id ath_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 8596aba34f96..237d0cda1bcb 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -256,6 +256,7 @@ struct ar9170 { atomic_t rx_work_urbs; atomic_t rx_pool_urbs; kernel_ulong_t features; + bool usb_ep_cmd_is_bulk; /* firmware settings */ struct completion fw_load_wait; diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index f35c7f30f9a6..c9f93310c0d6 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -621,9 +621,16 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd, goto err_free; } - usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev, - AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4, - carl9170_usb_cmd_complete, ar, 1); + if (ar->usb_ep_cmd_is_bulk) + usb_fill_bulk_urb(urb, ar->udev, + usb_sndbulkpipe(ar->udev, AR9170_USB_EP_CMD), + cmd, cmd->hdr.len + 4, + carl9170_usb_cmd_complete, ar); + else + usb_fill_int_urb(urb, ar->udev, + usb_sndintpipe(ar->udev, AR9170_USB_EP_CMD), + cmd, cmd->hdr.len + 4, + carl9170_usb_cmd_complete, ar, 1); if (free_buf) urb->transfer_flags |= URB_FREE_BUFFER; @@ -1032,9 +1039,10 @@ static void carl9170_usb_firmware_step2(const struct firmware *fw, static int carl9170_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct usb_endpoint_descriptor *ep; struct ar9170 *ar; struct usb_device *udev; - int err; + int i, err; err = usb_reset_device(interface_to_usbdev(intf)); if (err) @@ -1050,6 +1058,21 @@ static int carl9170_usb_probe(struct usb_interface *intf, ar->intf = intf; ar->features = id->driver_info; + /* We need to remember the type of endpoint 4 because it differs + * between high- and full-speed configuration. The high-speed + * configuration specifies it as interrupt and the full-speed + * configuration as bulk endpoint. This information is required + * later when sending urbs to that endpoint. + */ + for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; ++i) { + ep = &intf->cur_altsetting->endpoint[i].desc; + + if (usb_endpoint_num(ep) == AR9170_USB_EP_CMD && + usb_endpoint_dir_out(ep) && + usb_endpoint_type(ep) == USB_ENDPOINT_XFER_BULK) + ar->usb_ep_cmd_is_bulk = true; + } + usb_set_intfdata(intf, ar); SET_IEEE80211_DEV(ar->hw, &intf->dev); diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c index 5cd97e3cbee3..bcf1f274a251 100644 --- a/drivers/net/wireless/atmel_pci.c +++ b/drivers/net/wireless/atmel_pci.c @@ -30,7 +30,7 @@ MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.") MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("Atmel at76c506 PCI wireless cards"); -static DEFINE_PCI_DEVICE_TABLE(card_ids) = { +static const struct pci_device_id card_ids[] = { { 0x1114, 0x0506, PCI_ANY_ID, PCI_ANY_ID }, { 0, } }; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index 535c7eb01b3a..8f8b9373de95 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c @@ -1318,6 +1318,8 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) msgbuf->nrof_flowrings = if_msgbuf->nrof_flowrings; msgbuf->flowring_dma_handle = kzalloc(msgbuf->nrof_flowrings * sizeof(*msgbuf->flowring_dma_handle), GFP_ATOMIC); + if (!msgbuf->flowring_dma_handle) + goto fail; msgbuf->rx_dataoffset = if_msgbuf->rx_dataoffset; msgbuf->max_rxbufpost = if_msgbuf->max_rxbufpost; @@ -1362,6 +1364,7 @@ fail: kfree(msgbuf->flow_map); kfree(msgbuf->txstatus_done_map); brcmf_msgbuf_release_pktids(msgbuf); + kfree(msgbuf->flowring_dma_handle); if (msgbuf->ioctbuf) dma_free_coherent(drvr->bus_if->dev, BRCMF_TX_IOCTL_MAX_MSG_SIZE, @@ -1391,6 +1394,7 @@ void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr) BRCMF_TX_IOCTL_MAX_MSG_SIZE, msgbuf->ioctbuf, msgbuf->ioctbuf_handle); brcmf_msgbuf_release_pktids(msgbuf); + kfree(msgbuf->flowring_dma_handle); kfree(msgbuf); drvr->proto->pd = NULL; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index bc972c0ba5f8..e5101b287e4e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c @@ -591,12 +591,13 @@ static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo) } if (dtoh_mb_data & BRCMF_D2H_DEV_DS_EXIT_NOTE) brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n"); - if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) + if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) { brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n"); if (waitqueue_active(&devinfo->mbdata_resp_wait)) { devinfo->mbdata_completed = true; wake_up(&devinfo->mbdata_resp_wait); } + } } diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 91158e2e961c..c864ef4b0015 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -39,7 +39,7 @@ struct hostap_pci_priv { /* FIX: do we need mb/wmb/rmb with memory operations? */ -static DEFINE_PCI_DEVICE_TABLE(prism2_pci_id_table) = { +static const struct pci_device_id prism2_pci_id_table[] = { /* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */ { 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID }, /* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */ diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 3bf530d9a40f..4901a99c6c59 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -60,7 +60,7 @@ struct hostap_plx_priv { #define PLXDEV(vendor,dev,str) { vendor, dev, PCI_ANY_ID, PCI_ANY_ID } -static DEFINE_PCI_DEVICE_TABLE(prism2_plx_id_table) = { +static const struct pci_device_id prism2_plx_id_table[] = { PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"), PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"), PLXDEV(0x126c, 0x8030, "Nortel emobility"), diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 1ab8e500fb77..c3d726f334e3 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6505,7 +6505,7 @@ static void ipw2100_shutdown(struct pci_dev *pci_dev) #define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x } -static DEFINE_PCI_DEVICE_TABLE(ipw2100_pci_id_table) = { +static const struct pci_device_id ipw2100_pci_id_table[] = { IPW2100_DEV_ID(0x2520), /* IN 2100A mPCI 3A */ IPW2100_DEV_ID(0x2521), /* IN 2100A mPCI 3B */ IPW2100_DEV_ID(0x2524), /* IN 2100A mPCI 3B */ diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index c5aa404069f3..a42f9c335090 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -9853,6 +9853,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, strncpy(extra, "unknown", MAX_WX_STRING); break; } + extra[MAX_WX_STRING - 1] = '\0'; IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra); @@ -11542,7 +11543,7 @@ out: } /* PCI driver stuff */ -static DEFINE_PCI_DEVICE_TABLE(card_ids) = { +static const struct pci_device_id card_ids[] = { {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2701, 0, 0, 0}, {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2702, 0, 0, 0}, {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2711, 0, 0, 0}, diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index b598e2803500..93bdf684babe 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -2728,7 +2728,7 @@ static struct il_cfg il3945_abg_cfg = { }, }; -DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = { +const struct pci_device_id il3945_hw_card_ids[] = { {IL_PCI_DEVICE(0x4222, 0x1005, il3945_bg_cfg)}, {IL_PCI_DEVICE(0x4222, 0x1034, il3945_bg_cfg)}, {IL_PCI_DEVICE(0x4222, 0x1044, il3945_bg_cfg)}, diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index c159c05db6ef..3dcbe2cd2b28 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6800,7 +6800,7 @@ il4965_txq_set_sched(struct il_priv *il, u32 mask) *****************************************************************************/ /* Hardware specific file defines the PCI IDs table for that hardware module */ -static DEFINE_PCI_DEVICE_TABLE(il4965_hw_card_ids) = { +static const struct pci_device_id il4965_hw_card_ids[] = { {IL_PCI_DEVICE(0x4229, PCI_ANY_ID, il4965_cfg)}, {IL_PCI_DEVICE(0x4230, PCI_ANY_ID, il4965_cfg)}, {0} diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 0d6a8b768a68..7c8796584c25 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -396,7 +396,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) else hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + /* TODO: enable that only for firmwares that don't crash */ + /* hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; */ hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; /* we create the 802.11 header and zero length SSID IE. */ diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 98950e45c7b0..f0e722ced080 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -78,7 +78,7 @@ .driver_data = (kernel_ulong_t)&(cfg) /* Hardware specific file defines the PCI IDs table for that hardware module */ -static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { +static const struct pci_device_id iwl_hw_card_ids[] = { #if IS_ENABLED(CONFIG_IWLDVM) {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index c16dd2cc8198..ff0545888dd0 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -257,7 +257,7 @@ static void mwifiex_pcie_shutdown(struct pci_dev *pdev) return; } -static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = { +static const struct pci_device_id mwifiex_ids[] = { { PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P, PCI_ANY_ID, PCI_ANY_ID, 0, 0, diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index fc6cb215e761..ef1104476bd8 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -5674,7 +5674,7 @@ MODULE_FIRMWARE("mwl8k/helper_8366.fw"); MODULE_FIRMWARE("mwl8k/fmimage_8366.fw"); MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); -static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { +static const struct pci_device_id mwl8k_pci_id_table[] = { { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, }, { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, }, { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, }, diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c index ffb2469eb679..1b543e30eff7 100644 --- a/drivers/net/wireless/orinoco/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco/orinoco_nortel.c @@ -272,7 +272,7 @@ static void orinoco_nortel_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } -static DEFINE_PCI_DEVICE_TABLE(orinoco_nortel_id_table) = { +static const struct pci_device_id orinoco_nortel_id_table[] = { /* Nortel emobility PCI */ {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, /* Symbol LA-4123 PCI */ diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index 5ae1191d2532..b6bdad632842 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c @@ -210,7 +210,7 @@ static void orinoco_pci_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } -static DEFINE_PCI_DEVICE_TABLE(orinoco_pci_id_table) = { +static const struct pci_device_id orinoco_pci_id_table[] = { /* Intersil Prism 3 */ {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, /* Intersil Prism 2.5 */ diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index bbd36d1676ff..b8f6e5c431ae 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c @@ -308,7 +308,7 @@ static void orinoco_plx_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } -static DEFINE_PCI_DEVICE_TABLE(orinoco_plx_id_table) = { +static const struct pci_device_id orinoco_plx_id_table[] = { {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index 04b08de5fd5d..79d0e33b625e 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c @@ -201,7 +201,7 @@ static void orinoco_tmd_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } -static DEFINE_PCI_DEVICE_TABLE(orinoco_tmd_id_table) = { +static const struct pci_device_id orinoco_tmd_id_table[] = { {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ {0,}, }; diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index d411de409050..d4aee64fb5ea 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -32,7 +32,7 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("prism54pci"); MODULE_FIRMWARE("isl3886pci"); -static DEFINE_PCI_DEVICE_TABLE(p54p_table) = { +static const struct pci_device_id p54p_table[] = { /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ { PCI_DEVICE(0x1260, 0x3890) }, /* 3COM 3CRWE154G72 Wireless LAN adapter */ diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index 1105a12dbde8..300c846ea087 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -39,7 +39,7 @@ module_param(init_pcitm, int, 0); * driver_data * If you have an update for this please contact prism54-devel@prism54.org * The latest list can be found at http://wireless.kernel.org/en/users/Drivers/p54 */ -static DEFINE_PCI_DEVICE_TABLE(prism54_id_tbl) = { +static const struct pci_device_id prism54_id_tbl[] = { /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ { 0x1260, 0x3890, diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4ccfef5094e0..bdf5590ba304 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1821,7 +1821,7 @@ static const struct rt2x00_ops rt2400pci_ops = { /* * RT2400pci module information. */ -static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = { +static const struct pci_device_id rt2400pci_device_table[] = { { PCI_DEVICE(0x1814, 0x0101) }, { 0, } }; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index a511cccc9f01..79f4fe65a119 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -2120,7 +2120,7 @@ static const struct rt2x00_ops rt2500pci_ops = { /* * RT2500pci module information. */ -static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = { +static const struct pci_device_id rt2500pci_device_table[] = { { PCI_DEVICE(0x1814, 0x0201) }, { 0, } }; diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index a5b32ca2cf0f..cc1b3cc73c5a 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -400,7 +400,7 @@ static const struct rt2x00_ops rt2800pci_ops = { /* * RT2800pci module information. */ -static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { +static const struct pci_device_id rt2800pci_device_table[] = { { PCI_DEVICE(0x1814, 0x0601) }, { PCI_DEVICE(0x1814, 0x0681) }, { PCI_DEVICE(0x1814, 0x0701) }, diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 9048a9cbe52c..819455009fe4 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -3075,7 +3075,7 @@ static const struct rt2x00_ops rt61pci_ops = { /* * RT61pci module information. */ -static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = { +static const struct pci_device_id rt61pci_device_table[] = { /* RT2561s */ { PCI_DEVICE(0x1814, 0x0301) }, /* RT2561 v2 */ diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index fcc45e5bf50a..026d912f516b 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -64,7 +64,7 @@ MODULE_AUTHOR("Andrea Merello <andrea.merello@gmail.com>"); MODULE_DESCRIPTION("RTL8180 / RTL8185 / RTL8187SE PCI wireless driver"); MODULE_LICENSE("GPL"); -static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = { +static const struct pci_device_id rtl8180_table[] = { /* rtl8187se */ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8199) }, diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c index 842d69349a37..631b6907c17d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c @@ -364,7 +364,7 @@ static struct rtl_hal_cfg rtl88ee_hal_cfg = { .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, }; -static DEFINE_PCI_DEVICE_TABLE(rtl88ee_pci_ids) = { +static const struct pci_device_id rtl88ee_pci_ids[] = { {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8179, rtl88ee_hal_cfg)}, {}, }; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 12f21f4073e8..4bbdfb2df363 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -344,7 +344,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, }; -static DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = { +static const struct pci_device_id rtl92ce_pci_ids[] = { {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)}, {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)}, {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)}, diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c index ff12bf41644b..532913c6622a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c @@ -348,7 +348,7 @@ static struct rtl_hal_cfg rtl8723be_hal_cfg = { .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, }; -static DEFINE_PCI_DEVICE_TABLE(rtl8723be_pci_id) = { +static const struct pci_device_id rtl8723be_pci_id[] = { {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xb723, rtl8723be_hal_cfg)}, {}, }; diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index ef3026f46a37..d4eb8d2e9cb7 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -165,6 +165,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */ u16 dealloc_ring[MAX_PENDING_REQS]; struct task_struct *dealloc_task; wait_queue_head_t dealloc_wq; + atomic_t inflight_packets; /* Use kthread for guest RX */ struct task_struct *task; @@ -329,4 +330,8 @@ extern unsigned int xenvif_max_queues; extern struct dentry *xen_netback_dbg_root; #endif +void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue, + struct sk_buff *skb); +void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue); + #endif /* __XEN_NETBACK__COMMON_H__ */ diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index bfd10cb9c8de..e29e15dca86e 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -43,6 +43,23 @@ #define XENVIF_QUEUE_LENGTH 32 #define XENVIF_NAPI_WEIGHT 64 +/* This function is used to set SKBTX_DEV_ZEROCOPY as well as + * increasing the inflight counter. We need to increase the inflight + * counter because core driver calls into xenvif_zerocopy_callback + * which calls xenvif_skb_zerocopy_complete. + */ +void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue, + struct sk_buff *skb) +{ + skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + atomic_inc(&queue->inflight_packets); +} + +void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue) +{ + atomic_dec(&queue->inflight_packets); +} + static inline void xenvif_stop_queue(struct xenvif_queue *queue) { struct net_device *dev = queue->vif->dev; @@ -524,9 +541,6 @@ int xenvif_init_queue(struct xenvif_queue *queue) init_timer(&queue->rx_stalled); - netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, - XENVIF_NAPI_WEIGHT); - return 0; } @@ -560,6 +574,7 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref, init_waitqueue_head(&queue->wq); init_waitqueue_head(&queue->dealloc_wq); + atomic_set(&queue->inflight_packets, 0); if (tx_evtchn == rx_evtchn) { /* feature-split-event-channels == 0 */ @@ -614,6 +629,9 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref, wake_up_process(queue->task); wake_up_process(queue->dealloc_task); + netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, + XENVIF_NAPI_WEIGHT); + return 0; err_rx_unbind: @@ -642,25 +660,6 @@ void xenvif_carrier_off(struct xenvif *vif) rtnl_unlock(); } -static void xenvif_wait_unmap_timeout(struct xenvif_queue *queue, - unsigned int worst_case_skb_lifetime) -{ - int i, unmap_timeout = 0; - - for (i = 0; i < MAX_PENDING_REQS; ++i) { - if (queue->grant_tx_handle[i] != NETBACK_INVALID_HANDLE) { - unmap_timeout++; - schedule_timeout(msecs_to_jiffies(1000)); - if (unmap_timeout > worst_case_skb_lifetime && - net_ratelimit()) - netdev_err(queue->vif->dev, - "Page still granted! Index: %x\n", - i); - i = -1; - } - } -} - void xenvif_disconnect(struct xenvif *vif) { struct xenvif_queue *queue = NULL; @@ -672,6 +671,8 @@ void xenvif_disconnect(struct xenvif *vif) for (queue_index = 0; queue_index < num_queues; ++queue_index) { queue = &vif->queues[queue_index]; + netif_napi_del(&queue->napi); + if (queue->task) { del_timer_sync(&queue->rx_stalled); kthread_stop(queue->task); @@ -704,7 +705,6 @@ void xenvif_disconnect(struct xenvif *vif) void xenvif_deinit_queue(struct xenvif_queue *queue) { free_xenballooned_pages(MAX_PENDING_REQS, queue->mmap_pages); - netif_napi_del(&queue->napi); } void xenvif_free(struct xenvif *vif) @@ -712,21 +712,11 @@ void xenvif_free(struct xenvif *vif) struct xenvif_queue *queue = NULL; unsigned int num_queues = vif->num_queues; unsigned int queue_index; - /* Here we want to avoid timeout messages if an skb can be legitimately - * stuck somewhere else. Realistically this could be an another vif's - * internal or QDisc queue. That another vif also has this - * rx_drain_timeout_msecs timeout, so give it time to drain out. - * Although if that other guest wakes up just before its timeout happens - * and takes only one skb from QDisc, it can hold onto other skbs for a - * longer period. - */ - unsigned int worst_case_skb_lifetime = (rx_drain_timeout_msecs/1000); unregister_netdev(vif->dev); for (queue_index = 0; queue_index < num_queues; ++queue_index) { queue = &vif->queues[queue_index]; - xenvif_wait_unmap_timeout(queue, worst_case_skb_lifetime); xenvif_deinit_queue(queue); } diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 4734472aa620..08f65996534c 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1525,10 +1525,12 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s /* remove traces of mapped pages and frag_list */ skb_frag_list_init(skb); uarg = skb_shinfo(skb)->destructor_arg; + /* increase inflight counter to offset decrement in callback */ + atomic_inc(&queue->inflight_packets); uarg->callback(uarg, true); skb_shinfo(skb)->destructor_arg = NULL; - skb_shinfo(nskb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + xenvif_skb_zerocopy_prepare(queue, nskb); kfree_skb(nskb); return 0; @@ -1589,7 +1591,7 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) if (net_ratelimit()) netdev_err(queue->vif->dev, "Not enough memory to consolidate frag_list!\n"); - skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + xenvif_skb_zerocopy_prepare(queue, skb); kfree_skb(skb); continue; } @@ -1609,7 +1611,7 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) "Can't setup checksum in net_tx_action\n"); /* We have to set this flag to trigger the callback */ if (skb_shinfo(skb)->destructor_arg) - skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + xenvif_skb_zerocopy_prepare(queue, skb); kfree_skb(skb); continue; } @@ -1641,7 +1643,7 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) * skb. E.g. the __pskb_pull_tail earlier can do such thing. */ if (skb_shinfo(skb)->destructor_arg) { - skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + xenvif_skb_zerocopy_prepare(queue, skb); queue->stats.tx_zerocopy_sent++; } @@ -1681,6 +1683,7 @@ void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success) queue->stats.tx_zerocopy_success++; else queue->stats.tx_zerocopy_fail++; + xenvif_skb_zerocopy_complete(queue); } static inline void xenvif_tx_dealloc_action(struct xenvif_queue *queue) @@ -2058,15 +2061,24 @@ int xenvif_kthread_guest_rx(void *data) return 0; } +static bool xenvif_dealloc_kthread_should_stop(struct xenvif_queue *queue) +{ + /* Dealloc thread must remain running until all inflight + * packets complete. + */ + return kthread_should_stop() && + !atomic_read(&queue->inflight_packets); +} + int xenvif_dealloc_kthread(void *data) { struct xenvif_queue *queue = data; - while (!kthread_should_stop()) { + for (;;) { wait_event_interruptible(queue->dealloc_wq, tx_dealloc_work_todo(queue) || - kthread_should_stop()); - if (kthread_should_stop()) + xenvif_dealloc_kthread_should_stop(queue)); + if (xenvif_dealloc_kthread_should_stop(queue)) break; xenvif_tx_dealloc_action(queue); diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 580517d857bf..9c47b897b6d2 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -116,6 +116,7 @@ static int xenvif_read_io_ring(struct seq_file *m, void *v) } #define XENVIF_KICK_STR "kick" +#define BUFFER_SIZE 32 static ssize_t xenvif_write_io_ring(struct file *filp, const char __user *buf, size_t count, @@ -124,22 +125,24 @@ xenvif_write_io_ring(struct file *filp, const char __user *buf, size_t count, struct xenvif_queue *queue = ((struct seq_file *)filp->private_data)->private; int len; - char write[sizeof(XENVIF_KICK_STR)]; + char write[BUFFER_SIZE]; /* don't allow partial writes and check the length */ if (*ppos != 0) return 0; - if (count < sizeof(XENVIF_KICK_STR) - 1) + if (count >= sizeof(write)) return -ENOSPC; len = simple_write_to_buffer(write, - sizeof(write), + sizeof(write) - 1, ppos, buf, count); if (len < 0) return len; + write[len] = '\0'; + if (!strncmp(write, XENVIF_KICK_STR, sizeof(XENVIF_KICK_STR) - 1)) xenvif_interrupt(0, (void *)queue); else { @@ -171,10 +174,9 @@ static const struct file_operations xenvif_dbg_io_ring_ops_fops = { .write = xenvif_write_io_ring, }; -static void xenvif_debugfs_addif(struct xenvif_queue *queue) +static void xenvif_debugfs_addif(struct xenvif *vif) { struct dentry *pfile; - struct xenvif *vif = queue->vif; int i; if (IS_ERR_OR_NULL(xen_netback_dbg_root)) @@ -733,10 +735,11 @@ static void connect(struct backend_info *be) be->vif->num_queues = queue_index; goto err; } + } + #ifdef CONFIG_DEBUG_FS - xenvif_debugfs_addif(queue); + xenvif_debugfs_addif(be->vif); #endif /* CONFIG_DEBUG_FS */ - } /* Initialisation completed, tell core driver the number of * active queues. diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c index 6b2b7dddbbdb..f6219d36227f 100644 --- a/drivers/pci/ioapic.c +++ b/drivers/pci/ioapic.c @@ -98,7 +98,7 @@ static void ioapic_remove(struct pci_dev *dev) } -static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = { +static const struct pci_device_id ioapic_devices[] = { { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) }, { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) }, { } diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 172f26ce59ac..3bbcbf12c1fb 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -652,6 +652,25 @@ config TOSHIBA_BT_RFKILL If you have a modern Toshiba laptop with a Bluetooth and an RFKill switch (such as the Portege R500), say Y. +config TOSHIBA_HAPS + tristate "Toshiba HDD Active Protection Sensor" + depends on ACPI + ---help--- + This driver adds support for the built-in accelerometer + found on recent Toshiba laptops equiped with HID TOS620A + device. + + This driver receives ACPI notify events 0x80 when the sensor + detects a sudden move or a harsh vibration, as well as an + ACPI notify event 0x81 whenever the movement or vibration has + been stabilized. + + Also provides sysfs entries to get/set the desired protection + level and reseting the HDD protection interface. + + If you have a recent Toshiba laptop with a built-in accelerometer + device, say Y. + config ACPI_CMPC tristate "CMPC Laptop Extras" depends on X86 && ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index c4ca428fd3db..f82232b1fc4d 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o +obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index bbf78b2d6d93..96a0b75c52c9 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -96,7 +96,7 @@ enum acer_wmi_event_ids { WMID_ACCEL_EVENT = 0x5, }; -static const struct key_entry acer_wmi_keymap[] = { +static const struct key_entry acer_wmi_keymap[] __initconst = { {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */ {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */ {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */ @@ -294,7 +294,7 @@ struct quirk_entry { static struct quirk_entry *quirks; -static void set_quirks(void) +static void __init set_quirks(void) { if (!interface) return; @@ -306,7 +306,7 @@ static void set_quirks(void) interface->capability |= ACER_CAP_BRIGHTNESS; } -static int dmi_matched(const struct dmi_system_id *dmi) +static int __init dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; return 1; @@ -337,7 +337,7 @@ static struct quirk_entry quirk_lenovo_ideapad_s205 = { }; /* The Aspire One has a dummy ACPI-WMI interface - disable it */ -static struct dmi_system_id acer_blacklist[] = { +static const struct dmi_system_id acer_blacklist[] __initconst = { { .ident = "Acer Aspire One (SSD)", .matches = { @@ -355,7 +355,7 @@ static struct dmi_system_id acer_blacklist[] = { {} }; -static struct dmi_system_id acer_quirks[] = { +static const struct dmi_system_id acer_quirks[] __initconst = { { .callback = dmi_matched, .ident = "Acer Aspire 1360", @@ -530,14 +530,15 @@ static struct dmi_system_id acer_quirks[] = { {} }; -static int video_set_backlight_video_vendor(const struct dmi_system_id *d) +static int __init +video_set_backlight_video_vendor(const struct dmi_system_id *d) { interface->capability &= ~ACER_CAP_BRIGHTNESS; pr_info("Brightness must be controlled by generic video driver\n"); return 0; } -static const struct dmi_system_id video_vendor_dmi_table[] = { +static const struct dmi_system_id video_vendor_dmi_table[] __initconst = { { .callback = video_set_backlight_video_vendor, .ident = "Acer TravelMate 4750", @@ -582,7 +583,7 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { }; /* Find which quirks are needed for a particular vendor/ model pair */ -static void find_quirks(void) +static void __init find_quirks(void) { if (!force_series) { dmi_check_system(acer_quirks); @@ -749,7 +750,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap) return wmab_execute(&args, NULL); } -static acpi_status AMW0_find_mailled(void) +static acpi_status __init AMW0_find_mailled(void) { struct wmab_args args; struct wmab_ret ret; @@ -781,16 +782,16 @@ static acpi_status AMW0_find_mailled(void) return AE_OK; } -static int AMW0_set_cap_acpi_check_device_found; +static int AMW0_set_cap_acpi_check_device_found __initdata; -static acpi_status AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, +static acpi_status __init AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, u32 level, void *context, void **retval) { AMW0_set_cap_acpi_check_device_found = 1; return AE_OK; } -static const struct acpi_device_id norfkill_ids[] = { +static const struct acpi_device_id norfkill_ids[] __initconst = { { "VPC2004", 0}, { "IBM0068", 0}, { "LEN0068", 0}, @@ -798,7 +799,7 @@ static const struct acpi_device_id norfkill_ids[] = { { "", 0}, }; -static int AMW0_set_cap_acpi_check_device(void) +static int __init AMW0_set_cap_acpi_check_device(void) { const struct acpi_device_id *id; @@ -808,7 +809,7 @@ static int AMW0_set_cap_acpi_check_device(void) return AMW0_set_cap_acpi_check_device_found; } -static acpi_status AMW0_set_capabilities(void) +static acpi_status __init AMW0_set_capabilities(void) { struct wmab_args args; struct wmab_ret ret; @@ -1184,7 +1185,7 @@ static acpi_status wmid_v2_set_u32(u32 value, u32 cap) return wmid3_set_device_status(value, device); } -static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) +static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d) { struct hotkey_function_type_aa *type_aa; @@ -1209,7 +1210,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) commun_fn_key_number = type_aa->commun_fn_key_number; } -static acpi_status WMID_set_capabilities(void) +static acpi_status __init WMID_set_capabilities(void) { struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *obj; @@ -1658,7 +1659,7 @@ static ssize_t show_bool_threeg(struct device *dev, u32 result; \ acpi_status status; - pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", + pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", current->comm); status = get_u32(&result, ACER_CAP_THREEG); if (ACPI_SUCCESS(status)) @@ -1671,7 +1672,7 @@ static ssize_t set_bool_threeg(struct device *dev, { u32 tmp = simple_strtoul(buf, NULL, 10); acpi_status status = set_u32(tmp, ACER_CAP_THREEG); - pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", + pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", current->comm); if (ACPI_FAILURE(status)) return -EINVAL; @@ -1683,7 +1684,7 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg, static ssize_t show_interface(struct device *dev, struct device_attribute *attr, char *buf) { - pr_info("This interface sysfs will be removed in 2012 - used by: %s\n", + pr_info("This interface sysfs will be removed in 2014 - used by: %s\n", current->comm); switch (interface->type) { case ACER_AMW0: @@ -1777,7 +1778,7 @@ static void acer_wmi_notify(u32 value, void *context) } } -static acpi_status +static acpi_status __init wmid3_set_lm_mode(struct lm_input_params *params, struct lm_return_value *return_value) { @@ -1811,7 +1812,7 @@ wmid3_set_lm_mode(struct lm_input_params *params, return status; } -static int acer_wmi_enable_ec_raw(void) +static int __init acer_wmi_enable_ec_raw(void) { struct lm_return_value return_value; acpi_status status; @@ -1834,7 +1835,7 @@ static int acer_wmi_enable_ec_raw(void) return status; } -static int acer_wmi_enable_lm(void) +static int __init acer_wmi_enable_lm(void) { struct lm_return_value return_value; acpi_status status; @@ -2043,6 +2044,7 @@ static int acer_platform_remove(struct platform_device *device) return 0; } +#ifdef CONFIG_PM_SLEEP static int acer_suspend(struct device *dev) { u32 value; @@ -2083,6 +2085,10 @@ static int acer_resume(struct device *dev) return 0; } +#else +#define acer_suspend NULL +#define acer_resume NULL +#endif static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume); @@ -2120,7 +2126,7 @@ static int remove_sysfs(struct platform_device *device) return 0; } -static int create_sysfs(void) +static int __init create_sysfs(void) { int retval = -ENOMEM; @@ -2149,7 +2155,7 @@ static void remove_debugfs(void) debugfs_remove(interface->debug.root); } -static int create_debugfs(void) +static int __init create_debugfs(void) { interface->debug.root = debugfs_create_dir("acer-wmi", NULL); if (!interface->debug.root) { diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 297b6640213f..c5af23b64438 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -59,25 +59,33 @@ enum WMAX_CONTROL_STATES { struct quirk_entry { u8 num_zones; + u8 hdmi_mux; }; static struct quirk_entry *quirks; static struct quirk_entry quirk_unknown = { .num_zones = 2, + .hdmi_mux = 0, }; static struct quirk_entry quirk_x51_family = { .num_zones = 3, + .hdmi_mux = 0. }; -static int dmi_matched(const struct dmi_system_id *dmi) +static struct quirk_entry quirk_asm100 = { + .num_zones = 2, + .hdmi_mux = 1, +}; + +static int __init dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; return 1; } -static struct dmi_system_id alienware_quirks[] = { +static const struct dmi_system_id alienware_quirks[] __initconst = { { .callback = dmi_matched, .ident = "Alienware X51 R1", @@ -96,6 +104,15 @@ static struct dmi_system_id alienware_quirks[] = { }, .driver_data = &quirk_x51_family, }, + { + .callback = dmi_matched, + .ident = "Alienware ASM100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), + }, + .driver_data = &quirk_asm100, + }, {} }; @@ -537,7 +554,8 @@ static struct attribute_group hdmi_attribute_group = { static void remove_hdmi(struct platform_device *dev) { - sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); + if (quirks->hdmi_mux > 0) + sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); } static int create_hdmi(struct platform_device *dev) @@ -583,7 +601,7 @@ static int __init alienware_wmi_init(void) if (ret) goto fail_platform_device2; - if (interface == WMAX) { + if (quirks->hdmi_mux > 0) { ret = create_hdmi(platform_device); if (ret) goto fail_prep_hdmi; diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index ddf0eefd862c..3a4951f46065 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -70,17 +70,35 @@ static struct quirk_entry quirk_asus_x55u = { .no_display_toggle = true, }; -static struct quirk_entry quirk_asus_x401u = { +static struct quirk_entry quirk_asus_wapf4 = { .wapf = 4, }; +static struct quirk_entry quirk_asus_x200ca = { + .wapf = 2, +}; + static int dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; return 1; } -static struct dmi_system_id asus_quirks[] = { +static const struct dmi_system_id asus_quirks[] = { + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. U32U", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "U32U"), + }, + /* + * Note this machine has a Brazos APU, and most Brazos Asus + * machines need quirk_asus_x55u / wmi_backlight_power but + * here acpi-video seems to work fine for backlight control. + */ + .driver_data = &quirk_asus_wapf4, + }, { .callback = dmi_matched, .ident = "ASUSTeK COMPUTER INC. X401U", @@ -97,7 +115,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -106,7 +124,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -124,7 +142,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -133,7 +151,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -142,7 +160,25 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X550CC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"), + }, + .driver_data = &quirk_asus_wapf4, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X550CL", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"), + }, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -151,7 +187,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -160,7 +196,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -178,7 +214,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -187,7 +223,16 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X75VBP", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"), + }, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -196,7 +241,7 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, }, { .callback = dmi_matched, @@ -205,7 +250,16 @@ static struct dmi_system_id asus_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), }, - .driver_data = &quirk_asus_x401u, + .driver_data = &quirk_asus_wapf4, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X200CA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"), + }, + .driver_data = &quirk_asus_x200ca, }, {}, }; diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 3c6ccedc82b6..21fc932da3a1 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -46,6 +46,7 @@ #include <linux/platform_device.h> #include <linux/thermal.h> #include <linux/acpi.h> +#include <linux/dmi.h> #include <acpi/video.h> #include "asus-wmi.h" @@ -554,7 +555,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } - if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) { + if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) { INIT_WORK(&asus->wlan_led_work, wlan_led_update); asus->wlan_led.name = "asus::wlan"; @@ -884,7 +885,7 @@ static int asus_new_rfkill(struct asus_wmi *asus, return -EINVAL; if ((dev_id == ASUS_WMI_DEVID_WLAN) && - (asus->driver->quirks->wapf == 4)) + (asus->driver->quirks->wapf > 0)) rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); rfkill_init_sw_state(*rfkill, !result); @@ -1270,10 +1271,7 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus) int power; max = read_brightness_max(asus); - - if (max == -ENODEV) - max = 0; - else if (max < 0) + if (max < 0) return max; power = read_backlight_power(asus); @@ -1734,6 +1732,7 @@ static int asus_wmi_add(struct platform_device *pdev) struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); struct asus_wmi *asus; + const char *chassis_type; acpi_status status; int err; u32 result; @@ -1770,6 +1769,11 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_rfkill; + /* Some Asus desktop boards export an acpi-video backlight interface, + stop this from showing up */ + chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); + if (chassis_type && !strcmp(chassis_type, "3")) + acpi_video_dmi_promote_vendor(); if (asus->driver->quirks->wmi_backlight_power) acpi_video_dmi_promote_vendor(); if (!acpi_video_backlight_support()) { diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 7297df2ebf50..26bfd7bb5c13 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -1028,7 +1028,7 @@ static int compal_probe(struct platform_device *pdev) return err; hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, - DRIVER_NAME, data, + "compal", data, compal_hwmon_groups); if (IS_ERR(hwmon_dev)) { err = PTR_ERR(hwmon_dev); diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index fed4111ac31a..233d2ee598a6 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -70,7 +70,7 @@ static struct quirk_entry quirk_dell_vostro_v130 = { .touchpad_led = 1, }; -static int dmi_matched(const struct dmi_system_id *dmi) +static int __init dmi_matched(const struct dmi_system_id *dmi) { quirks = dmi->driver_data; return 1; @@ -123,7 +123,7 @@ static const struct dmi_system_id dell_device_table[] __initconst = { }; MODULE_DEVICE_TABLE(dmi, dell_device_table); -static struct dmi_system_id dell_quirks[] = { +static const struct dmi_system_id dell_quirks[] __initconst = { { .callback = dmi_matched, .ident = "Dell Vostro V130", @@ -780,7 +780,7 @@ static struct led_classdev touchpad_led = { .flags = LED_CORE_SUSPENDRESUME, }; -static int touchpad_led_init(struct device *dev) +static int __init touchpad_led_init(struct device *dev) { return led_classdev_register(dev, &touchpad_led); } diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9b0c57cd1d4a..bd533c22be57 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1053,20 +1053,20 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf) return sprintf(buf, "%d\n", get()); } -#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \ +#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _get, _set) \ static ssize_t show_##_name(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - return show_sys_hwmon(_set, buf); \ + return show_sys_hwmon(_get, buf); \ } \ static ssize_t store_##_name(struct device *dev, \ struct device_attribute *attr, \ const char *buf, size_t count) \ { \ - return store_sys_hwmon(_get, buf, count); \ + return store_sys_hwmon(_set, buf, count); \ } \ - static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name); + static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name) EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 6112933f6278..14fd2ecb06a1 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -145,7 +145,7 @@ static int dmi_matched(const struct dmi_system_id *dmi) return 1; } -static struct dmi_system_id asus_quirks[] = { +static const struct dmi_system_id asus_quirks[] = { { .callback = dmi_matched, .ident = "ASUSTeK Computer INC. 1000H", diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index e6f336270c21..87aa28c4280f 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -129,15 +129,14 @@ #define FUJLAPTOP_DBG_INFO 0x0004 #define FUJLAPTOP_DBG_TRACE 0x0008 -#define dbg_printk(a_dbg_level, format, arg...) \ +#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG +#define vdbg_printk(a_dbg_level, format, arg...) \ do { if (dbg_level & a_dbg_level) \ printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ } while (0) -#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG -#define vdbg_printk(a_dbg_level, format, arg...) \ - dbg_printk(a_dbg_level, format, ## arg) #else -#define vdbg_printk(a_dbg_level, format, arg...) +#define vdbg_printk(a_dbg_level, format, arg...) \ + do { } while (0) #endif /* Device controlling the backlight and associated keys */ @@ -564,7 +563,7 @@ static struct platform_driver fujitsupf_driver = { } }; -static void dmi_check_cb_common(const struct dmi_system_id *id) +static void __init dmi_check_cb_common(const struct dmi_system_id *id) { pr_info("Identified laptop model '%s'\n", id->ident); if (use_alt_lcd_levels == -1) { @@ -578,7 +577,7 @@ static void dmi_check_cb_common(const struct dmi_system_id *id) } } -static int dmi_check_cb_s6410(const struct dmi_system_id *id) +static int __init dmi_check_cb_s6410(const struct dmi_system_id *id) { dmi_check_cb_common(id); fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ @@ -586,7 +585,7 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) return 1; } -static int dmi_check_cb_s6420(const struct dmi_system_id *id) +static int __init dmi_check_cb_s6420(const struct dmi_system_id *id) { dmi_check_cb_common(id); fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ @@ -594,7 +593,7 @@ static int dmi_check_cb_s6420(const struct dmi_system_id *id) return 1; } -static int dmi_check_cb_p8010(const struct dmi_system_id *id) +static int __init dmi_check_cb_p8010(const struct dmi_system_id *id) { dmi_check_cb_common(id); fujitsu->keycode1 = KEY_HELP; /* "Support" */ @@ -603,7 +602,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id) return 1; } -static struct dmi_system_id fujitsu_dmi_table[] = { +static const struct dmi_system_id fujitsu_dmi_table[] __initconst = { { .ident = "Fujitsu Siemens S6410", .matches = { diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c index c3784baceae3..53bdbb01bd3f 100644 --- a/drivers/platform/x86/fujitsu-tablet.c +++ b/drivers/platform/x86/fujitsu-tablet.c @@ -315,21 +315,21 @@ static irqreturn_t fujitsu_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void fujitsu_dmi_common(const struct dmi_system_id *dmi) +static void __init fujitsu_dmi_common(const struct dmi_system_id *dmi) { pr_info("%s\n", dmi->ident); memcpy(fujitsu.config.keymap, dmi->driver_data, sizeof(fujitsu.config.keymap)); } -static int fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) +static int __init fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) { fujitsu_dmi_common(dmi); fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; return 1; } -static int fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) +static int __init fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) { fujitsu_dmi_common(dmi); fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 484a8673b835..4c559640dcba 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -295,7 +295,7 @@ static int hp_wmi_tablet_state(void) return (state & 0x4) ? 1 : 0; } -static int hp_wmi_bios_2009_later(void) +static int __init hp_wmi_bios_2009_later(void) { int state = 0; int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, @@ -704,7 +704,7 @@ static void cleanup_sysfs(struct platform_device *device) device_remove_file(&device->dev, &dev_attr_postcode); } -static int hp_wmi_rfkill_setup(struct platform_device *device) +static int __init hp_wmi_rfkill_setup(struct platform_device *device) { int err; int wireless = 0; @@ -806,7 +806,7 @@ register_wifi_error: return err; } -static int hp_wmi_rfkill2_setup(struct platform_device *device) +static int __init hp_wmi_rfkill2_setup(struct platform_device *device) { int err, i; struct bios_rfkill2_state state; diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 3dc934438c28..13e14ec1d3d7 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -74,7 +74,7 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev, /* HP-specific accelerometer driver ------------------------------------ */ /* For automatic insertion of the module */ -static struct acpi_device_id lis3lv02d_device_ids[] = { +static const struct acpi_device_id lis3lv02d_device_ids[] = { {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ @@ -192,7 +192,7 @@ DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3); }, \ .driver_data = &lis3lv02d_axis_##_axis \ } -static struct dmi_system_id lis3lv02d_dmi_ids[] = { +static const struct dmi_system_id lis3lv02d_dmi_ids[] = { /* product names are truncated to match all kinds of a same model */ AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index b4c495a62eec..fc468a3d95ce 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -87,6 +87,8 @@ struct ideapad_private { struct backlight_device *blightdev; struct dentry *debug; unsigned long cfg; + bool has_hw_rfkill_switch; + bool has_touchpad_control; }; static bool no_bt_rfkill; @@ -439,7 +441,7 @@ static umode_t ideapad_is_visible(struct kobject *kobj, return supported ? attr->mode : 0; } -static struct attribute_group ideapad_attribute_group = { +static const struct attribute_group ideapad_attribute_group = { .is_visible = ideapad_is_visible, .attrs = ideapad_attributes }; @@ -454,7 +456,7 @@ struct ideapad_rfk_data { int type; }; -const struct ideapad_rfk_data ideapad_rfk_data[] = { +const const struct ideapad_rfk_data ideapad_rfk_data[] = { { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, @@ -473,12 +475,14 @@ static struct rfkill_ops ideapad_rfk_ops = { static void ideapad_sync_rfk_state(struct ideapad_private *priv) { - unsigned long hw_blocked; + unsigned long hw_blocked = 0; int i; - if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) - return; - hw_blocked = !hw_blocked; + if (priv->has_hw_rfkill_switch) { + if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) + return; + hw_blocked = !hw_blocked; + } for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) if (priv->rfk[i]) @@ -763,6 +767,9 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv) { unsigned long value; + if (!priv->has_touchpad_control) + return; + /* Without reading from EC touchpad LED doesn't switch state */ if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { /* Some IdeaPads don't really turn off touchpad - they only @@ -821,14 +828,39 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) } } -/* Blacklist for devices where the ideapad rfkill interface does not work */ -static struct dmi_system_id rfkill_blacklist[] = { - /* The Lenovo Yoga 2 11 always reports everything as blocked */ +/* + * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF + * always results in 0 on these models, causing ideapad_laptop to wrongly + * report all radios as hardware-blocked. + */ +static struct dmi_system_id no_hw_rfkill_list[] = { { - .ident = "Lenovo Yoga 2 11", + .ident = "Lenovo Yoga 2 11 / 13 / Pro", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), + }, + }, + {} +}; + +/* + * Some models don't offer touchpad ctrl through the ideapad interface, causing + * ideapad_sync_touchpad_state to send wrong touchpad enable/disable events. + */ +static struct dmi_system_id no_touchpad_ctrl_list[] = { + { + .ident = "Lenovo Yoga 1 series", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga"), + }, + }, + { + .ident = "Lenovo Yoga 2 11 / 13 / Pro", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), }, }, {} @@ -856,6 +888,8 @@ static int ideapad_acpi_add(struct platform_device *pdev) priv->cfg = cfg; priv->adev = adev; priv->platform_device = pdev; + priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list); + priv->has_touchpad_control = !dmi_check_system(no_touchpad_ctrl_list); ret = ideapad_sysfs_init(priv); if (ret) @@ -869,11 +903,17 @@ static int ideapad_acpi_add(struct platform_device *pdev) if (ret) goto input_failed; - if (!dmi_check_system(rfkill_blacklist)) { - for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) - if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) - ideapad_register_rfkill(priv, i); - } + /* + * On some models without a hw-switch (the yoga 2 13 at least) + * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work. + */ + if (!priv->has_hw_rfkill_switch) + write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1); + + for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) + if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) + ideapad_register_rfkill(priv, i); + ideapad_sync_rfk_state(priv); ideapad_sync_touchpad_state(priv); diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 18dcb58ba965..c0242ed13d9e 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -269,7 +269,7 @@ struct ips_mcp_limits { /* Max temps are -10 degrees C to avoid PROCHOT# */ -struct ips_mcp_limits ips_sv_limits = { +static struct ips_mcp_limits ips_sv_limits = { .mcp_power_limit = 35000, .core_power_limit = 29000, .mch_power_limit = 20000, @@ -277,7 +277,7 @@ struct ips_mcp_limits ips_sv_limits = { .mch_temp_limit = 90 }; -struct ips_mcp_limits ips_lv_limits = { +static struct ips_mcp_limits ips_lv_limits = { .mcp_power_limit = 25000, .core_power_limit = 21000, .mch_power_limit = 13000, @@ -285,7 +285,7 @@ struct ips_mcp_limits ips_lv_limits = { .mch_temp_limit = 90 }; -struct ips_mcp_limits ips_ulv_limits = { +static struct ips_mcp_limits ips_ulv_limits = { .mcp_power_limit = 18000, .core_power_limit = 14000, .mch_power_limit = 11000, @@ -1478,7 +1478,7 @@ ips_link_to_i915_driver(void) } EXPORT_SYMBOL_GPL(ips_link_to_i915_driver); -static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = { +static const struct pci_device_id ips_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), }, { 0, } diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index 76ca094ed012..66a4d3284aab 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -640,7 +640,7 @@ static void ipc_remove(struct pci_dev *pdev) intel_scu_devices_destroy(); } -static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { +static const struct pci_device_id pci_ids[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT), (kernel_ulong_t)&intel_scu_ipc_lincroft_pdata, diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 9c5a07417b2b..26ad9ff12ac5 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2389,7 +2389,7 @@ static int sony_nc_lid_resume_setup(struct platform_device *pd, lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store; } for (i = 0; i < LID_RESUME_MAX && - lid_ctl->attrs[LID_RESUME_S3].attr.name; i++) { + lid_ctl->attrs[i].attr.name; i++) { result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); if (result) goto liderror; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d82f196e3cfe..3bbc6eb60de5 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3174,7 +3174,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, /* Extra keys in use since the X240 / T440 / T540 */ - KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_COMPUTER, + KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE, }, }; @@ -6144,7 +6144,7 @@ static int brightness_set(unsigned int value) { int res; - if (value > bright_maxlvl || value < 0) + if (value > bright_maxlvl) return -EINVAL; vdbg_printk(TPACPI_DBG_BRGHT, @@ -6860,7 +6860,7 @@ static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol, return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); } -static struct snd_kcontrol_new volume_alsa_control_vol = { +static struct snd_kcontrol_new volume_alsa_control_vol __initdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Console Playback Volume", .index = 0, @@ -6869,7 +6869,7 @@ static struct snd_kcontrol_new volume_alsa_control_vol = { .get = volume_alsa_vol_get, }; -static struct snd_kcontrol_new volume_alsa_control_mute = { +static struct snd_kcontrol_new volume_alsa_control_mute __initdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Console Playback Switch", .index = 0, diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 76441dcbe5ff..e4da61bcbf8b 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -222,6 +222,12 @@ static const struct dmi_system_id toshiba_alt_keymap_dmi[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), }, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"), + }, + }, {} }; @@ -229,6 +235,7 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = { { KE_KEY, 0x157, { KEY_MUTE } }, { KE_KEY, 0x102, { KEY_ZOOMOUT } }, { KE_KEY, 0x103, { KEY_ZOOMIN } }, + { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } }, { KE_KEY, 0x139, { KEY_ZOOMRESET } }, { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, @@ -872,7 +879,9 @@ static int lcd_proc_open(struct inode *inode, struct file *file) static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) { - u32 hci_result; + u32 in[HCI_WORDS] = { HCI_SET, HCI_LCD_BRIGHTNESS, 0, 0, 0, 0 }; + u32 out[HCI_WORDS]; + acpi_status status; if (dev->tr_backlight_supported) { bool enable = !value; @@ -883,9 +892,20 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) value--; } - value = value << HCI_LCD_BRIGHTNESS_SHIFT; - hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); - return hci_result == HCI_SUCCESS ? 0 : -EIO; + in[2] = value << HCI_LCD_BRIGHTNESS_SHIFT; + status = hci_raw(dev, in, out); + if (ACPI_FAILURE(status) || out[0] == HCI_FAILURE) { + pr_err("ACPI call to set brightness failed"); + return -EIO; + } + /* Extra check for "incomplete" backlight method, where the AML code + * doesn't check for HCI_SET or HCI_GET and returns HCI_SUCCESS, + * the actual brightness, and in some cases the max brightness. + */ + if (out[2] > 0 || out[3] == 0xE000) + return -ENODEV; + + return out[0] == HCI_SUCCESS ? 0 : -EIO; } static int set_lcd_status(struct backlight_device *bd) @@ -1238,7 +1258,7 @@ static ssize_t toshiba_kbd_bl_mode_store(struct device *dev, int mode = -1; int time = -1; - if (sscanf(buf, "%i", &mode) != 1 && (mode != 2 || mode != 1)) + if (sscanf(buf, "%i", &mode) != 1 || (mode != 2 || mode != 1)) return -EINVAL; /* Set the Keyboard Backlight Mode where: diff --git a/drivers/platform/x86/toshiba_haps.c b/drivers/platform/x86/toshiba_haps.c new file mode 100644 index 000000000000..65300b6a84b9 --- /dev/null +++ b/drivers/platform/x86/toshiba_haps.c @@ -0,0 +1,265 @@ +/* + * Toshiba HDD Active Protection Sensor (HAPS) driver + * + * Copyright (C) 2014 Azael Avalos <coproscefalo@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/acpi.h> + +MODULE_AUTHOR("Azael Avalos <coproscefalo@gmail.com>"); +MODULE_DESCRIPTION("Toshiba HDD Active Protection Sensor"); +MODULE_LICENSE("GPL"); + +struct toshiba_haps_dev { + struct acpi_device *acpi_dev; + + int protection_level; +}; + +static struct toshiba_haps_dev *toshiba_haps; + +/* HAPS functions */ +static int toshiba_haps_reset_protection(acpi_handle handle) +{ + acpi_status status; + + status = acpi_evaluate_object(handle, "RSSS", NULL, NULL); + if (ACPI_FAILURE(status)) { + pr_err("Unable to reset the HDD protection\n"); + return -EIO; + } + + return 0; +} + +static int toshiba_haps_protection_level(acpi_handle handle, int level) +{ + acpi_status status; + + status = acpi_execute_simple_method(handle, "PTLV", level); + if (ACPI_FAILURE(status)) { + pr_err("Error while setting the protection level\n"); + return -EIO; + } + + pr_info("HDD protection level set to: %d\n", level); + + return 0; +} + +/* sysfs files */ +static ssize_t protection_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct toshiba_haps_dev *haps = dev_get_drvdata(dev); + + return sprintf(buf, "%i\n", haps->protection_level); +} + +static ssize_t protection_level_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct toshiba_haps_dev *haps = dev_get_drvdata(dev); + int level, ret; + + if (sscanf(buf, "%d", &level) != 1 || level < 0 || level > 3) + return -EINVAL; + + /* Set the sensor level. + * Acceptable levels are: + * 0 - Disabled | 1 - Low | 2 - Medium | 3 - High + */ + ret = toshiba_haps_protection_level(haps->acpi_dev->handle, level); + if (ret != 0) + return ret; + + haps->protection_level = level; + + return count; +} + +static ssize_t reset_protection_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct toshiba_haps_dev *haps = dev_get_drvdata(dev); + int reset, ret; + + if (sscanf(buf, "%d", &reset) != 1 || reset != 1) + return -EINVAL; + + /* Reset the protection interface */ + ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); + if (ret != 0) + return ret; + + return count; +} + +static DEVICE_ATTR(protection_level, S_IRUGO | S_IWUSR, + protection_level_show, protection_level_store); +static DEVICE_ATTR(reset_protection, S_IWUSR, NULL, reset_protection_store); + +static struct attribute *haps_attributes[] = { + &dev_attr_protection_level.attr, + &dev_attr_reset_protection.attr, + NULL, +}; + +static struct attribute_group haps_attr_group = { + .attrs = haps_attributes, +}; + +/* + * ACPI stuff + */ +static void toshiba_haps_notify(struct acpi_device *device, u32 event) +{ + pr_info("Received event: 0x%x", event); + + acpi_bus_generate_netlink_event(device->pnp.device_class, + dev_name(&device->dev), + event, 0); +} + +static int toshiba_haps_remove(struct acpi_device *device) +{ + sysfs_remove_group(&device->dev.kobj, &haps_attr_group); + + if (toshiba_haps) + toshiba_haps = NULL; + + return 0; +} + +/* Helper function */ +static int toshiba_haps_available(acpi_handle handle) +{ + acpi_status status; + u64 hdd_present; + + /* + * A non existent device as well as having (only) + * Solid State Drives can cause the call to fail. + */ + status = acpi_evaluate_integer(handle, "_STA", NULL, + &hdd_present); + if (ACPI_FAILURE(status) || !hdd_present) { + pr_info("HDD protection not available or using SSD\n"); + return 0; + } + + return 1; +} + +static int toshiba_haps_add(struct acpi_device *acpi_dev) +{ + struct toshiba_haps_dev *haps; + int ret; + + if (toshiba_haps) + return -EBUSY; + + if (!toshiba_haps_available(acpi_dev->handle)) + return -ENODEV; + + pr_info("Toshiba HDD Active Protection Sensor device\n"); + + haps = kzalloc(sizeof(struct toshiba_haps_dev), GFP_KERNEL); + if (!haps) + return -ENOMEM; + + haps->acpi_dev = acpi_dev; + haps->protection_level = 2; + acpi_dev->driver_data = haps; + dev_set_drvdata(&acpi_dev->dev, haps); + + /* Set the protection level, currently at level 2 (Medium) */ + ret = toshiba_haps_protection_level(acpi_dev->handle, 2); + if (ret != 0) + return ret; + + ret = sysfs_create_group(&acpi_dev->dev.kobj, &haps_attr_group); + if (ret) + return ret; + + toshiba_haps = haps; + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int toshiba_haps_suspend(struct device *device) +{ + struct toshiba_haps_dev *haps; + int ret; + + haps = acpi_driver_data(to_acpi_device(device)); + + /* Deactivate the protection on suspend */ + ret = toshiba_haps_protection_level(haps->acpi_dev->handle, 0); + + return ret; +} + +static int toshiba_haps_resume(struct device *device) +{ + struct toshiba_haps_dev *haps; + int ret; + + haps = acpi_driver_data(to_acpi_device(device)); + + /* Set the stored protection level */ + ret = toshiba_haps_protection_level(haps->acpi_dev->handle, + haps->protection_level); + + /* Reset the protection on resume */ + ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); + if (ret != 0) + return ret; + + return ret; +} +#endif + +static SIMPLE_DEV_PM_OPS(toshiba_haps_pm, + toshiba_haps_suspend, toshiba_haps_resume); + +static const struct acpi_device_id haps_device_ids[] = { + {"TOS620A", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, haps_device_ids); + +static struct acpi_driver toshiba_haps_driver = { + .name = "Toshiba HAPS", + .owner = THIS_MODULE, + .ids = haps_device_ids, + .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, + .ops = { + .add = toshiba_haps_add, + .remove = toshiba_haps_remove, + .notify = toshiba_haps_notify, + }, + .drv.pm = &toshiba_haps_pm, +}; + +module_acpi_driver(toshiba_haps_driver); diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 43d13295e63d..737e56d46f61 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -256,10 +256,6 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) block = &wblock->gblock; handle = wblock->handle; - if (!block) - return AE_NOT_EXIST; - - snprintf(method, 5, "WE%02X", block->notify_id); status = acpi_execute_simple_method(handle, method, enable); diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c index 90a106308c4f..255487272859 100644 --- a/drivers/ptp/ptp_pch.c +++ b/drivers/ptp/ptp_pch.c @@ -691,7 +691,7 @@ err_pci_en: return ret; } -static DEFINE_PCI_DEVICE_TABLE(pch_ieee1588_pcidev_id) = { +static const struct pci_device_id pch_ieee1588_pcidev_id[] = { { .vendor = PCI_VENDOR_ID_INTEL, .device = PCI_DEVICE_ID_PCH_1588 diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 2ca1a0b3ad57..8bcfecd66281 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -2493,7 +2493,7 @@ err_exit: return err; } -static DEFINE_PCI_DEVICE_TABLE(tsi721_pci_tbl) = { +static const struct pci_device_id tsi721_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_TSI721) }, { 0, } /* terminate list */ }; diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 972f8176665f..64c75143c89a 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -3893,7 +3893,7 @@ __setup("BusLogic=", blogic_setup); PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { } };*/ -static DEFINE_PCI_DEVICE_TABLE(blogic_pci_tbl) = { +static const struct pci_device_id blogic_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER)}, {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC)}, {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT)}, diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index eb3e3e619155..915c26b23ab6 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -539,7 +539,7 @@ static umode_t beiscsi_eth_get_attr_visibility(void *data, int type) } /*------------------- PCI Driver operations and data ----------------- */ -static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { +static const struct pci_device_id beiscsi_pci_id_table[] = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c index 1aafc331ee63..17794add855c 100644 --- a/drivers/scsi/csiostor/csio_init.c +++ b/drivers/scsi/csiostor/csio_init.c @@ -1167,7 +1167,7 @@ static struct pci_error_handlers csio_err_handler = { .resume = csio_pci_resume, }; -static DEFINE_PCI_DEVICE_TABLE(csio_pci_tbl) = { +static const struct pci_device_id csio_pci_tbl[] = { CSIO_DEVICE(CSIO_DEVID_T440DBG_FCOE, 0), /* T4 DEBUG FCOE */ CSIO_DEVICE(CSIO_DEVID_T420CR_FCOE, 0), /* T420CR FCOE */ CSIO_DEVICE(CSIO_DEVID_T422CR_FCOE, 0), /* T422CR FCOE */ diff --git a/drivers/scsi/cxgbi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig index 6bbc36fbd6ec..e4603985dce3 100644 --- a/drivers/scsi/cxgbi/cxgb3i/Kconfig +++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig @@ -1,6 +1,6 @@ config SCSI_CXGB3_ISCSI tristate "Chelsio T3 iSCSI support" - depends on PCI && INET + depends on PCI && INET && (IPV6 || IPV6=n) select NETDEVICES select ETHERNET select NET_VENDOR_CHELSIO diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig index 16b2c7d26617..8c4e423037b6 100644 --- a/drivers/scsi/cxgbi/cxgb4i/Kconfig +++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig @@ -1,6 +1,6 @@ config SCSI_CXGB4_ISCSI tristate "Chelsio T4 iSCSI support" - depends on PCI && INET + depends on PCI && INET && (IPV6 || IPV6=n) select NETDEVICES select ETHERNET select NET_VENDOR_CHELSIO diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 4198e45ea941..2e890b1e2526 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -75,7 +75,7 @@ MODULE_VERSION(DRV_VERSION); static struct scsi_transport_template *isci_transport_template; -static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { +static const struct pci_device_id isci_id_table[] = { { PCI_VDEVICE(INTEL, 0x1D61),}, { PCI_VDEVICE(INTEL, 0x1D63),}, { PCI_VDEVICE(INTEL, 0x1D65),}, diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index f9f3a1224dfa..ea025e4806b6 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2097,7 +2097,7 @@ static void iscsi_check_transport_timeouts(unsigned long data) conn->ping_timeout, conn->recv_timeout, last_recv, conn->last_ping, jiffies); spin_unlock(&session->frwd_lock); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + iscsi_conn_failure(conn, ISCSI_ERR_NOP_TIMEDOUT); return; } diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 7cf48c5c15a7..135f12c20ecf 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -247,7 +247,7 @@ struct _scsi_io_transfer { /* * The pci device ids are defined in mpi/mpi2_cnfg.h. */ -static DEFINE_PCI_DEVICE_TABLE(scsih_pci_table) = { +static const struct pci_device_id scsih_pci_table[] = { /* Fury ~ 3004 and 3008 */ { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004, PCI_ANY_ID, PCI_ANY_ID }, diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index 3e716b2f611a..3e6b866759fe 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -48,7 +48,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("jyli@marvell.com"); MODULE_DESCRIPTION("Marvell UMI Driver"); -static DEFINE_PCI_DEVICE_TABLE(mvumi_pci_table) = { +static const struct pci_device_id mvumi_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9143) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9580) }, { 0 } diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index d3a08aea0948..7abbf284da1a 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -526,18 +526,19 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) { struct pm8001_ioctl_payload *payload; DECLARE_COMPLETION_ONSTACK(completion); - u8 *ioctlbuffer = NULL; - u32 length = 0; - u32 ret = 0; + u8 *ioctlbuffer; + u32 ret; + u32 length = 1024 * 5 + sizeof(*payload) - 1; + + if (pm8001_ha->fw_image->size > 4096) { + pm8001_ha->fw_status = FAIL_FILE_SIZE; + return -EFAULT; + } - length = 1024 * 5 + sizeof(*payload) - 1; ioctlbuffer = kzalloc(length, GFP_KERNEL); - if (!ioctlbuffer) + if (!ioctlbuffer) { + pm8001_ha->fw_status = FAIL_OUT_MEMORY; return -ENOMEM; - if ((pm8001_ha->fw_image->size <= 0) || - (pm8001_ha->fw_image->size > 4096)) { - ret = FAIL_FILE_SIZE; - goto out; } payload = (struct pm8001_ioctl_payload *)ioctlbuffer; memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data, @@ -547,6 +548,10 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) payload->minor_function = 0x1; pm8001_ha->nvmd_completion = &completion; ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); + if (ret) { + pm8001_ha->fw_status = FAIL_OUT_MEMORY; + goto out; + } wait_for_completion(&completion); out: kfree(ioctlbuffer); @@ -557,35 +562,31 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) { struct pm8001_ioctl_payload *payload; DECLARE_COMPLETION_ONSTACK(completion); - u8 *ioctlbuffer = NULL; - u32 length = 0; + u8 *ioctlbuffer; struct fw_control_info *fwControl; - u32 loopNumber, loopcount = 0; - u32 sizeRead = 0; u32 partitionSize, partitionSizeTmp; - u32 ret = 0; - u32 partitionNumber = 0; + u32 loopNumber, loopcount; struct pm8001_fw_image_header *image_hdr; + u32 sizeRead = 0; + u32 ret = 0; + u32 length = 1024 * 16 + sizeof(*payload) - 1; - length = 1024 * 16 + sizeof(*payload) - 1; + if (pm8001_ha->fw_image->size < 28) { + pm8001_ha->fw_status = FAIL_FILE_SIZE; + return -EFAULT; + } ioctlbuffer = kzalloc(length, GFP_KERNEL); - image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data; - if (!ioctlbuffer) + if (!ioctlbuffer) { + pm8001_ha->fw_status = FAIL_OUT_MEMORY; return -ENOMEM; - if (pm8001_ha->fw_image->size < 28) { - ret = FAIL_FILE_SIZE; - goto out; } - + image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data; while (sizeRead < pm8001_ha->fw_image->size) { partitionSizeTmp = *(u32 *)((u8 *)&image_hdr->image_length + sizeRead); partitionSize = be32_to_cpu(partitionSizeTmp); - loopcount = (partitionSize + HEADER_LEN)/IOCTL_BUF_SIZE; - if (loopcount % IOCTL_BUF_SIZE) - loopcount++; - if (loopcount == 0) - loopcount++; + loopcount = DIV_ROUND_UP(partitionSize + HEADER_LEN, + IOCTL_BUF_SIZE); for (loopNumber = 0; loopNumber < loopcount; loopNumber++) { payload = (struct pm8001_ioctl_payload *)ioctlbuffer; payload->length = 1024*16; @@ -617,18 +618,18 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) pm8001_ha->nvmd_completion = &completion; ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload); - if (ret) - break; + if (ret) { + pm8001_ha->fw_status = FAIL_OUT_MEMORY; + goto out; + } wait_for_completion(&completion); if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) { - ret = fwControl->retcode; - break; + pm8001_ha->fw_status = fwControl->retcode; + ret = -EFAULT; + goto out; + } } } - if (ret) - break; - partitionNumber++; -} out: kfree(ioctlbuffer); return ret; @@ -643,22 +644,29 @@ static ssize_t pm8001_store_update_fw(struct device *cdev, char *cmd_ptr, *filename_ptr; int res, i; int flash_command = FLASH_CMD_NONE; - int err = 0; + int ret; + if (!capable(CAP_SYS_ADMIN)) return -EACCES; - cmd_ptr = kzalloc(count*2, GFP_KERNEL); + /* this test protects us from running two flash processes at once, + * so we should start with this test */ + if (pm8001_ha->fw_status == FLASH_IN_PROGRESS) + return -EINPROGRESS; + pm8001_ha->fw_status = FLASH_IN_PROGRESS; + cmd_ptr = kzalloc(count*2, GFP_KERNEL); if (!cmd_ptr) { - err = FAIL_OUT_MEMORY; - goto out; + pm8001_ha->fw_status = FAIL_OUT_MEMORY; + return -ENOMEM; } filename_ptr = cmd_ptr + count; res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr); if (res != 2) { - err = FAIL_PARAMETERS; - goto out1; + pm8001_ha->fw_status = FAIL_PARAMETERS; + ret = -EINVAL; + goto out; } for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) { @@ -669,50 +677,38 @@ static ssize_t pm8001_store_update_fw(struct device *cdev, } } if (flash_command == FLASH_CMD_NONE) { - err = FAIL_PARAMETERS; - goto out1; + pm8001_ha->fw_status = FAIL_PARAMETERS; + ret = -EINVAL; + goto out; } - if (pm8001_ha->fw_status == FLASH_IN_PROGRESS) { - err = FLASH_IN_PROGRESS; - goto out1; - } - err = request_firmware(&pm8001_ha->fw_image, + ret = request_firmware(&pm8001_ha->fw_image, filename_ptr, pm8001_ha->dev); - if (err) { + if (ret) { PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Failed to load firmware image file %s," - " error %d\n", filename_ptr, err)); - err = FAIL_OPEN_BIOS_FILE; - goto out1; + pm8001_printk( + "Failed to load firmware image file %s, error %d\n", + filename_ptr, ret)); + pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE; + goto out; } - switch (flash_command) { - case FLASH_CMD_UPDATE: - pm8001_ha->fw_status = FLASH_IN_PROGRESS; - err = pm8001_update_flash(pm8001_ha); - break; - case FLASH_CMD_SET_NVMD: - pm8001_ha->fw_status = FLASH_IN_PROGRESS; - err = pm8001_set_nvmd(pm8001_ha); - break; - default: - pm8001_ha->fw_status = FAIL_PARAMETERS; - err = FAIL_PARAMETERS; - break; - } + if (FLASH_CMD_UPDATE == flash_command) + ret = pm8001_update_flash(pm8001_ha); + else + ret = pm8001_set_nvmd(pm8001_ha); + release_firmware(pm8001_ha->fw_image); -out1: - kfree(cmd_ptr); out: - pm8001_ha->fw_status = err; + kfree(cmd_ptr); - if (!err) - return count; - else - return -err; + if (ret) + return ret; + + pm8001_ha->fw_status = FLASH_OK; + return count; } static ssize_t pm8001_show_update_fw(struct device *cdev, diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 173831016f5f..dd12c6fe57a6 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -4824,7 +4824,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, rc = pm8001_tag_alloc(pm8001_ha, &tag); if (rc) { kfree(fw_control_context); - return rc; + return -EBUSY; } ccb = &pm8001_ha->ccb_info[tag]; ccb->fw_control_context = fw_control_context; @@ -4946,7 +4946,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, rc = pm8001_tag_alloc(pm8001_ha, &tag); if (rc) { kfree(fw_control_context); - return rc; + return -EBUSY; } ccb = &pm8001_ha->ccb_info[tag]; ccb->fw_control_context = fw_control_context; diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e49623a897a7..666bf5af06e2 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -748,34 +748,35 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) sizeof(pm8001_ha->msix_entries[0]); for (i = 0; i < max_entry ; i++) pm8001_ha->msix_entries[i].entry = i; - rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries, + rc = pci_enable_msix_exact(pm8001_ha->pdev, pm8001_ha->msix_entries, number_of_intr); pm8001_ha->number_of_intr = number_of_intr; - if (!rc) { - PM8001_INIT_DBG(pm8001_ha, pm8001_printk( - "pci_enable_msix request ret:%d no of intr %d\n", - rc, pm8001_ha->number_of_intr)); + if (rc) + return rc; + PM8001_INIT_DBG(pm8001_ha, pm8001_printk( + "pci_enable_msix_exact request ret:%d no of intr %d\n", + rc, pm8001_ha->number_of_intr)); - for (i = 0; i < number_of_intr; i++) { - snprintf(intr_drvname[i], sizeof(intr_drvname[0]), - DRV_NAME"%d", i); - pm8001_ha->irq_vector[i].irq_id = i; - pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; + for (i = 0; i < number_of_intr; i++) { + snprintf(intr_drvname[i], sizeof(intr_drvname[0]), + DRV_NAME"%d", i); + pm8001_ha->irq_vector[i].irq_id = i; + pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; - rc = request_irq(pm8001_ha->msix_entries[i].vector, - pm8001_interrupt_handler_msix, flag, - intr_drvname[i], &(pm8001_ha->irq_vector[i])); - if (rc) { - for (j = 0; j < i; j++) - free_irq( - pm8001_ha->msix_entries[j].vector, + rc = request_irq(pm8001_ha->msix_entries[i].vector, + pm8001_interrupt_handler_msix, flag, + intr_drvname[i], &(pm8001_ha->irq_vector[i])); + if (rc) { + for (j = 0; j < i; j++) { + free_irq(pm8001_ha->msix_entries[j].vector, &(pm8001_ha->irq_vector[i])); - pci_disable_msix(pm8001_ha->pdev); - break; } + pci_disable_msix(pm8001_ha->pdev); + break; } } + return rc; } #endif diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 6f12f859b11d..4180d6d9fe78 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -334,6 +334,12 @@ void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha) /* Allocate memory for saving the template */ md_tmp = dma_alloc_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size, &md_tmp_dma, GFP_KERNEL); + if (!md_tmp) { + ql4_printk(KERN_INFO, ha, + "scsi%ld: Failed to allocate DMA memory\n", + ha->host_no); + return; + } /* Request template */ status = qla4xxx_get_minidump_template(ha, md_tmp_dma); diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index fdfae79924ac..c291fdff1b33 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1620,8 +1620,8 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, goto exit_get_chap; } - strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); - strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); + strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); + strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); exit_get_chap: @@ -1663,8 +1663,8 @@ int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password, else chap_table->flags |= BIT_7; /* local */ chap_table->secret_len = strlen(password); - strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN); - strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN); + strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN - 1); + strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN - 1); chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); if (is_qla40XX(ha)) { @@ -1742,8 +1742,8 @@ int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, goto exit_unlock_uni_chap; } - strncpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); - strncpy(username, chap_table->name, MAX_CHAP_NAME_LEN); + strlcpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); + strlcpy(username, chap_table->name, MAX_CHAP_NAME_LEN); rval = QLA_SUCCESS; @@ -2295,7 +2295,7 @@ int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param) if (param == SET_DRVR_VERSION) { mbox_cmd[1] = SET_DRVR_VERSION; strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION, - MAX_DRVR_VER_LEN); + MAX_DRVR_VER_LEN - 1); } else { ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n", __func__, param); diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 9dbdb4be2d8f..7c3365864242 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -4221,7 +4221,7 @@ qla4_8xxx_enable_msix(struct scsi_qla_host *ha) for (i = 0; i < QLA_MSIX_ENTRIES; i++) entries[i].entry = qla4_8xxx_msix_entries[i].entry; - ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries)); + ret = pci_enable_msix_exact(ha->pdev, entries, ARRAY_SIZE(entries)); if (ret) { ql4_printk(KERN_WARNING, ha, "MSI-X: Failed to enable support -- %d/%d\n", diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index c5d9564d455c..199fcf79a051 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -756,9 +756,9 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, continue; chap_rec->chap_tbl_idx = i; - strncpy(chap_rec->username, chap_table->name, + strlcpy(chap_rec->username, chap_table->name, ISCSI_CHAP_AUTH_NAME_MAX_LEN); - strncpy(chap_rec->password, chap_table->secret, + strlcpy(chap_rec->password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); chap_rec->password_length = chap_table->secret_len; @@ -1050,6 +1050,7 @@ static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len) if (!ql_iscsi_stats) { ql4_printk(KERN_ERR, ha, "Unable to allocate memory for iscsi stats\n"); + ret = -ENOMEM; goto exit_host_stats; } @@ -1058,6 +1059,7 @@ static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len) if (ret != QLA_SUCCESS) { ql4_printk(KERN_ERR, ha, "Unable to retrieve iscsi stats\n"); + ret = -EIO; goto exit_host_stats; } host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames); @@ -6027,8 +6029,8 @@ static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username, if (!(chap_table->flags & BIT_6)) /* Not BIDI */ continue; - strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); - strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); + strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); + strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); ret = 0; break; } @@ -6258,8 +6260,8 @@ static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry, tddb->tpgt = sess->tpgt; tddb->port = conn->persistent_port; - strncpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); - strncpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); + strlcpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); + strlcpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); } static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry, @@ -7764,7 +7766,7 @@ static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, goto exit_ddb_logout; } - strncpy(flash_tddb->iscsi_name, fnode_sess->targetname, + strlcpy(flash_tddb->iscsi_name, fnode_sess->targetname, ISCSI_NAME_SIZE); if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index b481e62a12cc..67d43e35693d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -3429,7 +3429,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) char *buf; if (!transport->get_host_stats) - return -EINVAL; + return -ENOSYS; priv = iscsi_if_transport_lookup(transport); if (!priv) @@ -3467,6 +3467,10 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) memset(buf, 0, host_stats_size); err = transport->get_host_stats(shost, buf, host_stats_size); + if (err) { + kfree_skb(skbhost_stats); + goto exit_host_stats; + } actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size); skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size)); diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 4e76fe863fc4..d8dcf36aed11 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1006,7 +1006,7 @@ static int port_detect \ sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue); if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) - printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", + printk("%s: wide SCSI support enabled, max_id %u, max_lun %llu.\n", BN(j), sh[j]->max_id, sh[j]->max_lun); for (i = 0; i <= sh[j]->max_channel; i++) @@ -1285,7 +1285,7 @@ static int u14_34f_queuecommand_lck(struct scsi_cmnd *SCpnt, void (*done)(struct cpp->cpp_index = i; SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index; - if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%llu.\n", + if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%u.\n", BN(j), i, SCpnt->device->channel, SCpnt->device->id, (u8)SCpnt->device->lun); diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index c007a7a69c28..afaabe2aeac8 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -185,7 +185,7 @@ static const struct dev_pm_ops ufshcd_pci_pm_ops = { .runtime_idle = ufshcd_pci_runtime_idle, }; -static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = { +static const struct pci_device_id ufshcd_pci_tbl[] = { { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { } /* terminate list */ }; diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 569e7562fa3d..42543362f163 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -892,7 +892,7 @@ static int hvfb_remove(struct hv_device *hdev) } -static DEFINE_PCI_DEVICE_TABLE(pci_stub_id_table) = { +static const struct pci_device_id pci_stub_id_table[] = { { .vendor = PCI_VENDOR_ID_MICROSOFT, .device = PCI_DEVICE_ID_HYPERV_VIDEO, diff --git a/drivers/video/fbdev/i740fb.c b/drivers/video/fbdev/i740fb.c index ca7c9df193b0..a2b4204b42bb 100644 --- a/drivers/video/fbdev/i740fb.c +++ b/drivers/video/fbdev/i740fb.c @@ -1260,7 +1260,7 @@ fail: #define I740_ID_PCI 0x00d1 #define I740_ID_AGP 0x7800 -static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = { +static const struct pci_device_id i740fb_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) }, { 0 } diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index d57a173685f3..259ba2661543 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -579,7 +579,7 @@ static void pcistub_remove(struct pci_dev *dev) } } -static DEFINE_PCI_DEVICE_TABLE(pcistub_ids) = { +static const struct pci_device_id pcistub_ids[] = { { .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, @@ -192,7 +192,6 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) } file->f_flags = O_RDWR; - file->private_data = ctx; return file; } @@ -202,7 +201,7 @@ static struct dentry *aio_mount(struct file_system_type *fs_type, static const struct dentry_operations ops = { .d_dname = simple_dname, }; - return mount_pseudo(fs_type, "aio:", NULL, &ops, 0xa10a10a1); + return mount_pseudo(fs_type, "aio:", NULL, &ops, AIO_RING_MAGIC); } /* aio_setup @@ -556,8 +555,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) struct aio_ring *ring; spin_lock(&mm->ioctx_lock); - rcu_read_lock(); - table = rcu_dereference(mm->ioctx_table); + table = rcu_dereference_raw(mm->ioctx_table); while (1) { if (table) @@ -565,7 +563,6 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) if (!table->table[i]) { ctx->id = i; table->table[i] = ctx; - rcu_read_unlock(); spin_unlock(&mm->ioctx_lock); /* While kioctx setup is in progress, @@ -579,8 +576,6 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) } new_nr = (table ? table->nr : 1) * 4; - - rcu_read_unlock(); spin_unlock(&mm->ioctx_lock); table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) * @@ -591,8 +586,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) table->nr = new_nr; spin_lock(&mm->ioctx_lock); - rcu_read_lock(); - old = rcu_dereference(mm->ioctx_table); + old = rcu_dereference_raw(mm->ioctx_table); if (!old) { rcu_assign_pointer(mm->ioctx_table, table); @@ -739,12 +733,9 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, spin_lock(&mm->ioctx_lock); - rcu_read_lock(); - table = rcu_dereference(mm->ioctx_table); - + table = rcu_dereference_raw(mm->ioctx_table); WARN_ON(ctx != table->table[ctx->id]); table->table[ctx->id] = NULL; - rcu_read_unlock(); spin_unlock(&mm->ioctx_lock); /* percpu_ref_kill() will do the necessary call_rcu() */ @@ -793,40 +784,30 @@ EXPORT_SYMBOL(wait_on_sync_kiocb); */ void exit_aio(struct mm_struct *mm) { - struct kioctx_table *table; - struct kioctx *ctx; - unsigned i = 0; - - while (1) { - rcu_read_lock(); - table = rcu_dereference(mm->ioctx_table); - - do { - if (!table || i >= table->nr) { - rcu_read_unlock(); - rcu_assign_pointer(mm->ioctx_table, NULL); - if (table) - kfree(table); - return; - } + struct kioctx_table *table = rcu_dereference_raw(mm->ioctx_table); + int i; - ctx = table->table[i++]; - } while (!ctx); + if (!table) + return; - rcu_read_unlock(); + for (i = 0; i < table->nr; ++i) { + struct kioctx *ctx = table->table[i]; + if (!ctx) + continue; /* - * We don't need to bother with munmap() here - - * exit_mmap(mm) is coming and it'll unmap everything. - * Since aio_free_ring() uses non-zero ->mmap_size - * as indicator that it needs to unmap the area, - * just set it to 0; aio_free_ring() is the only - * place that uses ->mmap_size, so it's safe. + * We don't need to bother with munmap() here - exit_mmap(mm) + * is coming and it'll unmap everything. And we simply can't, + * this is not necessarily our ->mm. + * Since kill_ioctx() uses non-zero ->mmap_size as indicator + * that it needs to unmap the area, just set it to 0. */ ctx->mmap_size = 0; - kill_ioctx(mm, ctx, NULL); } + + RCU_INIT_POINTER(mm->ioctx_table, NULL); + kfree(table); } static void put_reqs_available(struct kioctx *ctx, unsigned nr) @@ -834,10 +815,8 @@ static void put_reqs_available(struct kioctx *ctx, unsigned nr) struct kioctx_cpu *kcpu; unsigned long flags; - preempt_disable(); - kcpu = this_cpu_ptr(ctx->cpu); - local_irq_save(flags); + kcpu = this_cpu_ptr(ctx->cpu); kcpu->reqs_available += nr; while (kcpu->reqs_available >= ctx->req_batch * 2) { @@ -846,7 +825,6 @@ static void put_reqs_available(struct kioctx *ctx, unsigned nr) } local_irq_restore(flags); - preempt_enable(); } static bool get_reqs_available(struct kioctx *ctx) @@ -855,10 +833,8 @@ static bool get_reqs_available(struct kioctx *ctx) bool ret = false; unsigned long flags; - preempt_disable(); - kcpu = this_cpu_ptr(ctx->cpu); - local_irq_save(flags); + kcpu = this_cpu_ptr(ctx->cpu); if (!kcpu->reqs_available) { int old, avail = atomic_read(&ctx->reqs_available); @@ -878,7 +854,6 @@ static bool get_reqs_available(struct kioctx *ctx) kcpu->reqs_available--; out: local_irq_restore(flags); - preempt_enable(); return ret; } @@ -1047,7 +1022,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2) } EXPORT_SYMBOL(aio_complete); -/* aio_read_events +/* aio_read_events_ring * Pull an event off of the ioctx's event ring. Returns the number of * events fetched */ @@ -1270,12 +1245,12 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, if (compat) ret = compat_rw_copy_check_uvector(rw, (struct compat_iovec __user *)buf, - *nr_segs, 1, *iovec, iovec); + *nr_segs, UIO_FASTIOV, *iovec, iovec); else #endif ret = rw_copy_check_uvector(rw, (struct iovec __user *)buf, - *nr_segs, 1, *iovec, iovec); + *nr_segs, UIO_FASTIOV, *iovec, iovec); if (ret < 0) return ret; @@ -1299,9 +1274,8 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb, } /* - * aio_setup_iocb: - * Performs the initial checks and aio retry method - * setup for the kiocb at the time of io submission. + * aio_run_iocb: + * Performs the initial checks and io submission. */ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, char __user *buf, bool compat) @@ -1313,7 +1287,7 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, fmode_t mode; aio_rw_op *rw_op; rw_iter_op *iter_op; - struct iovec inline_vec, *iovec = &inline_vec; + struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; struct iov_iter iter; switch (opcode) { @@ -1348,7 +1322,7 @@ rw_common: if (!ret) ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes); if (ret < 0) { - if (iovec != &inline_vec) + if (iovec != inline_vecs) kfree(iovec); return ret; } @@ -1395,7 +1369,7 @@ rw_common: return -EINVAL; } - if (iovec != &inline_vec) + if (iovec != inline_vecs) kfree(iovec); if (ret != -EIOCBQUEUED) { diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index e25564bfcb46..54a201dac7f9 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -276,9 +276,8 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, } if (ret > 0) goto next; - ret = ulist_add_merge(parents, eb->start, - (uintptr_t)eie, - (u64 *)&old, GFP_NOFS); + ret = ulist_add_merge_ptr(parents, eb->start, + eie, (void **)&old, GFP_NOFS); if (ret < 0) break; if (!ret && extent_item_pos) { @@ -1001,16 +1000,19 @@ again: ret = -EIO; goto out; } + btrfs_tree_read_lock(eb); + btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); ret = find_extent_in_eb(eb, bytenr, *extent_item_pos, &eie); + btrfs_tree_read_unlock_blocking(eb); free_extent_buffer(eb); if (ret < 0) goto out; ref->inode_list = eie; } - ret = ulist_add_merge(refs, ref->parent, - (uintptr_t)ref->inode_list, - (u64 *)&eie, GFP_NOFS); + ret = ulist_add_merge_ptr(refs, ref->parent, + ref->inode_list, + (void **)&eie, GFP_NOFS); if (ret < 0) goto out; if (!ret && extent_item_pos) { diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 4794923c410c..43527fd78825 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -84,12 +84,6 @@ struct btrfs_inode { */ struct list_head delalloc_inodes; - /* - * list for tracking inodes that must be sent to disk before a - * rename or truncate commit - */ - struct list_head ordered_operations; - /* node for the red-black tree that links inodes in subvolume root */ struct rb_node rb_node; diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index aeab453b8e24..44ee5d2e52a4 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -280,9 +280,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, WARN_ON(btrfs_header_generation(buf) > trans->transid); if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) - ret = btrfs_inc_ref(trans, root, cow, 1, 1); + ret = btrfs_inc_ref(trans, root, cow, 1); else - ret = btrfs_inc_ref(trans, root, cow, 0, 1); + ret = btrfs_inc_ref(trans, root, cow, 0); if (ret) return ret; @@ -1035,14 +1035,14 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, if ((owner == root->root_key.objectid || root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) { - ret = btrfs_inc_ref(trans, root, buf, 1, 1); + ret = btrfs_inc_ref(trans, root, buf, 1); BUG_ON(ret); /* -ENOMEM */ if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) { - ret = btrfs_dec_ref(trans, root, buf, 0, 1); + ret = btrfs_dec_ref(trans, root, buf, 0); BUG_ON(ret); /* -ENOMEM */ - ret = btrfs_inc_ref(trans, root, cow, 1, 1); + ret = btrfs_inc_ref(trans, root, cow, 1); BUG_ON(ret); /* -ENOMEM */ } new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF; @@ -1050,9 +1050,9 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) - ret = btrfs_inc_ref(trans, root, cow, 1, 1); + ret = btrfs_inc_ref(trans, root, cow, 1); else - ret = btrfs_inc_ref(trans, root, cow, 0, 1); + ret = btrfs_inc_ref(trans, root, cow, 0); BUG_ON(ret); /* -ENOMEM */ } if (new_flags != 0) { @@ -1069,11 +1069,11 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) { if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) - ret = btrfs_inc_ref(trans, root, cow, 1, 1); + ret = btrfs_inc_ref(trans, root, cow, 1); else - ret = btrfs_inc_ref(trans, root, cow, 0, 1); + ret = btrfs_inc_ref(trans, root, cow, 0); BUG_ON(ret); /* -ENOMEM */ - ret = btrfs_dec_ref(trans, root, buf, 1, 1); + ret = btrfs_dec_ref(trans, root, buf, 1); BUG_ON(ret); /* -ENOMEM */ } clean_tree_block(trans, root, buf); diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index be91397f4e92..8e29b614fe93 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -3326,9 +3326,9 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 num_bytes, u64 min_alloc_size, u64 empty_size, u64 hint_byte, struct btrfs_key *ins, int is_data, int delalloc); int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct extent_buffer *buf, int full_backref, int no_quota); + struct extent_buffer *buf, int full_backref); int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct extent_buffer *buf, int full_backref, int no_quota); + struct extent_buffer *buf, int full_backref); int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 flags, diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 08e65e9cf2aa..d0ed9e664f7d 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -60,8 +60,6 @@ static void end_workqueue_fn(struct btrfs_work *work); static void free_fs_root(struct btrfs_root *root); static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, int read_only); -static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t, - struct btrfs_root *root); static void btrfs_destroy_ordered_extents(struct btrfs_root *root); static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, struct btrfs_root *root); @@ -3829,34 +3827,6 @@ static void btrfs_error_commit_super(struct btrfs_root *root) btrfs_cleanup_transaction(root); } -static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t, - struct btrfs_root *root) -{ - struct btrfs_inode *btrfs_inode; - struct list_head splice; - - INIT_LIST_HEAD(&splice); - - mutex_lock(&root->fs_info->ordered_operations_mutex); - spin_lock(&root->fs_info->ordered_root_lock); - - list_splice_init(&t->ordered_operations, &splice); - while (!list_empty(&splice)) { - btrfs_inode = list_entry(splice.next, struct btrfs_inode, - ordered_operations); - - list_del_init(&btrfs_inode->ordered_operations); - spin_unlock(&root->fs_info->ordered_root_lock); - - btrfs_invalidate_inodes(btrfs_inode->root); - - spin_lock(&root->fs_info->ordered_root_lock); - } - - spin_unlock(&root->fs_info->ordered_root_lock); - mutex_unlock(&root->fs_info->ordered_operations_mutex); -} - static void btrfs_destroy_ordered_extents(struct btrfs_root *root) { struct btrfs_ordered_extent *ordered; @@ -4093,8 +4063,6 @@ again: void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, struct btrfs_root *root) { - btrfs_destroy_ordered_operations(cur_trans, root); - btrfs_destroy_delayed_refs(cur_trans, root); cur_trans->state = TRANS_STATE_COMMIT_START; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 813537f362f9..102ed3143976 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3057,7 +3057,7 @@ out: static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, - int full_backref, int inc, int no_quota) + int full_backref, int inc) { u64 bytenr; u64 num_bytes; @@ -3111,7 +3111,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, key.offset -= btrfs_file_extent_offset(buf, fi); ret = process_func(trans, root, bytenr, num_bytes, parent, ref_root, key.objectid, - key.offset, no_quota); + key.offset, 1); if (ret) goto fail; } else { @@ -3119,7 +3119,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, num_bytes = btrfs_level_size(root, level - 1); ret = process_func(trans, root, bytenr, num_bytes, parent, ref_root, level - 1, 0, - no_quota); + 1); if (ret) goto fail; } @@ -3130,15 +3130,15 @@ fail: } int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct extent_buffer *buf, int full_backref, int no_quota) + struct extent_buffer *buf, int full_backref) { - return __btrfs_mod_ref(trans, root, buf, full_backref, 1, no_quota); + return __btrfs_mod_ref(trans, root, buf, full_backref, 1); } int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct extent_buffer *buf, int full_backref, int no_quota) + struct extent_buffer *buf, int full_backref) { - return __btrfs_mod_ref(trans, root, buf, full_backref, 0, no_quota); + return __btrfs_mod_ref(trans, root, buf, full_backref, 0); } static int write_one_cache_group(struct btrfs_trans_handle *trans, @@ -7478,6 +7478,220 @@ reada: wc->reada_slot = slot; } +static int account_leaf_items(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct extent_buffer *eb) +{ + int nr = btrfs_header_nritems(eb); + int i, extent_type, ret; + struct btrfs_key key; + struct btrfs_file_extent_item *fi; + u64 bytenr, num_bytes; + + for (i = 0; i < nr; i++) { + btrfs_item_key_to_cpu(eb, &key, i); + + if (key.type != BTRFS_EXTENT_DATA_KEY) + continue; + + fi = btrfs_item_ptr(eb, i, struct btrfs_file_extent_item); + /* filter out non qgroup-accountable extents */ + extent_type = btrfs_file_extent_type(eb, fi); + + if (extent_type == BTRFS_FILE_EXTENT_INLINE) + continue; + + bytenr = btrfs_file_extent_disk_bytenr(eb, fi); + if (!bytenr) + continue; + + num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi); + + ret = btrfs_qgroup_record_ref(trans, root->fs_info, + root->objectid, + bytenr, num_bytes, + BTRFS_QGROUP_OPER_SUB_SUBTREE, 0); + if (ret) + return ret; + } + return 0; +} + +/* + * Walk up the tree from the bottom, freeing leaves and any interior + * nodes which have had all slots visited. If a node (leaf or + * interior) is freed, the node above it will have it's slot + * incremented. The root node will never be freed. + * + * At the end of this function, we should have a path which has all + * slots incremented to the next position for a search. If we need to + * read a new node it will be NULL and the node above it will have the + * correct slot selected for a later read. + * + * If we increment the root nodes slot counter past the number of + * elements, 1 is returned to signal completion of the search. + */ +static int adjust_slots_upwards(struct btrfs_root *root, + struct btrfs_path *path, int root_level) +{ + int level = 0; + int nr, slot; + struct extent_buffer *eb; + + if (root_level == 0) + return 1; + + while (level <= root_level) { + eb = path->nodes[level]; + nr = btrfs_header_nritems(eb); + path->slots[level]++; + slot = path->slots[level]; + if (slot >= nr || level == 0) { + /* + * Don't free the root - we will detect this + * condition after our loop and return a + * positive value for caller to stop walking the tree. + */ + if (level != root_level) { + btrfs_tree_unlock_rw(eb, path->locks[level]); + path->locks[level] = 0; + + free_extent_buffer(eb); + path->nodes[level] = NULL; + path->slots[level] = 0; + } + } else { + /* + * We have a valid slot to walk back down + * from. Stop here so caller can process these + * new nodes. + */ + break; + } + + level++; + } + + eb = path->nodes[root_level]; + if (path->slots[root_level] >= btrfs_header_nritems(eb)) + return 1; + + return 0; +} + +/* + * root_eb is the subtree root and is locked before this function is called. + */ +static int account_shared_subtree(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct extent_buffer *root_eb, + u64 root_gen, + int root_level) +{ + int ret = 0; + int level; + struct extent_buffer *eb = root_eb; + struct btrfs_path *path = NULL; + + BUG_ON(root_level < 0 || root_level > BTRFS_MAX_LEVEL); + BUG_ON(root_eb == NULL); + + if (!root->fs_info->quota_enabled) + return 0; + + if (!extent_buffer_uptodate(root_eb)) { + ret = btrfs_read_buffer(root_eb, root_gen); + if (ret) + goto out; + } + + if (root_level == 0) { + ret = account_leaf_items(trans, root, root_eb); + goto out; + } + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + /* + * Walk down the tree. Missing extent blocks are filled in as + * we go. Metadata is accounted every time we read a new + * extent block. + * + * When we reach a leaf, we account for file extent items in it, + * walk back up the tree (adjusting slot pointers as we go) + * and restart the search process. + */ + extent_buffer_get(root_eb); /* For path */ + path->nodes[root_level] = root_eb; + path->slots[root_level] = 0; + path->locks[root_level] = 0; /* so release_path doesn't try to unlock */ +walk_down: + level = root_level; + while (level >= 0) { + if (path->nodes[level] == NULL) { + int child_bsize = root->nodesize; + int parent_slot; + u64 child_gen; + u64 child_bytenr; + + /* We need to get child blockptr/gen from + * parent before we can read it. */ + eb = path->nodes[level + 1]; + parent_slot = path->slots[level + 1]; + child_bytenr = btrfs_node_blockptr(eb, parent_slot); + child_gen = btrfs_node_ptr_generation(eb, parent_slot); + + eb = read_tree_block(root, child_bytenr, child_bsize, + child_gen); + if (!eb || !extent_buffer_uptodate(eb)) { + ret = -EIO; + goto out; + } + + path->nodes[level] = eb; + path->slots[level] = 0; + + btrfs_tree_read_lock(eb); + btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); + path->locks[level] = BTRFS_READ_LOCK_BLOCKING; + + ret = btrfs_qgroup_record_ref(trans, root->fs_info, + root->objectid, + child_bytenr, + child_bsize, + BTRFS_QGROUP_OPER_SUB_SUBTREE, + 0); + if (ret) + goto out; + + } + + if (level == 0) { + ret = account_leaf_items(trans, root, path->nodes[level]); + if (ret) + goto out; + + /* Nonzero return here means we completed our search */ + ret = adjust_slots_upwards(root, path, root_level); + if (ret) + break; + + /* Restart search with new slots */ + goto walk_down; + } + + level--; + } + + ret = 0; +out: + btrfs_free_path(path); + + return ret; +} + /* * helper to process tree block while walking down the tree. * @@ -7532,9 +7746,9 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans, /* wc->stage == UPDATE_BACKREF */ if (!(wc->flags[level] & flag)) { BUG_ON(!path->locks[level]); - ret = btrfs_inc_ref(trans, root, eb, 1, wc->for_reloc); + ret = btrfs_inc_ref(trans, root, eb, 1); BUG_ON(ret); /* -ENOMEM */ - ret = btrfs_dec_ref(trans, root, eb, 0, wc->for_reloc); + ret = btrfs_dec_ref(trans, root, eb, 0); BUG_ON(ret); /* -ENOMEM */ ret = btrfs_set_disk_extent_flags(trans, root, eb->start, eb->len, flag, @@ -7581,6 +7795,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, int level = wc->level; int reada = 0; int ret = 0; + bool need_account = false; generation = btrfs_node_ptr_generation(path->nodes[level], path->slots[level]); @@ -7626,6 +7841,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, if (wc->stage == DROP_REFERENCE) { if (wc->refs[level - 1] > 1) { + need_account = true; if (level == 1 && (wc->flags[0] & BTRFS_BLOCK_FLAG_FULL_BACKREF)) goto skip; @@ -7689,6 +7905,16 @@ skip: parent = 0; } + if (need_account) { + ret = account_shared_subtree(trans, root, next, + generation, level - 1); + if (ret) { + printk_ratelimited(KERN_ERR "BTRFS: %s Error " + "%d accounting shared subtree. Quota " + "is out of sync, rescan required.\n", + root->fs_info->sb->s_id, ret); + } + } ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent, root->root_key.objectid, level - 1, 0, 0); BUG_ON(ret); /* -ENOMEM */ @@ -7769,12 +7995,17 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, if (wc->refs[level] == 1) { if (level == 0) { if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) - ret = btrfs_dec_ref(trans, root, eb, 1, - wc->for_reloc); + ret = btrfs_dec_ref(trans, root, eb, 1); else - ret = btrfs_dec_ref(trans, root, eb, 0, - wc->for_reloc); + ret = btrfs_dec_ref(trans, root, eb, 0); BUG_ON(ret); /* -ENOMEM */ + ret = account_leaf_items(trans, root, eb); + if (ret) { + printk_ratelimited(KERN_ERR "BTRFS: %s Error " + "%d accounting leaf items. Quota " + "is out of sync, rescan required.\n", + root->fs_info->sb->s_id, ret); + } } /* make block locked assertion in clean_tree_block happy */ if (!path->locks[level] && @@ -7900,6 +8131,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int level; bool root_dropped = false; + btrfs_debug(root->fs_info, "Drop subvolume %llu", root->objectid); + path = btrfs_alloc_path(); if (!path) { err = -ENOMEM; @@ -8025,6 +8258,24 @@ int btrfs_drop_snapshot(struct btrfs_root *root, goto out_end_trans; } + /* + * Qgroup update accounting is run from + * delayed ref handling. This usually works + * out because delayed refs are normally the + * only way qgroup updates are added. However, + * we may have added updates during our tree + * walk so run qgroups here to make sure we + * don't lose any updates. + */ + ret = btrfs_delayed_qgroup_accounting(trans, + root->fs_info); + if (ret) + printk_ratelimited(KERN_ERR "BTRFS: Failure %d " + "running qgroup updates " + "during snapshot delete. " + "Quota is out of sync, " + "rescan required.\n", ret); + btrfs_end_transaction_throttle(trans, tree_root); if (!for_reloc && btrfs_need_cleaner_sleep(root)) { pr_debug("BTRFS: drop snapshot early exit\n"); @@ -8078,6 +8329,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root, } root_dropped = true; out_end_trans: + ret = btrfs_delayed_qgroup_accounting(trans, tree_root->fs_info); + if (ret) + printk_ratelimited(KERN_ERR "BTRFS: Failure %d " + "running qgroup updates " + "during snapshot delete. " + "Quota is out of sync, " + "rescan required.\n", ret); + btrfs_end_transaction_throttle(trans, tree_root); out_free: kfree(wc); diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index f46cfe45d686..54c84daec9b5 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -756,7 +756,7 @@ again: found_next = 1; if (ret != 0) goto insert; - slot = 0; + slot = path->slots[0]; } btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 1f2b99cb55ea..d3afac292d67 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1838,33 +1838,9 @@ out: int btrfs_release_file(struct inode *inode, struct file *filp) { - /* - * ordered_data_close is set by settattr when we are about to truncate - * a file from a non-zero size to a zero size. This tries to - * flush down new bytes that may have been written if the - * application were using truncate to replace a file in place. - */ - if (test_and_clear_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, - &BTRFS_I(inode)->runtime_flags)) { - struct btrfs_trans_handle *trans; - struct btrfs_root *root = BTRFS_I(inode)->root; - - /* - * We need to block on a committing transaction to keep us from - * throwing a ordered operation on to the list and causing - * something like sync to deadlock trying to flush out this - * inode. - */ - trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) - return PTR_ERR(trans); - btrfs_add_ordered_operation(trans, BTRFS_I(inode)->root, inode); - btrfs_end_transaction(trans, root); - if (inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) - filemap_flush(inode->i_mapping); - } if (filp->private_data) btrfs_ioctl_trans_end(filp); + filemap_flush(inode->i_mapping); return 0; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3183742d6f0d..03708ef3deef 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -709,6 +709,18 @@ retry: unlock_extent(io_tree, async_extent->start, async_extent->start + async_extent->ram_size - 1); + + /* + * we need to redirty the pages if we decide to + * fallback to uncompressed IO, otherwise we + * will not submit these pages down to lower + * layers. + */ + extent_range_redirty_for_io(inode, + async_extent->start, + async_extent->start + + async_extent->ram_size - 1); + goto retry; } goto out_free; @@ -7939,27 +7951,6 @@ static int btrfs_truncate(struct inode *inode) BUG_ON(ret); /* - * setattr is responsible for setting the ordered_data_close flag, - * but that is only tested during the last file release. That - * could happen well after the next commit, leaving a great big - * window where new writes may get lost if someone chooses to write - * to this file after truncating to zero - * - * The inode doesn't have any dirty data here, and so if we commit - * this is a noop. If someone immediately starts writing to the inode - * it is very likely we'll catch some of their writes in this - * transaction, and the commit will find this file on the ordered - * data list with good things to send down. - * - * This is a best effort solution, there is still a window where - * using truncate to replace the contents of the file will - * end up with a zero length file after a crash. - */ - if (inode->i_size == 0 && test_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, - &BTRFS_I(inode)->runtime_flags)) - btrfs_add_ordered_operation(trans, root, inode); - - /* * So if we truncate and then write and fsync we normally would just * write the extents that changed, which is a problem if we need to * first truncate that entire inode. So set this flag so we write out @@ -8106,7 +8097,6 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) mutex_init(&ei->delalloc_mutex); btrfs_ordered_inode_tree_init(&ei->ordered_tree); INIT_LIST_HEAD(&ei->delalloc_inodes); - INIT_LIST_HEAD(&ei->ordered_operations); RB_CLEAR_NODE(&ei->rb_node); return inode; @@ -8146,17 +8136,6 @@ void btrfs_destroy_inode(struct inode *inode) if (!root) goto free; - /* - * Make sure we're properly removed from the ordered operation - * lists. - */ - smp_mb(); - if (!list_empty(&BTRFS_I(inode)->ordered_operations)) { - spin_lock(&root->fs_info->ordered_root_lock); - list_del_init(&BTRFS_I(inode)->ordered_operations); - spin_unlock(&root->fs_info->ordered_root_lock); - } - if (test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, &BTRFS_I(inode)->runtime_flags)) { btrfs_info(root->fs_info, "inode %llu still on the orphan list", @@ -8338,12 +8317,10 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, ret = 0; /* - * we're using rename to replace one file with another. - * and the replacement file is large. Start IO on it now so - * we don't add too much work to the end of the transaction + * we're using rename to replace one file with another. Start IO on it + * now so we don't add too much work to the end of the transaction */ - if (new_inode && S_ISREG(old_inode->i_mode) && new_inode->i_size && - old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) + if (new_inode && S_ISREG(old_inode->i_mode) && new_inode->i_size) filemap_flush(old_inode->i_mapping); /* close the racy window with snapshot create/destroy ioctl */ @@ -8391,12 +8368,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, */ btrfs_pin_log_trans(root); } - /* - * make sure the inode gets flushed if it is replacing - * something. - */ - if (new_inode && new_inode->i_size && S_ISREG(old_inode->i_mode)) - btrfs_add_ordered_operation(trans, root, old_inode); inode_inc_iversion(old_dir); inode_inc_iversion(new_dir); diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 7187b14faa6c..963895c1f801 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -571,18 +571,6 @@ void btrfs_remove_ordered_extent(struct inode *inode, trace_btrfs_ordered_extent_remove(inode, entry); - /* - * we have no more ordered extents for this inode and - * no dirty pages. We can safely remove it from the - * list of ordered extents - */ - if (RB_EMPTY_ROOT(&tree->tree) && - !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY)) { - spin_lock(&root->fs_info->ordered_root_lock); - list_del_init(&BTRFS_I(inode)->ordered_operations); - spin_unlock(&root->fs_info->ordered_root_lock); - } - if (!root->nr_ordered_extents) { spin_lock(&root->fs_info->ordered_root_lock); BUG_ON(list_empty(&root->ordered_root)); @@ -687,81 +675,6 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr) } /* - * this is used during transaction commit to write all the inodes - * added to the ordered operation list. These files must be fully on - * disk before the transaction commits. - * - * we have two modes here, one is to just start the IO via filemap_flush - * and the other is to wait for all the io. When we wait, we have an - * extra check to make sure the ordered operation list really is empty - * before we return - */ -int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, - struct btrfs_root *root, int wait) -{ - struct btrfs_inode *btrfs_inode; - struct inode *inode; - struct btrfs_transaction *cur_trans = trans->transaction; - struct list_head splice; - struct list_head works; - struct btrfs_delalloc_work *work, *next; - int ret = 0; - - INIT_LIST_HEAD(&splice); - INIT_LIST_HEAD(&works); - - mutex_lock(&root->fs_info->ordered_extent_flush_mutex); - spin_lock(&root->fs_info->ordered_root_lock); - list_splice_init(&cur_trans->ordered_operations, &splice); - while (!list_empty(&splice)) { - btrfs_inode = list_entry(splice.next, struct btrfs_inode, - ordered_operations); - inode = &btrfs_inode->vfs_inode; - - list_del_init(&btrfs_inode->ordered_operations); - - /* - * the inode may be getting freed (in sys_unlink path). - */ - inode = igrab(inode); - if (!inode) - continue; - - if (!wait) - list_add_tail(&BTRFS_I(inode)->ordered_operations, - &cur_trans->ordered_operations); - spin_unlock(&root->fs_info->ordered_root_lock); - - work = btrfs_alloc_delalloc_work(inode, wait, 1); - if (!work) { - spin_lock(&root->fs_info->ordered_root_lock); - if (list_empty(&BTRFS_I(inode)->ordered_operations)) - list_add_tail(&btrfs_inode->ordered_operations, - &splice); - list_splice_tail(&splice, - &cur_trans->ordered_operations); - spin_unlock(&root->fs_info->ordered_root_lock); - ret = -ENOMEM; - goto out; - } - list_add_tail(&work->list, &works); - btrfs_queue_work(root->fs_info->flush_workers, - &work->work); - - cond_resched(); - spin_lock(&root->fs_info->ordered_root_lock); - } - spin_unlock(&root->fs_info->ordered_root_lock); -out: - list_for_each_entry_safe(work, next, &works, list) { - list_del_init(&work->list); - btrfs_wait_and_free_delalloc_work(work); - } - mutex_unlock(&root->fs_info->ordered_extent_flush_mutex); - return ret; -} - -/* * Used to start IO or wait for a given ordered extent to finish. * * If wait is one, this effectively waits on page writeback for all the pages @@ -1120,42 +1033,6 @@ out: return index; } - -/* - * add a given inode to the list of inodes that must be fully on - * disk before a transaction commit finishes. - * - * This basically gives us the ext3 style data=ordered mode, and it is mostly - * used to make sure renamed files are fully on disk. - * - * It is a noop if the inode is already fully on disk. - * - * If trans is not null, we'll do a friendly check for a transaction that - * is already flushing things and force the IO down ourselves. - */ -void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode) -{ - struct btrfs_transaction *cur_trans = trans->transaction; - u64 last_mod; - - last_mod = max(BTRFS_I(inode)->generation, BTRFS_I(inode)->last_trans); - - /* - * if this file hasn't been changed since the last transaction - * commit, we can safely return without doing anything - */ - if (last_mod <= root->fs_info->last_trans_committed) - return; - - spin_lock(&root->fs_info->ordered_root_lock); - if (list_empty(&BTRFS_I(inode)->ordered_operations)) { - list_add_tail(&BTRFS_I(inode)->ordered_operations, - &cur_trans->ordered_operations); - } - spin_unlock(&root->fs_info->ordered_root_lock); -} - int __init ordered_data_init(void) { btrfs_ordered_extent_cache = kmem_cache_create("btrfs_ordered_extent", diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 246897058efb..d81a274d621e 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h @@ -190,11 +190,6 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, struct btrfs_ordered_extent *ordered); int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, u32 *sum, int len); -int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, - struct btrfs_root *root, int wait); -void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct inode *inode); int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr); void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr); void btrfs_get_logged_extents(struct inode *inode, diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 98cb6b2630f9..b497498484be 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1201,6 +1201,50 @@ out: mutex_unlock(&fs_info->qgroup_ioctl_lock); return ret; } + +static int comp_oper_exist(struct btrfs_qgroup_operation *oper1, + struct btrfs_qgroup_operation *oper2) +{ + /* + * Ignore seq and type here, we're looking for any operation + * at all related to this extent on that root. + */ + if (oper1->bytenr < oper2->bytenr) + return -1; + if (oper1->bytenr > oper2->bytenr) + return 1; + if (oper1->ref_root < oper2->ref_root) + return -1; + if (oper1->ref_root > oper2->ref_root) + return 1; + return 0; +} + +static int qgroup_oper_exists(struct btrfs_fs_info *fs_info, + struct btrfs_qgroup_operation *oper) +{ + struct rb_node *n; + struct btrfs_qgroup_operation *cur; + int cmp; + + spin_lock(&fs_info->qgroup_op_lock); + n = fs_info->qgroup_op_tree.rb_node; + while (n) { + cur = rb_entry(n, struct btrfs_qgroup_operation, n); + cmp = comp_oper_exist(cur, oper); + if (cmp < 0) { + n = n->rb_right; + } else if (cmp) { + n = n->rb_left; + } else { + spin_unlock(&fs_info->qgroup_op_lock); + return -EEXIST; + } + } + spin_unlock(&fs_info->qgroup_op_lock); + return 0; +} + static int comp_oper(struct btrfs_qgroup_operation *oper1, struct btrfs_qgroup_operation *oper2) { @@ -1290,6 +1334,23 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans, oper->seq = atomic_inc_return(&fs_info->qgroup_op_seq); INIT_LIST_HEAD(&oper->elem.list); oper->elem.seq = 0; + + if (type == BTRFS_QGROUP_OPER_SUB_SUBTREE) { + /* + * If any operation for this bytenr/ref_root combo + * exists, then we know it's not exclusively owned and + * shouldn't be queued up. + * + * This also catches the case where we have a cloned + * extent that gets queued up multiple times during + * drop snapshot. + */ + if (qgroup_oper_exists(fs_info, oper)) { + kfree(oper); + return 0; + } + } + ret = insert_qgroup_oper(fs_info, oper); if (ret) { /* Shouldn't happen so have an assert for developers */ @@ -1884,6 +1945,111 @@ out: } /* + * Process a reference to a shared subtree. This type of operation is + * queued during snapshot removal when we encounter extents which are + * shared between more than one root. + */ +static int qgroup_subtree_accounting(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, + struct btrfs_qgroup_operation *oper) +{ + struct ulist *roots = NULL; + struct ulist_node *unode; + struct ulist_iterator uiter; + struct btrfs_qgroup_list *glist; + struct ulist *parents; + int ret = 0; + int err; + struct btrfs_qgroup *qg; + u64 root_obj = 0; + struct seq_list elem = {}; + + parents = ulist_alloc(GFP_NOFS); + if (!parents) + return -ENOMEM; + + btrfs_get_tree_mod_seq(fs_info, &elem); + ret = btrfs_find_all_roots(trans, fs_info, oper->bytenr, + elem.seq, &roots); + btrfs_put_tree_mod_seq(fs_info, &elem); + if (ret < 0) + return ret; + + if (roots->nnodes != 1) + goto out; + + ULIST_ITER_INIT(&uiter); + unode = ulist_next(roots, &uiter); /* Only want 1 so no need to loop */ + /* + * If we find our ref root then that means all refs + * this extent has to the root have not yet been + * deleted. In that case, we do nothing and let the + * last ref for this bytenr drive our update. + * + * This can happen for example if an extent is + * referenced multiple times in a snapshot (clone, + * etc). If we are in the middle of snapshot removal, + * queued updates for such an extent will find the + * root if we have not yet finished removing the + * snapshot. + */ + if (unode->val == oper->ref_root) + goto out; + + root_obj = unode->val; + BUG_ON(!root_obj); + + spin_lock(&fs_info->qgroup_lock); + qg = find_qgroup_rb(fs_info, root_obj); + if (!qg) + goto out_unlock; + + qg->excl += oper->num_bytes; + qg->excl_cmpr += oper->num_bytes; + qgroup_dirty(fs_info, qg); + + /* + * Adjust counts for parent groups. First we find all + * parents, then in the 2nd loop we do the adjustment + * while adding parents of the parents to our ulist. + */ + list_for_each_entry(glist, &qg->groups, next_group) { + err = ulist_add(parents, glist->group->qgroupid, + ptr_to_u64(glist->group), GFP_ATOMIC); + if (err < 0) { + ret = err; + goto out_unlock; + } + } + + ULIST_ITER_INIT(&uiter); + while ((unode = ulist_next(parents, &uiter))) { + qg = u64_to_ptr(unode->aux); + qg->excl += oper->num_bytes; + qg->excl_cmpr += oper->num_bytes; + qgroup_dirty(fs_info, qg); + + /* Add any parents of the parents */ + list_for_each_entry(glist, &qg->groups, next_group) { + err = ulist_add(parents, glist->group->qgroupid, + ptr_to_u64(glist->group), GFP_ATOMIC); + if (err < 0) { + ret = err; + goto out_unlock; + } + } + } + +out_unlock: + spin_unlock(&fs_info->qgroup_lock); + +out: + ulist_free(roots); + ulist_free(parents); + return ret; +} + +/* * btrfs_qgroup_account_ref is called for every ref that is added to or deleted * from the fs. First, all roots referencing the extent are searched, and * then the space is accounted accordingly to the different roots. The @@ -1920,6 +2086,9 @@ static int btrfs_qgroup_account(struct btrfs_trans_handle *trans, case BTRFS_QGROUP_OPER_SUB_SHARED: ret = qgroup_shared_accounting(trans, fs_info, oper); break; + case BTRFS_QGROUP_OPER_SUB_SUBTREE: + ret = qgroup_subtree_accounting(trans, fs_info, oper); + break; default: ASSERT(0); } diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h index 5952ff1fbd7a..18cc68ca3090 100644 --- a/fs/btrfs/qgroup.h +++ b/fs/btrfs/qgroup.h @@ -44,6 +44,7 @@ enum btrfs_qgroup_operation_type { BTRFS_QGROUP_OPER_ADD_SHARED, BTRFS_QGROUP_OPER_SUB_EXCL, BTRFS_QGROUP_OPER_SUB_SHARED, + BTRFS_QGROUP_OPER_SUB_SUBTREE, }; struct btrfs_qgroup_operation { diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 67b48b9a03e0..c4124de4435b 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1665,6 +1665,21 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) return 0; } +/* + * Calculate numbers for 'df', pessimistic in case of mixed raid profiles. + * + * If there's a redundant raid level at DATA block groups, use the respective + * multiplier to scale the sizes. + * + * Unused device space usage is based on simulating the chunk allocator + * algorithm that respects the device sizes, order of allocations and the + * 'alloc_start' value, this is a close approximation of the actual use but + * there are other factors that may change the result (like a new metadata + * chunk). + * + * FIXME: not accurate for mixed block groups, total and free/used are ok, + * available appears slightly larger. + */ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb); @@ -1675,6 +1690,8 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) u64 total_free_data = 0; int bits = dentry->d_sb->s_blocksize_bits; __be32 *fsid = (__be32 *)fs_info->fsid; + unsigned factor = 1; + struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; int ret; /* holding chunk_muext to avoid allocating new chunks */ @@ -1682,30 +1699,52 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) rcu_read_lock(); list_for_each_entry_rcu(found, head, list) { if (found->flags & BTRFS_BLOCK_GROUP_DATA) { + int i; + total_free_data += found->disk_total - found->disk_used; total_free_data -= btrfs_account_ro_block_groups_free_space(found); + + for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { + if (!list_empty(&found->block_groups[i])) { + switch (i) { + case BTRFS_RAID_DUP: + case BTRFS_RAID_RAID1: + case BTRFS_RAID_RAID10: + factor = 2; + } + } + } } total_used += found->disk_used; } + rcu_read_unlock(); - buf->f_namelen = BTRFS_NAME_LEN; - buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits; - buf->f_bfree = buf->f_blocks - (total_used >> bits); - buf->f_bsize = dentry->d_sb->s_blocksize; - buf->f_type = BTRFS_SUPER_MAGIC; + buf->f_blocks = div_u64(btrfs_super_total_bytes(disk_super), factor); + buf->f_blocks >>= bits; + buf->f_bfree = buf->f_blocks - (div_u64(total_used, factor) >> bits); + + /* Account global block reserve as used, it's in logical size already */ + spin_lock(&block_rsv->lock); + buf->f_bfree -= block_rsv->size >> bits; + spin_unlock(&block_rsv->lock); + buf->f_bavail = total_free_data; ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data); if (ret) { mutex_unlock(&fs_info->chunk_mutex); return ret; } - buf->f_bavail += total_free_data; + buf->f_bavail += div_u64(total_free_data, factor); buf->f_bavail = buf->f_bavail >> bits; mutex_unlock(&fs_info->chunk_mutex); + buf->f_type = BTRFS_SUPER_MAGIC; + buf->f_bsize = dentry->d_sb->s_blocksize; + buf->f_namelen = BTRFS_NAME_LEN; + /* We treat it as constant endianness (it doesn't matter _which_) because we want the fsid to come out the same whether mounted on a big-endian or little-endian host */ diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 5f379affdf23..d89c6d3542ca 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -218,7 +218,6 @@ loop: spin_lock_init(&cur_trans->delayed_refs.lock); INIT_LIST_HEAD(&cur_trans->pending_snapshots); - INIT_LIST_HEAD(&cur_trans->ordered_operations); INIT_LIST_HEAD(&cur_trans->pending_chunks); INIT_LIST_HEAD(&cur_trans->switch_commits); list_add_tail(&cur_trans->list, &fs_info->trans_list); @@ -1612,27 +1611,6 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, kmem_cache_free(btrfs_trans_handle_cachep, trans); } -static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans, - struct btrfs_root *root) -{ - int ret; - - ret = btrfs_run_delayed_items(trans, root); - if (ret) - return ret; - - /* - * rename don't use btrfs_join_transaction, so, once we - * set the transaction to blocked above, we aren't going - * to get any new ordered operations. We can safely run - * it here and no for sure that nothing new will be added - * to the list - */ - ret = btrfs_run_ordered_operations(trans, root, 1); - - return ret; -} - static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info) { if (btrfs_test_opt(fs_info->tree_root, FLUSHONCOMMIT)) @@ -1653,13 +1631,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct btrfs_transaction *prev_trans = NULL; int ret; - ret = btrfs_run_ordered_operations(trans, root, 0); - if (ret) { - btrfs_abort_transaction(trans, root, ret); - btrfs_end_transaction(trans, root); - return ret; - } - /* Stop the commit early if ->aborted is set */ if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { ret = cur_trans->aborted; @@ -1740,7 +1711,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, if (ret) goto cleanup_transaction; - ret = btrfs_flush_all_pending_stuffs(trans, root); + ret = btrfs_run_delayed_items(trans, root); if (ret) goto cleanup_transaction; @@ -1748,7 +1719,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, extwriter_counter_read(cur_trans) == 0); /* some pending stuffs might be added after the previous flush. */ - ret = btrfs_flush_all_pending_stuffs(trans, root); + ret = btrfs_run_delayed_items(trans, root); if (ret) goto cleanup_transaction; diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 7dd558ed0716..579be51b27e5 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h @@ -55,7 +55,6 @@ struct btrfs_transaction { wait_queue_head_t writer_wait; wait_queue_head_t commit_wait; struct list_head pending_snapshots; - struct list_head ordered_operations; struct list_head pending_chunks; struct list_head switch_commits; struct btrfs_delayed_ref_root delayed_refs; diff --git a/fs/btrfs/ulist.h b/fs/btrfs/ulist.h index 7f78cbf5cf41..4c29db604bbe 100644 --- a/fs/btrfs/ulist.h +++ b/fs/btrfs/ulist.h @@ -57,6 +57,21 @@ void ulist_free(struct ulist *ulist); int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask); int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, u64 *old_aux, gfp_t gfp_mask); + +/* just like ulist_add_merge() but take a pointer for the aux data */ +static inline int ulist_add_merge_ptr(struct ulist *ulist, u64 val, void *aux, + void **old_aux, gfp_t gfp_mask) +{ +#if BITS_PER_LONG == 32 + u64 old64 = (uintptr_t)*old_aux; + int ret = ulist_add_merge(ulist, val, (uintptr_t)aux, &old64, gfp_mask); + *old_aux = (void *)((uintptr_t)old64); + return ret; +#else + return ulist_add_merge(ulist, val, (u64)aux, (u64 *)old_aux, gfp_mask); +#endif +} + struct ulist_node *ulist_next(struct ulist *ulist, struct ulist_iterator *uiter); diff --git a/fs/locks.c b/fs/locks.c index a6f54802d277..cb66fb05ad4a 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -247,6 +247,18 @@ void locks_free_lock(struct file_lock *fl) } EXPORT_SYMBOL(locks_free_lock); +static void +locks_dispose_list(struct list_head *dispose) +{ + struct file_lock *fl; + + while (!list_empty(dispose)) { + fl = list_first_entry(dispose, struct file_lock, fl_block); + list_del_init(&fl->fl_block); + locks_free_lock(fl); + } +} + void locks_init_lock(struct file_lock *fl) { memset(fl, 0, sizeof(struct file_lock)); @@ -285,7 +297,8 @@ EXPORT_SYMBOL(__locks_copy_lock); void locks_copy_lock(struct file_lock *new, struct file_lock *fl) { - locks_release_private(new); + /* "new" must be a freshly-initialized lock */ + WARN_ON_ONCE(new->fl_ops); __locks_copy_lock(new, fl); new->fl_file = fl->fl_file; @@ -650,12 +663,16 @@ static void locks_unlink_lock(struct file_lock **thisfl_p) * * Must be called with i_lock held! */ -static void locks_delete_lock(struct file_lock **thisfl_p) +static void locks_delete_lock(struct file_lock **thisfl_p, + struct list_head *dispose) { struct file_lock *fl = *thisfl_p; locks_unlink_lock(thisfl_p); - locks_free_lock(fl); + if (dispose) + list_add(&fl->fl_block, dispose); + else + locks_free_lock(fl); } /* Determine if lock sys_fl blocks lock caller_fl. Common functionality @@ -811,6 +828,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) struct inode * inode = file_inode(filp); int error = 0; int found = 0; + LIST_HEAD(dispose); if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { new_fl = locks_alloc_lock(); @@ -833,7 +851,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) if (request->fl_type == fl->fl_type) goto out; found = 1; - locks_delete_lock(before); + locks_delete_lock(before, &dispose); break; } @@ -880,6 +898,7 @@ out: spin_unlock(&inode->i_lock); if (new_fl) locks_free_lock(new_fl); + locks_dispose_list(&dispose); return error; } @@ -893,6 +912,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str struct file_lock **before; int error; bool added = false; + LIST_HEAD(dispose); /* * We may need two file_lock structures for this operation, @@ -988,7 +1008,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str else request->fl_end = fl->fl_end; if (added) { - locks_delete_lock(before); + locks_delete_lock(before, &dispose); continue; } request = fl; @@ -1018,21 +1038,24 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str * one (This may happen several times). */ if (added) { - locks_delete_lock(before); + locks_delete_lock(before, &dispose); continue; } - /* Replace the old lock with the new one. - * Wake up anybody waiting for the old one, - * as the change in lock type might satisfy - * their needs. + /* + * Replace the old lock with new_fl, and + * remove the old one. It's safe to do the + * insert here since we know that we won't be + * using new_fl later, and that the lock is + * just replacing an existing lock. */ - locks_wake_up_blocks(fl); - fl->fl_start = request->fl_start; - fl->fl_end = request->fl_end; - fl->fl_type = request->fl_type; - locks_release_private(fl); - locks_copy_private(fl, request); - request = fl; + error = -ENOLCK; + if (!new_fl) + goto out; + locks_copy_lock(new_fl, request); + request = new_fl; + new_fl = NULL; + locks_delete_lock(before, &dispose); + locks_insert_lock(before, request); added = true; } } @@ -1093,6 +1116,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str locks_free_lock(new_fl); if (new_fl2) locks_free_lock(new_fl2); + locks_dispose_list(&dispose); return error; } @@ -1268,7 +1292,7 @@ int lease_modify(struct file_lock **before, int arg) printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); fl->fl_fasync = NULL; } - locks_delete_lock(before); + locks_delete_lock(before, NULL); } return 0; } @@ -1737,13 +1761,10 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) ret = fl; spin_lock(&inode->i_lock); error = __vfs_setlease(filp, arg, &ret); - if (error) { - spin_unlock(&inode->i_lock); - locks_free_lock(fl); - goto out_free_fasync; - } - if (ret != fl) - locks_free_lock(fl); + if (error) + goto out_unlock; + if (ret == fl) + fl = NULL; /* * fasync_insert_entry() returns the old entry if any. @@ -1755,9 +1776,10 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) new = NULL; error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); +out_unlock: spin_unlock(&inode->i_lock); - -out_free_fasync: + if (fl) + locks_free_lock(fl); if (new) fasync_free(new); return error; @@ -2320,6 +2342,7 @@ void locks_remove_file(struct file *filp) struct inode * inode = file_inode(filp); struct file_lock *fl; struct file_lock **before; + LIST_HEAD(dispose); if (!inode->i_flock) return; @@ -2365,12 +2388,13 @@ void locks_remove_file(struct file *filp) fl->fl_type, fl->fl_flags, fl->fl_start, fl->fl_end); - locks_delete_lock(before); + locks_delete_lock(before, &dispose); continue; } before = &fl->fl_next; } spin_unlock(&inode->i_lock); + locks_dispose_list(&dispose); } /** @@ -2452,7 +2476,11 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, seq_puts(f, "FLOCK ADVISORY "); } } else if (IS_LEASE(fl)) { - seq_puts(f, "LEASE "); + if (fl->fl_flags & FL_DELEG) + seq_puts(f, "DELEG "); + else + seq_puts(f, "LEASE "); + if (lease_breaking(fl)) seq_puts(f, "BREAKING "); else if (fl->fl_file) diff --git a/include/linux/edac.h b/include/linux/edac.h index 8e6c20af11a2..e1e68da6f35c 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -194,6 +194,9 @@ static inline char *mc_event_error_type(const unsigned int err_type) * @MEM_DDR3: DDR3 RAM * @MEM_RDDR3: Registered DDR3 RAM * This is a variant of the DDR3 memories. + * @MEM_DDR4: DDR4 RAM + * @MEM_RDDR4: Registered DDR4 RAM + * This is a variant of the DDR4 memories. */ enum mem_type { MEM_EMPTY = 0, @@ -213,6 +216,8 @@ enum mem_type { MEM_XDR, MEM_DDR3, MEM_RDDR3, + MEM_DDR4, + MEM_RDDR4, }; #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h index 1b1dfa80d9ff..f583ff639776 100644 --- a/include/linux/input/mt.h +++ b/include/linux/input/mt.h @@ -105,6 +105,7 @@ void input_mt_report_slot_state(struct input_dev *dev, void input_mt_report_finger_count(struct input_dev *dev, int count); void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count); +void input_mt_drop_unused(struct input_dev *dev); void input_mt_sync_frame(struct input_dev *dev); diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index 9cda293c867d..36826c0166c5 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h @@ -21,7 +21,7 @@ #include <linux/rculist.h> struct rhash_head { - struct rhash_head *next; + struct rhash_head __rcu *next; }; #define INIT_HASH_HEAD(ptr) ((ptr)->next = NULL) @@ -97,7 +97,7 @@ u32 rhashtable_obj_hashfn(const struct rhashtable *ht, void *ptr); void rhashtable_insert(struct rhashtable *ht, struct rhash_head *node, gfp_t); bool rhashtable_remove(struct rhashtable *ht, struct rhash_head *node, gfp_t); void rhashtable_remove_pprev(struct rhashtable *ht, struct rhash_head *obj, - struct rhash_head **pprev, gfp_t flags); + struct rhash_head __rcu **pprev, gfp_t flags); bool rht_grow_above_75(const struct rhashtable *ht, size_t new_size); bool rht_shrink_below_30(const struct rhashtable *ht, size_t new_size); @@ -117,18 +117,12 @@ void rhashtable_destroy(const struct rhashtable *ht); #define rht_dereference_rcu(p, ht) \ rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht)) -/* Internal, use rht_obj() instead */ #define rht_entry(ptr, type, member) container_of(ptr, type, member) #define rht_entry_safe(ptr, type, member) \ ({ \ typeof(ptr) __ptr = (ptr); \ __ptr ? rht_entry(__ptr, type, member) : NULL; \ }) -#define rht_entry_safe_rcu(ptr, type, member) \ -({ \ - typeof(*ptr) __rcu *__ptr = (typeof(*ptr) __rcu __force *)ptr; \ - __ptr ? container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member) : NULL; \ -}) #define rht_next_entry_safe(pos, ht, member) \ ({ \ @@ -205,9 +199,10 @@ void rhashtable_destroy(const struct rhashtable *ht); * traversal is guarded by rcu_read_lock(). */ #define rht_for_each_entry_rcu(pos, head, member) \ - for (pos = rht_entry_safe_rcu(head, typeof(*(pos)), member); \ + for (pos = rht_entry_safe(rcu_dereference_raw(head), \ + typeof(*(pos)), member); \ pos; \ - pos = rht_entry_safe_rcu((pos)->member.next, \ - typeof(*(pos)), member)) + pos = rht_entry_safe(rcu_dereference_raw((pos)->member.next), \ + typeof(*(pos)), member)) #endif /* _LINUX_RHASHTABLE_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 857ba40426ba..5c2c885ee52b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -169,8 +169,7 @@ extern int nr_processes(void); extern unsigned long nr_running(void); extern unsigned long nr_iowait(void); extern unsigned long nr_iowait_cpu(int cpu); -extern unsigned long this_cpu_load(void); - +extern void get_iowait_load(unsigned long *nr_waiters, unsigned long *load); extern void calc_global_load(unsigned long ticks); extern void update_cpu_load_nohz(void); diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 7a4313887568..5fbe6568c3cf 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -62,6 +62,7 @@ struct inet_connection_sock_af_ops { void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); int (*bind_conflict)(const struct sock *sk, const struct inet_bind_bucket *tb, bool relax); + void (*mtu_reduced)(struct sock *sk); }; /** inet_connection_sock - INET connection oriented sock diff --git a/include/net/sock.h b/include/net/sock.h index 38805fa02e48..7f2ab72f321a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -987,7 +987,6 @@ struct proto { struct sk_buff *skb); void (*release_cb)(struct sock *sk); - void (*mtu_reduced)(struct sock *sk); /* Keeping track of sk's, looking them up, and port selection methods. */ void (*hash)(struct sock *sk); diff --git a/include/net/tcp.h b/include/net/tcp.h index dafa1cbc149b..590e01a476ac 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -417,7 +417,7 @@ void tcp_update_metrics(struct sock *sk); void tcp_init_metrics(struct sock *sk); void tcp_metrics_init(void); bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, - bool paws_check); + bool paws_check, bool timestamps); bool tcp_remember_stamp(struct sock *sk); bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw); void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst); @@ -448,6 +448,7 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); */ void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); +void tcp_v4_mtu_reduced(struct sock *sk); int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb); struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, @@ -705,8 +706,10 @@ struct tcp_skb_cb { #define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */ #define TCPCB_LOST 0x04 /* SKB is lost */ #define TCPCB_TAGBITS 0x07 /* All tag bits */ +#define TCPCB_REPAIRED 0x10 /* SKB repaired (no skb_mstamp) */ #define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */ -#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS) +#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS| \ + TCPCB_REPAIRED) __u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */ /* 1 byte hole */ diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index fd0421c6d40a..95ed9424a11a 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -527,6 +527,7 @@ enum iscsi_err { ISCSI_ERR_XMIT_FAILED = ISCSI_ERR_BASE + 19, ISCSI_ERR_TCP_CONN_CLOSE = ISCSI_ERR_BASE + 20, ISCSI_ERR_SCSI_EH_SESSION_RST = ISCSI_ERR_BASE + 21, + ISCSI_ERR_NOP_TIMEDOUT = ISCSI_ERR_BASE + 22, }; /* diff --git a/kernel/module.c b/kernel/module.c index 6f69463f0066..03214bd288e9 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3304,6 +3304,11 @@ static int load_module(struct load_info *info, const char __user *uargs, mutex_lock(&module_mutex); module_bug_cleanup(mod); mutex_unlock(&module_mutex); + + /* we can't deallocate the module until we clear memory protection */ + unset_module_init_ro_nx(mod); + unset_module_core_ro_nx(mod); + ddebug_cleanup: dynamic_debug_remove(info->debug); synchronize_sched(); diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 4fc5c32422b3..c4b8093c80b3 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -954,6 +954,25 @@ static void mark_nosave_pages(struct memory_bitmap *bm) } } +static bool is_nosave_page(unsigned long pfn) +{ + struct nosave_region *region; + + list_for_each_entry(region, &nosave_regions, list) { + if (pfn >= region->start_pfn && pfn < region->end_pfn) { + pr_err("PM: %#010llx in e820 nosave region: " + "[mem %#010llx-%#010llx]\n", + (unsigned long long) pfn << PAGE_SHIFT, + (unsigned long long) region->start_pfn << PAGE_SHIFT, + ((unsigned long long) region->end_pfn << PAGE_SHIFT) + - 1); + return true; + } + } + + return false; +} + /** * create_basic_memory_bitmaps - create bitmaps needed for marking page * frames that should not be saved and free page frames. The pointers @@ -2015,7 +2034,7 @@ static int mark_unsafe_pages(struct memory_bitmap *bm) do { pfn = memory_bm_next_pfn(bm); if (likely(pfn != BM_END_OF_MAP)) { - if (likely(pfn_valid(pfn))) + if (likely(pfn_valid(pfn)) && !is_nosave_page(pfn)) swsusp_set_page_free(pfn_to_page(pfn)); else return -EFAULT; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1211575a2208..ec1a286684a5 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2393,6 +2393,13 @@ unsigned long nr_iowait_cpu(int cpu) return atomic_read(&this->nr_iowait); } +void get_iowait_load(unsigned long *nr_waiters, unsigned long *load) +{ + struct rq *this = this_rq(); + *nr_waiters = atomic_read(&this->nr_iowait); + *load = this->cpu_load[0]; +} + #ifdef CONFIG_SMP /* diff --git a/kernel/sched/proc.c b/kernel/sched/proc.c index 16f5a30f9c88..8ecd552fe4f2 100644 --- a/kernel/sched/proc.c +++ b/kernel/sched/proc.c @@ -8,13 +8,6 @@ #include "sched.h" -unsigned long this_cpu_load(void) -{ - struct rq *this = this_rq(); - return this->cpu_load[0]; -} - - /* * Global load-average calculations * diff --git a/lib/rhashtable.c b/lib/rhashtable.c index e6940cf16628..a2c78810ebc1 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -38,16 +38,10 @@ int lockdep_rht_mutex_is_held(const struct rhashtable *ht) EXPORT_SYMBOL_GPL(lockdep_rht_mutex_is_held); #endif -/** - * rht_obj - cast hash head to outer object - * @ht: hash table - * @he: hashed node - */ -void *rht_obj(const struct rhashtable *ht, const struct rhash_head *he) +static void *rht_obj(const struct rhashtable *ht, const struct rhash_head *he) { return (void *) he - ht->p.head_offset; } -EXPORT_SYMBOL_GPL(rht_obj); static u32 __hashfn(const struct rhashtable *ht, const void *key, u32 len, u32 hsize) @@ -386,7 +380,7 @@ EXPORT_SYMBOL_GPL(rhashtable_insert); * deletion when combined with walking or lookup. */ void rhashtable_remove_pprev(struct rhashtable *ht, struct rhash_head *obj, - struct rhash_head **pprev, gfp_t flags) + struct rhash_head __rcu **pprev, gfp_t flags) { struct bucket_table *tbl = rht_dereference(ht->tbl, ht); diff --git a/net/atm/lec.c b/net/atm/lec.c index 4c5b8ba0f84f..e4853b50cf40 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -833,7 +833,6 @@ static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl, loff_t *l) { struct hlist_node *e = state->node; - struct lec_arp_table *tmp; if (!e) e = tbl->first; @@ -842,9 +841,7 @@ static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl, --*l; } - tmp = container_of(e, struct lec_arp_table, next); - - hlist_for_each_entry_from(tmp, next) { + for (; e; e = e->next) { if (--*l < 0) break; } diff --git a/net/atm/svc.c b/net/atm/svc.c index d8e5d0c2ebbc..1ba23f5018e7 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -50,12 +50,12 @@ static void svc_disconnect(struct atm_vcc *vcc) pr_debug("%p\n", vcc); if (test_bit(ATM_VF_REGIS, &vcc->flags)) { - prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); sigd_enq(vcc, as_close, NULL, NULL, NULL); - while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { + for (;;) { + prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); + if (test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd) + break; schedule(); - prepare_to_wait(sk_sleep(sk), &wait, - TASK_UNINTERRUPTIBLE); } finish_wait(sk_sleep(sk), &wait); } @@ -126,11 +126,12 @@ static int svc_bind(struct socket *sock, struct sockaddr *sockaddr, } vcc->local = *addr; set_bit(ATM_VF_WAITING, &vcc->flags); - prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); - while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { - schedule(); + for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); + if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) + break; + schedule(); } finish_wait(sk_sleep(sk), &wait); clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ @@ -202,15 +203,14 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, } vcc->remote = *addr; set_bit(ATM_VF_WAITING, &vcc->flags); - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); if (flags & O_NONBLOCK) { - finish_wait(sk_sleep(sk), &wait); sock->state = SS_CONNECTING; error = -EINPROGRESS; goto out; } error = 0; + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { schedule(); if (!signal_pending(current)) { @@ -297,11 +297,12 @@ static int svc_listen(struct socket *sock, int backlog) goto out; } set_bit(ATM_VF_WAITING, &vcc->flags); - prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); - while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { - schedule(); + for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); + if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) + break; + schedule(); } finish_wait(sk_sleep(sk), &wait); if (!sigd) { @@ -387,15 +388,15 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags) } /* wait should be short, so we ignore the non-blocking flag */ set_bit(ATM_VF_WAITING, &new_vcc->flags); - prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, - TASK_UNINTERRUPTIBLE); sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); - while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) { + for (;;) { + prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, + TASK_UNINTERRUPTIBLE); + if (!test_bit(ATM_VF_WAITING, &new_vcc->flags) || !sigd) + break; release_sock(sk); schedule(); lock_sock(sk); - prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, - TASK_UNINTERRUPTIBLE); } finish_wait(sk_sleep(sk_atm(new_vcc)), &wait); if (!sigd) { @@ -433,12 +434,14 @@ int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) DEFINE_WAIT(wait); set_bit(ATM_VF_WAITING, &vcc->flags); - prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); - while (test_bit(ATM_VF_WAITING, &vcc->flags) && - !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { - schedule(); + for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); + if (!test_bit(ATM_VF_WAITING, &vcc->flags) || + test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd) { + break; + } + schedule(); } finish_wait(sk_sleep(sk), &wait); if (!sigd) @@ -529,18 +532,18 @@ static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, lock_sock(sk); set_bit(ATM_VF_WAITING, &vcc->flags); - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); sigd_enq(vcc, as_addparty, NULL, NULL, (struct sockaddr_atmsvc *) sockaddr); if (flags & O_NONBLOCK) { - finish_wait(sk_sleep(sk), &wait); error = -EINPROGRESS; goto out; } pr_debug("added wait queue\n"); - while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { - schedule(); + for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) + break; + schedule(); } finish_wait(sk_sleep(sk), &wait); error = xchg(&sk->sk_err_soft, 0); @@ -558,11 +561,12 @@ static int svc_dropparty(struct socket *sock, int ep_ref) lock_sock(sk); set_bit(ATM_VF_WAITING, &vcc->flags); - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref); - while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { - schedule(); + for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) + break; + schedule(); } finish_wait(sk_sleep(sk), &wait); if (!sigd) { diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 181b70ebd964..541f26a67ba2 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1188,13 +1188,6 @@ new_segment: goto wait_for_memory; /* - * All packets are restored as if they have - * already been sent. - */ - if (tp->repair) - TCP_SKB_CB(skb)->when = tcp_time_stamp; - - /* * Check whether we can use HW checksum. */ if (sk->sk_route_caps & NETIF_F_ALL_CSUM) @@ -1203,6 +1196,13 @@ new_segment: skb_entail(sk, skb); copy = size_goal; max = size_goal; + + /* All packets are restored as if they have + * already been sent. skb_mstamp isn't set to + * avoid wrong rtt estimation. + */ + if (tp->repair) + TCP_SKB_CB(skb)->sacked |= TCPCB_REPAIRED; } /* Try to append data to the end of skb. */ diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a3d47af01906..a906e0200ff2 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2687,7 +2687,6 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) */ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) { - struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); bool recovered = !before(tp->snd_una, tp->high_seq); @@ -2713,12 +2712,9 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) if (recovered) { /* F-RTO RFC5682 sec 3.1 step 2.a and 1st part of step 3.a */ - icsk->icsk_retransmits = 0; tcp_try_undo_recovery(sk); return; } - if (flag & FLAG_DATA_ACKED) - icsk->icsk_retransmits = 0; if (tcp_is_reno(tp)) { /* A Reno DUPACK means new data in F-RTO step 2.b above are * delivered. Lower inflight to clock out (re)tranmissions. @@ -3050,10 +3046,15 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, first_ackt.v64 = 0; while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { + struct skb_shared_info *shinfo = skb_shinfo(skb); struct tcp_skb_cb *scb = TCP_SKB_CB(skb); u8 sacked = scb->sacked; u32 acked_pcount; + if (unlikely(shinfo->tx_flags & SKBTX_ACK_TSTAMP) && + between(shinfo->tskey, prior_snd_una, tp->snd_una - 1)) + __skb_tstamp_tx(skb, NULL, sk, SCM_TSTAMP_ACK); + /* Determine how many packets and what bytes were acked, tso and else */ if (after(scb->end_seq, tp->snd_una)) { if (tcp_skb_pcount(skb) == 1 || @@ -3107,11 +3108,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, tp->retrans_stamp = 0; } - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_ACK_TSTAMP) && - between(skb_shinfo(skb)->tskey, prior_snd_una, - tp->snd_una + 1)) - __skb_tstamp_tx(skb, NULL, sk, SCM_TSTAMP_ACK); - if (!fully_acked) break; @@ -3405,8 +3401,10 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) tcp_rearm_rto(sk); - if (after(ack, prior_snd_una)) + if (after(ack, prior_snd_una)) { flag |= FLAG_SND_UNA_ADVANCED; + icsk->icsk_retransmits = 0; + } prior_fackets = tp->fackets_out; @@ -5979,12 +5977,14 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, * timewait bucket, so that all the necessary checks * are made in the function processing timewait state. */ - if (tmp_opt.saw_tstamp && tcp_death_row.sysctl_tw_recycle) { + if (tcp_death_row.sysctl_tw_recycle) { bool strict; dst = af_ops->route_req(sk, &fl, req, &strict); + if (dst && strict && - !tcp_peer_is_proven(req, dst, true)) { + !tcp_peer_is_proven(req, dst, true, + tmp_opt.saw_tstamp)) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); goto drop_and_release; } @@ -5993,7 +5993,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, else if (!sysctl_tcp_syncookies && (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < (sysctl_max_syn_backlog >> 2)) && - !tcp_peer_is_proven(req, dst, false)) { + !tcp_peer_is_proven(req, dst, false, + tmp_opt.saw_tstamp)) { /* Without syncookies last quarter of * backlog is filled with destinations, * proven to be alive. diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index dceff5fe8e66..cd17f009aede 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -271,7 +271,7 @@ EXPORT_SYMBOL(tcp_v4_connect); * It can be called through tcp_release_cb() if socket was owned by user * at the time tcp_v4_err() was called to handle ICMP message. */ -static void tcp_v4_mtu_reduced(struct sock *sk) +void tcp_v4_mtu_reduced(struct sock *sk) { struct dst_entry *dst; struct inet_sock *inet = inet_sk(sk); @@ -302,6 +302,7 @@ static void tcp_v4_mtu_reduced(struct sock *sk) tcp_simple_retransmit(sk); } /* else let the usual retransmit timer handle it */ } +EXPORT_SYMBOL(tcp_v4_mtu_reduced); static void do_redirect(struct sk_buff *skb, struct sock *sk) { @@ -1787,6 +1788,7 @@ const struct inet_connection_sock_af_ops ipv4_specific = { .compat_setsockopt = compat_ip_setsockopt, .compat_getsockopt = compat_ip_getsockopt, #endif + .mtu_reduced = tcp_v4_mtu_reduced, }; EXPORT_SYMBOL(ipv4_specific); @@ -2406,7 +2408,6 @@ struct proto tcp_prot = { .sendpage = tcp_sendpage, .backlog_rcv = tcp_v4_do_rcv, .release_cb = tcp_release_cb, - .mtu_reduced = tcp_v4_mtu_reduced, .hash = inet_hash, .unhash = inet_unhash, .get_port = inet_csk_get_port, diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 0d54e59b9ea8..ed9c9a91851c 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -576,7 +576,8 @@ reset: tp->snd_cwnd_stamp = tcp_time_stamp; } -bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check) +bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, + bool paws_check, bool timestamps) { struct tcp_metrics_block *tm; bool ret; @@ -589,7 +590,8 @@ bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool pa if (paws_check) { if (tm && (u32)get_seconds() - tm->tcpm_ts_stamp < TCP_PAWS_MSL && - (s32)(tm->tcpm_ts - req->ts_recent) > TCP_PAWS_WINDOW) + ((s32)(tm->tcpm_ts - req->ts_recent) > TCP_PAWS_WINDOW || + !timestamps)) ret = false; else ret = true; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8fcfc91964ec..5a7c41fbc6d3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -800,7 +800,7 @@ void tcp_release_cb(struct sock *sk) __sock_put(sk); } if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { - sk->sk_prot->mtu_reduced(sk); + inet_csk(sk)->icsk_af_ops->mtu_reduced(sk); __sock_put(sk); } } @@ -1069,6 +1069,21 @@ static void tcp_adjust_pcount(struct sock *sk, const struct sk_buff *skb, int de tcp_verify_left_out(tp); } +static void tcp_fragment_tstamp(struct sk_buff *skb, struct sk_buff *skb2) +{ + struct skb_shared_info *shinfo = skb_shinfo(skb); + + if (unlikely(shinfo->tx_flags & SKBTX_ANY_TSTAMP) && + !before(shinfo->tskey, TCP_SKB_CB(skb2)->seq)) { + struct skb_shared_info *shinfo2 = skb_shinfo(skb2); + u8 tsflags = shinfo->tx_flags & SKBTX_ANY_TSTAMP; + + shinfo->tx_flags &= ~tsflags; + shinfo2->tx_flags |= tsflags; + swap(shinfo->tskey, shinfo2->tskey); + } +} + /* Function to create two new TCP segments. Shrinks the given segment * to the specified size and appends a new segment with the rest of the * packet to the list. This won't be called frequently, I hope. @@ -1136,6 +1151,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, */ TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when; buff->tstamp = skb->tstamp; + tcp_fragment_tstamp(skb, buff); old_factor = tcp_skb_pcount(skb); @@ -1652,6 +1668,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, buff->ip_summed = skb->ip_summed = CHECKSUM_PARTIAL; skb_split(skb, buff, len); + tcp_fragment_tstamp(skb, buff); /* Fix up tso_factor for both original and new SKB. */ tcp_set_skb_tso_segs(sk, skb, mss_now); @@ -1917,8 +1934,11 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, tso_segs = tcp_init_tso_segs(sk, skb, mss_now); BUG_ON(!tso_segs); - if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) + if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) { + /* "when" is used as a start point for the retransmit timer */ + TCP_SKB_CB(skb)->when = tcp_time_stamp; goto repair; /* Skip network transmission */ + } cwnd_quota = tcp_cwnd_test(tp, skb); if (!cwnd_quota) { diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 2e9ba035fb5f..6163f851dc01 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -101,19 +101,19 @@ static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net, for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) { if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr && - (!dev || !t->parms.link || dev->iflink == t->parms.link) && + (!dev || !t->parms.link || dev->ifindex == t->parms.link) && (t->dev->flags & IFF_UP)) return t; } for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) { if (remote == t->parms.iph.daddr && - (!dev || !t->parms.link || dev->iflink == t->parms.link) && + (!dev || !t->parms.link || dev->ifindex == t->parms.link) && (t->dev->flags & IFF_UP)) return t; } for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) { if (local == t->parms.iph.saddr && - (!dev || !t->parms.link || dev->iflink == t->parms.link) && + (!dev || !t->parms.link || dev->ifindex == t->parms.link) && (t->dev->flags & IFF_UP)) return t; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f2ce95502392..29964c3d363c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1595,6 +1595,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { .compat_setsockopt = compat_ipv6_setsockopt, .compat_getsockopt = compat_ipv6_getsockopt, #endif + .mtu_reduced = tcp_v6_mtu_reduced, }; #ifdef CONFIG_TCP_MD5SIG @@ -1625,6 +1626,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { .compat_setsockopt = compat_ipv6_setsockopt, .compat_getsockopt = compat_ipv6_getsockopt, #endif + .mtu_reduced = tcp_v4_mtu_reduced, }; #ifdef CONFIG_TCP_MD5SIG @@ -1864,7 +1866,6 @@ struct proto tcpv6_prot = { .sendpage = tcp_sendpage, .backlog_rcv = tcp_v6_do_rcv, .release_cb = tcp_release_cb, - .mtu_reduced = tcp_v6_mtu_reduced, .hash = tcp_v6_hash, .unhash = inet_unhash, .get_port = inet_csk_get_port, diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 9ea0c933b9ff..a37998c6273d 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c @@ -622,7 +622,7 @@ void irlap_send_rd_frame(struct irlap_cb *self) frame = (struct rd_frame *)skb_put(tx_skb, 2); frame->caddr = self->caddr; - frame->caddr = RD_RSP | PF_BIT; + frame->control = RD_RSP | PF_BIT; irlap_queue_xmit(self, tx_skb); } diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 2e152e5f2186..c416725d28c4 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2921,6 +2921,7 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos) } static void *netlink_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(RCU) { rcu_read_lock(); return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : SEQ_START_TOKEN; @@ -2970,6 +2971,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void netlink_seq_stop(struct seq_file *seq, void *v) + __releases(RCU) { rcu_read_unlock(); } diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 702fb21bfe15..6d8f2ec481d9 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -137,8 +137,10 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops, vport->ops = ops; INIT_HLIST_NODE(&vport->dp_hash_node); - if (ovs_vport_set_upcall_portids(vport, parms->upcall_portids)) + if (ovs_vport_set_upcall_portids(vport, parms->upcall_portids)) { + kfree(vport); return ERR_PTR(-EINVAL); + } vport->percpu_stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!vport->percpu_stats) { diff --git a/scripts/analyze_suspend.py b/scripts/analyze_suspend.py index 4f2cc12dc7c7..93e1fd40f430 100755 --- a/scripts/analyze_suspend.py +++ b/scripts/analyze_suspend.py @@ -36,146 +36,392 @@ # CONFIG_FUNCTION_TRACER=y # CONFIG_FUNCTION_GRAPH_TRACER=y # +# For kernel versions older than 3.15: # The following additional kernel parameters are required: # (e.g. in file /etc/default/grub) # GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..." # +# ----------------- LIBRARIES -------------------- + import sys import time import os import string import re -import array import platform -import datetime +from datetime import datetime import struct -# -- classes -- +# ----------------- CLASSES -------------------- +# Class: SystemValues +# Description: +# A global, single-instance container used to +# store system values and test parameters class SystemValues: - testdir = "." - tpath = "/sys/kernel/debug/tracing/" - mempath = "/dev/mem" - powerfile = "/sys/power/state" - suspendmode = "mem" - prefix = "test" - teststamp = "" - dmesgfile = "" - ftracefile = "" - htmlfile = "" + version = 3.0 + verbose = False + testdir = '.' + tpath = '/sys/kernel/debug/tracing/' + fpdtpath = '/sys/firmware/acpi/tables/FPDT' + epath = '/sys/kernel/debug/tracing/events/power/' + traceevents = [ + 'suspend_resume', + 'device_pm_callback_end', + 'device_pm_callback_start' + ] + modename = { + 'freeze': 'Suspend-To-Idle (S0)', + 'standby': 'Power-On Suspend (S1)', + 'mem': 'Suspend-to-RAM (S3)', + 'disk': 'Suspend-to-disk (S4)' + } + mempath = '/dev/mem' + powerfile = '/sys/power/state' + suspendmode = 'mem' + hostname = 'localhost' + prefix = 'test' + teststamp = '' + dmesgfile = '' + ftracefile = '' + htmlfile = '' rtcwake = False + rtcwaketime = 10 + rtcpath = '' + android = False + adb = 'adb' + devicefilter = [] + stamp = 0 + execcount = 1 + x2delay = 0 + usecallgraph = False + usetraceevents = False + usetraceeventsonly = False + notestrun = False + altdevname = dict() + postresumetime = 0 + tracertypefmt = '# tracer: (?P<t>.*)' + firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' + postresumefmt = '# post resume time (?P<t>[0-9]*)$' + stampfmt = '# suspend-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\ + '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\ + ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$' + def __init__(self): + self.hostname = platform.node() + if(self.hostname == ''): + self.hostname = 'localhost' + rtc = "rtc0" + if os.path.exists('/dev/rtc'): + rtc = os.readlink('/dev/rtc') + rtc = '/sys/class/rtc/'+rtc + if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \ + os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'): + self.rtcpath = rtc def setOutputFile(self): - if((self.htmlfile == "") and (self.dmesgfile != "")): - m = re.match(r"(?P<name>.*)_dmesg\.txt$", self.dmesgfile) + if((self.htmlfile == '') and (self.dmesgfile != '')): + m = re.match('(?P<name>.*)_dmesg\.txt$', self.dmesgfile) if(m): - self.htmlfile = m.group("name")+".html" - if((self.htmlfile == "") and (self.ftracefile != "")): - m = re.match(r"(?P<name>.*)_ftrace\.txt$", self.ftracefile) + self.htmlfile = m.group('name')+'.html' + if((self.htmlfile == '') and (self.ftracefile != '')): + m = re.match('(?P<name>.*)_ftrace\.txt$', self.ftracefile) if(m): - self.htmlfile = m.group("name")+".html" - if(self.htmlfile == ""): - self.htmlfile = "output.html" - def initTestOutput(self): - hostname = platform.node() - if(hostname != ""): - self.prefix = hostname - v = os.popen("cat /proc/version").read().strip() - kver = string.split(v)[2] - self.testdir = os.popen("date \"+suspend-%m%d%y-%H%M%S\"").read().strip() - self.teststamp = "# "+self.testdir+" "+self.prefix+" "+self.suspendmode+" "+kver - self.dmesgfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_dmesg.txt" - self.ftracefile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+"_ftrace.txt" - self.htmlfile = self.testdir+"/"+self.prefix+"_"+self.suspendmode+".html" + self.htmlfile = m.group('name')+'.html' + if(self.htmlfile == ''): + self.htmlfile = 'output.html' + def initTestOutput(self, subdir): + if(not self.android): + self.prefix = self.hostname + v = open('/proc/version', 'r').read().strip() + kver = string.split(v)[2] + else: + self.prefix = 'android' + v = os.popen(self.adb+' shell cat /proc/version').read().strip() + kver = string.split(v)[2] + testtime = datetime.now().strftime('suspend-%m%d%y-%H%M%S') + if(subdir != "."): + self.testdir = subdir+"/"+testtime + else: + self.testdir = testtime + self.teststamp = \ + '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver + self.dmesgfile = \ + self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt' + self.ftracefile = \ + self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt' + self.htmlfile = \ + self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html' os.mkdir(self.testdir) + def setDeviceFilter(self, devnames): + self.devicefilter = string.split(devnames) + def rtcWakeAlarm(self): + os.system('echo 0 > '+self.rtcpath+'/wakealarm') + outD = open(self.rtcpath+'/date', 'r').read().strip() + outT = open(self.rtcpath+'/time', 'r').read().strip() + mD = re.match('^(?P<y>[0-9]*)-(?P<m>[0-9]*)-(?P<d>[0-9]*)', outD) + mT = re.match('^(?P<h>[0-9]*):(?P<m>[0-9]*):(?P<s>[0-9]*)', outT) + if(mD and mT): + # get the current time from hardware + utcoffset = int((datetime.now() - datetime.utcnow()).total_seconds()) + dt = datetime(\ + int(mD.group('y')), int(mD.group('m')), int(mD.group('d')), + int(mT.group('h')), int(mT.group('m')), int(mT.group('s'))) + nowtime = int(dt.strftime('%s')) + utcoffset + else: + # if hardware time fails, use the software time + nowtime = int(datetime.now().strftime('%s')) + alarm = nowtime + self.rtcwaketime + os.system('echo %d > %s/wakealarm' % (alarm, self.rtcpath)) +sysvals = SystemValues() + +# Class: DeviceNode +# Description: +# A container used to create a device hierachy, with a single root node +# and a tree of child nodes. Used by Data.deviceTopology() +class DeviceNode: + name = '' + children = 0 + depth = 0 + def __init__(self, nodename, nodedepth): + self.name = nodename + self.children = [] + self.depth = nodedepth + +# Class: Data +# Description: +# The primary container for suspend/resume test data. There is one for +# each test run. The data is organized into a cronological hierarchy: +# Data.dmesg { +# root structure, started as dmesg & ftrace, but now only ftrace +# contents: times for suspend start/end, resume start/end, fwdata +# phases { +# 10 sequential, non-overlapping phases of S/R +# contents: times for phase start/end, order/color data for html +# devlist { +# device callback or action list for this phase +# device { +# a single device callback or generic action +# contents: start/stop times, pid/cpu/driver info +# parents/children, html id for timeline/callgraph +# optionally includes an ftrace callgraph +# optionally includes intradev trace events +# } +# } +# } +# } +# class Data: - altdevname = dict() - usedmesg = False - useftrace = False - notestrun = False - verbose = False - phases = [] - dmesg = {} # root data structure - start = 0.0 - end = 0.0 - stamp = {'time': "", 'host': "", 'mode': ""} - id = 0 - tSuspended = 0.0 - fwValid = False - fwSuspend = 0 - fwResume = 0 - def initialize(self): - self.dmesg = { # dmesg log data - 'suspend_general': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "#CCFFCC", 'order': 0}, - 'suspend_early': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "green", 'order': 1}, + dmesg = {} # root data structure + phases = [] # ordered list of phases + start = 0.0 # test start + end = 0.0 # test end + tSuspended = 0.0 # low-level suspend start + tResumed = 0.0 # low-level resume start + tLow = 0.0 # time spent in low-level suspend (standby/freeze) + fwValid = False # is firmware data available + fwSuspend = 0 # time spent in firmware suspend + fwResume = 0 # time spent in firmware resume + dmesgtext = [] # dmesg text file in memory + testnumber = 0 + idstr = '' + html_device_id = 0 + stamp = 0 + outfile = '' + def __init__(self, num): + idchar = 'abcdefghijklmnopqrstuvwxyz' + self.testnumber = num + self.idstr = idchar[num] + self.dmesgtext = [] + self.phases = [] + self.dmesg = { # fixed list of 10 phases + 'suspend_prepare': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#CCFFCC', 'order': 0}, + 'suspend': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#88FF88', 'order': 1}, + 'suspend_late': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#00AA00', 'order': 2}, 'suspend_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "#00FFFF", 'order': 2}, - 'suspend_cpu': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "blue", 'order': 3}, - 'resume_cpu': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "red", 'order': 4}, + 'row': 0, 'color': '#008888', 'order': 3}, + 'suspend_machine': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#0000FF', 'order': 4}, + 'resume_machine': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#FF0000', 'order': 5}, 'resume_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "orange", 'order': 5}, + 'row': 0, 'color': '#FF9900', 'order': 6}, 'resume_early': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "yellow", 'order': 6}, - 'resume_general': {'list': dict(), 'start': -1.0, 'end': -1.0, - 'row': 0, 'color': "#FFFFCC", 'order': 7} + 'row': 0, 'color': '#FFCC00', 'order': 7}, + 'resume': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#FFFF88', 'order': 8}, + 'resume_complete': {'list': dict(), 'start': -1.0, 'end': -1.0, + 'row': 0, 'color': '#FFFFCC', 'order': 9} } self.phases = self.sortedPhases() - def normalizeTime(self): - tSus = tRes = self.tSuspended - if self.fwValid: - tSus -= -self.fwSuspend / 1000000000.0 - tRes -= self.fwResume / 1000000000.0 - self.tSuspended = 0.0 - self.start -= tSus - self.end -= tRes + def getStart(self): + return self.dmesg[self.phases[0]]['start'] + def setStart(self, time): + self.start = time + self.dmesg[self.phases[0]]['start'] = time + def getEnd(self): + return self.dmesg[self.phases[-1]]['end'] + def setEnd(self, time): + self.end = time + self.dmesg[self.phases[-1]]['end'] = time + def isTraceEventOutsideDeviceCalls(self, pid, time): + for phase in self.phases: + list = self.dmesg[phase]['list'] + for dev in list: + d = list[dev] + if(d['pid'] == pid and time >= d['start'] and + time <= d['end']): + return False + return True + def addIntraDevTraceEvent(self, action, name, pid, time): + if(action == 'mutex_lock_try'): + color = 'red' + elif(action == 'mutex_lock_pass'): + color = 'green' + elif(action == 'mutex_unlock'): + color = 'blue' + else: + # create separate colors based on the name + v1 = len(name)*10 % 256 + v2 = string.count(name, 'e')*100 % 256 + v3 = ord(name[0])*20 % 256 + color = '#%06X' % ((v1*0x10000) + (v2*0x100) + v3) + for phase in self.phases: + list = self.dmesg[phase]['list'] + for dev in list: + d = list[dev] + if(d['pid'] == pid and time >= d['start'] and + time <= d['end']): + e = TraceEvent(action, name, color, time) + if('traceevents' not in d): + d['traceevents'] = [] + d['traceevents'].append(e) + return d + break + return 0 + def capIntraDevTraceEvent(self, action, name, pid, time): + for phase in self.phases: + list = self.dmesg[phase]['list'] + for dev in list: + d = list[dev] + if(d['pid'] == pid and time >= d['start'] and + time <= d['end']): + if('traceevents' not in d): + return + for e in d['traceevents']: + if(e.action == action and + e.name == name and not e.ready): + e.length = time - e.time + e.ready = True + break + return + def trimTimeVal(self, t, t0, dT, left): + if left: + if(t > t0): + if(t - dT < t0): + return t0 + return t - dT + else: + return t + else: + if(t < t0 + dT): + if(t > t0): + return t0 + dT + return t + dT + else: + return t + def trimTime(self, t0, dT, left): + self.tSuspended = self.trimTimeVal(self.tSuspended, t0, dT, left) + self.tResumed = self.trimTimeVal(self.tResumed, t0, dT, left) + self.start = self.trimTimeVal(self.start, t0, dT, left) + self.end = self.trimTimeVal(self.end, t0, dT, left) for phase in self.phases: - zero = tRes - if "suspend" in phase: - zero = tSus p = self.dmesg[phase] - p['start'] -= zero - p['end'] -= zero + p['start'] = self.trimTimeVal(p['start'], t0, dT, left) + p['end'] = self.trimTimeVal(p['end'], t0, dT, left) list = p['list'] for name in list: d = list[name] - d['start'] -= zero - d['end'] -= zero + d['start'] = self.trimTimeVal(d['start'], t0, dT, left) + d['end'] = self.trimTimeVal(d['end'], t0, dT, left) if('ftrace' in d): cg = d['ftrace'] - cg.start -= zero - cg.end -= zero + cg.start = self.trimTimeVal(cg.start, t0, dT, left) + cg.end = self.trimTimeVal(cg.end, t0, dT, left) for line in cg.list: - line.time -= zero - if self.fwValid: - fws = -self.fwSuspend / 1000000000.0 - fwr = self.fwResume / 1000000000.0 - list = dict() - self.id += 1 - devid = "dc%d" % self.id - list["firmware-suspend"] = \ - {'start': fws, 'end': 0, 'pid': 0, 'par': "", - 'length': -fws, 'row': 0, 'id': devid }; - self.id += 1 - devid = "dc%d" % self.id - list["firmware-resume"] = \ - {'start': 0, 'end': fwr, 'pid': 0, 'par': "", - 'length': fwr, 'row': 0, 'id': devid }; - self.dmesg['BIOS'] = \ - {'list': list, 'start': fws, 'end': fwr, - 'row': 0, 'color': "purple", 'order': 4} - self.dmesg['resume_cpu']['order'] += 1 - self.dmesg['resume_noirq']['order'] += 1 - self.dmesg['resume_early']['order'] += 1 - self.dmesg['resume_general']['order'] += 1 - self.phases = self.sortedPhases() - def vprint(self, msg): - if(self.verbose): - print(msg) + line.time = self.trimTimeVal(line.time, t0, dT, left) + if('traceevents' in d): + for e in d['traceevents']: + e.time = self.trimTimeVal(e.time, t0, dT, left) + def normalizeTime(self, tZero): + # first trim out any standby or freeze clock time + if(self.tSuspended != self.tResumed): + if(self.tResumed > tZero): + self.trimTime(self.tSuspended, \ + self.tResumed-self.tSuspended, True) + else: + self.trimTime(self.tSuspended, \ + self.tResumed-self.tSuspended, False) + # shift the timeline so that tZero is the new 0 + self.tSuspended -= tZero + self.tResumed -= tZero + self.start -= tZero + self.end -= tZero + for phase in self.phases: + p = self.dmesg[phase] + p['start'] -= tZero + p['end'] -= tZero + list = p['list'] + for name in list: + d = list[name] + d['start'] -= tZero + d['end'] -= tZero + if('ftrace' in d): + cg = d['ftrace'] + cg.start -= tZero + cg.end -= tZero + for line in cg.list: + line.time -= tZero + if('traceevents' in d): + for e in d['traceevents']: + e.time -= tZero + def newPhaseWithSingleAction(self, phasename, devname, start, end, color): + for phase in self.phases: + self.dmesg[phase]['order'] += 1 + self.html_device_id += 1 + devid = '%s%d' % (self.idstr, self.html_device_id) + list = dict() + list[devname] = \ + {'start': start, 'end': end, 'pid': 0, 'par': '', + 'length': (end-start), 'row': 0, 'id': devid, 'drv': '' }; + self.dmesg[phasename] = \ + {'list': list, 'start': start, 'end': end, + 'row': 0, 'color': color, 'order': 0} + self.phases = self.sortedPhases() + def newPhase(self, phasename, start, end, color, order): + if(order < 0): + order = len(self.phases) + for phase in self.phases[order:]: + self.dmesg[phase]['order'] += 1 + if(order > 0): + p = self.phases[order-1] + self.dmesg[p]['end'] = start + if(order < len(self.phases)): + p = self.phases[order] + self.dmesg[p]['start'] = end + list = dict() + self.dmesg[phasename] = \ + {'list': list, 'start': start, 'end': end, + 'row': 0, 'color': color, 'order': order} + self.phases = self.sortedPhases() + def setPhase(self, phase, ktime, isbegin): + if(isbegin): + self.dmesg[phase]['start'] = ktime + else: + self.dmesg[phase]['end'] = ktime def dmesgSortVal(self, phase): return self.dmesg[phase]['order'] def sortedPhases(self): @@ -197,59 +443,180 @@ class Data: dev = phaselist[devname] if(dev['end'] < 0): dev['end'] = end - self.vprint("%s (%s): callback didn't return" % (devname, phase)) + vprint('%s (%s): callback didnt return' % (devname, phase)) + def deviceFilter(self, devicefilter): + # remove all by the relatives of the filter devnames + filter = [] + for phase in self.phases: + list = self.dmesg[phase]['list'] + for name in devicefilter: + dev = name + while(dev in list): + if(dev not in filter): + filter.append(dev) + dev = list[dev]['par'] + children = self.deviceDescendants(name, phase) + for dev in children: + if(dev not in filter): + filter.append(dev) + for phase in self.phases: + list = self.dmesg[phase]['list'] + rmlist = [] + for name in list: + pid = list[name]['pid'] + if(name not in filter and pid >= 0): + rmlist.append(name) + for name in rmlist: + del list[name] def fixupInitcallsThatDidntReturn(self): # if any calls never returned, clip them at system resume end for phase in self.phases: - self.fixupInitcalls(phase, self.dmesg['resume_general']['end']) - if(phase == "resume_general"): - break - def newAction(self, phase, name, pid, parent, start, end): - self.id += 1 - devid = "dc%d" % self.id + self.fixupInitcalls(phase, self.getEnd()) + def newActionGlobal(self, name, start, end): + # which phase is this device callback or action "in" + targetphase = "none" + overlap = 0.0 + for phase in self.phases: + pstart = self.dmesg[phase]['start'] + pend = self.dmesg[phase]['end'] + o = max(0, min(end, pend) - max(start, pstart)) + if(o > overlap): + targetphase = phase + overlap = o + if targetphase in self.phases: + self.newAction(targetphase, name, -1, '', start, end, '') + return True + return False + def newAction(self, phase, name, pid, parent, start, end, drv): + # new device callback for a specific phase + self.html_device_id += 1 + devid = '%s%d' % (self.idstr, self.html_device_id) list = self.dmesg[phase]['list'] length = -1.0 if(start >= 0 and end >= 0): length = end - start list[name] = {'start': start, 'end': end, 'pid': pid, 'par': parent, - 'length': length, 'row': 0, 'id': devid } + 'length': length, 'row': 0, 'id': devid, 'drv': drv } def deviceIDs(self, devlist, phase): idlist = [] - for p in self.phases: - if(p[0] != phase[0]): - continue - list = data.dmesg[p]['list'] - for devname in list: - if devname in devlist: - idlist.append(list[devname]['id']) + list = self.dmesg[phase]['list'] + for devname in list: + if devname in devlist: + idlist.append(list[devname]['id']) return idlist def deviceParentID(self, devname, phase): - pdev = "" - pdevid = "" - for p in self.phases: - if(p[0] != phase[0]): - continue - list = data.dmesg[p]['list'] - if devname in list: - pdev = list[devname]['par'] - for p in self.phases: - if(p[0] != phase[0]): - continue - list = data.dmesg[p]['list'] - if pdev in list: - return list[pdev]['id'] + pdev = '' + pdevid = '' + list = self.dmesg[phase]['list'] + if devname in list: + pdev = list[devname]['par'] + if pdev in list: + return list[pdev]['id'] return pdev - def deviceChildrenIDs(self, devname, phase): + def deviceChildren(self, devname, phase): devlist = [] - for p in self.phases: - if(p[0] != phase[0]): - continue - list = data.dmesg[p]['list'] - for child in list: - if(list[child]['par'] == devname): - devlist.append(child) + list = self.dmesg[phase]['list'] + for child in list: + if(list[child]['par'] == devname): + devlist.append(child) + return devlist + def deviceDescendants(self, devname, phase): + children = self.deviceChildren(devname, phase) + family = children + for child in children: + family += self.deviceDescendants(child, phase) + return family + def deviceChildrenIDs(self, devname, phase): + devlist = self.deviceChildren(devname, phase) return self.deviceIDs(devlist, phase) - + def printDetails(self): + vprint(' test start: %f' % self.start) + for phase in self.phases: + dc = len(self.dmesg[phase]['list']) + vprint(' %16s: %f - %f (%d devices)' % (phase, \ + self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc)) + vprint(' test end: %f' % self.end) + def masterTopology(self, name, list, depth): + node = DeviceNode(name, depth) + for cname in list: + clist = self.deviceChildren(cname, 'resume') + cnode = self.masterTopology(cname, clist, depth+1) + node.children.append(cnode) + return node + def printTopology(self, node): + html = '' + if node.name: + info = '' + drv = '' + for phase in self.phases: + list = self.dmesg[phase]['list'] + if node.name in list: + s = list[node.name]['start'] + e = list[node.name]['end'] + if list[node.name]['drv']: + drv = ' {'+list[node.name]['drv']+'}' + info += ('<li>%s: %.3fms</li>' % (phase, (e-s)*1000)) + html += '<li><b>'+node.name+drv+'</b>' + if info: + html += '<ul>'+info+'</ul>' + html += '</li>' + if len(node.children) > 0: + html += '<ul>' + for cnode in node.children: + html += self.printTopology(cnode) + html += '</ul>' + return html + def rootDeviceList(self): + # list of devices graphed + real = [] + for phase in self.dmesg: + list = self.dmesg[phase]['list'] + for dev in list: + if list[dev]['pid'] >= 0 and dev not in real: + real.append(dev) + # list of top-most root devices + rootlist = [] + for phase in self.dmesg: + list = self.dmesg[phase]['list'] + for dev in list: + pdev = list[dev]['par'] + if(re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)): + continue + if pdev and pdev not in real and pdev not in rootlist: + rootlist.append(pdev) + return rootlist + def deviceTopology(self): + rootlist = self.rootDeviceList() + master = self.masterTopology('', rootlist, 0) + return self.printTopology(master) + +# Class: TraceEvent +# Description: +# A container for trace event data found in the ftrace file +class TraceEvent: + ready = False + name = '' + time = 0.0 + color = '#FFFFFF' + length = 0.0 + action = '' + def __init__(self, a, n, c, t): + self.action = a + self.name = n + self.color = c + self.time = t + +# Class: FTraceLine +# Description: +# A container for a single line of ftrace data. There are six basic types: +# callgraph line: +# call: " dpm_run_callback() {" +# return: " }" +# leaf: " dpm_run_callback();" +# trace event: +# tracing_mark_write: SUSPEND START or RESUME COMPLETE +# suspend_resume: phase or custom exec block data +# device_pm_callback: device callback info class FTraceLine: time = 0.0 length = 0.0 @@ -257,20 +624,33 @@ class FTraceLine: freturn = False fevent = False depth = 0 - name = "" + name = '' + type = '' def __init__(self, t, m, d): self.time = float(t) - # check to see if this is a trace event - em = re.match(r"^ *\/\* *(?P<msg>.*) \*\/ *$", m) - if(em): - self.name = em.group("msg") + # is this a trace event + if(d == 'traceevent' or re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)): + if(d == 'traceevent'): + # nop format trace event + msg = m + else: + # function_graph format trace event + em = re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m) + msg = em.group('msg') + + emm = re.match('^(?P<call>.*?): (?P<msg>.*)', msg) + if(emm): + self.name = emm.group('msg') + self.type = emm.group('call') + else: + self.name = msg self.fevent = True return # convert the duration to seconds if(d): self.length = float(d)/1000000 # the indentation determines the depth - match = re.match(r"^(?P<d> *)(?P<o>.*)$", m) + match = re.match('^(?P<d> *)(?P<o>.*)$', m) if(not match): return self.depth = self.getDepth(match.group('d')) @@ -280,7 +660,7 @@ class FTraceLine: self.freturn = True if(len(m) > 1): # includes comment with function name - match = re.match(r"^} *\/\* *(?P<n>.*) *\*\/$", m) + match = re.match('^} *\/\* *(?P<n>.*) *\*\/$', m) if(match): self.name = match.group('n') # function call @@ -288,13 +668,13 @@ class FTraceLine: self.fcall = True # function call with children if(m[-1] == '{'): - match = re.match(r"^(?P<n>.*) *\(.*", m) + match = re.match('^(?P<n>.*) *\(.*', m) if(match): self.name = match.group('n') # function call with no children (leaf) elif(m[-1] == ';'): self.freturn = True - match = re.match(r"^(?P<n>.*) *\(.*", m) + match = re.match('^(?P<n>.*) *\(.*', m) if(match): self.name = match.group('n') # something else (possibly a trace marker) @@ -302,7 +682,23 @@ class FTraceLine: self.name = m def getDepth(self, str): return len(str)/2 + def debugPrint(self, dev): + if(self.freturn and self.fcall): + print('%s -- %f (%02d): %s(); (%.3f us)' % (dev, self.time, \ + self.depth, self.name, self.length*1000000)) + elif(self.freturn): + print('%s -- %f (%02d): %s} (%.3f us)' % (dev, self.time, \ + self.depth, self.name, self.length*1000000)) + else: + print('%s -- %f (%02d): %s() { (%.3f us)' % (dev, self.time, \ + self.depth, self.name, self.length*1000000)) +# Class: FTraceCallGraph +# Description: +# A container for the ftrace callgraph of a single recursive function. +# This can be a dpm_run_callback, dpm_prepare, or dpm_complete callgraph +# Each instance is tied to a single device in a single phase, and is +# comprised of an ordered list of FTraceLine objects class FTraceCallGraph: start = -1.0 end = -1.0 @@ -327,24 +723,53 @@ class FTraceCallGraph: if(not self.invalid): self.setDepth(line) if(line.depth == 0 and line.freturn): + if(self.start < 0): + self.start = line.time self.end = line.time self.list.append(line) return True if(self.invalid): return False if(len(self.list) >= 1000000 or self.depth < 0): - first = self.list[0] - self.list = [] - self.list.append(first) - self.invalid = True - id = "task %s cpu %s" % (match.group("pid"), match.group("cpu")) - window = "(%f - %f)" % (self.start, line.time) - data.vprint("Too much data for "+id+" "+window+", ignoring this callback") - return False + if(len(self.list) > 0): + first = self.list[0] + self.list = [] + self.list.append(first) + self.invalid = True + if(not match): + return False + id = 'task %s cpu %s' % (match.group('pid'), match.group('cpu')) + window = '(%f - %f)' % (self.start, line.time) + if(self.depth < 0): + print('Too much data for '+id+\ + ' (buffer overflow), ignoring this callback') + else: + print('Too much data for '+id+\ + ' '+window+', ignoring this callback') + return False self.list.append(line) if(self.start < 0): self.start = line.time return False + def slice(self, t0, tN): + minicg = FTraceCallGraph() + count = -1 + firstdepth = 0 + for l in self.list: + if(l.time < t0 or l.time > tN): + continue + if(count < 0): + if(not l.fcall or l.name == 'dev_driver_string'): + continue + firstdepth = l.depth + count = 0 + l.depth -= firstdepth + minicg.addLine(l, 0) + if((count == 0 and l.freturn and l.fcall) or + (count > 0 and l.depth <= 0)): + break + count += 1 + return minicg def sanityCheck(self): stack = dict() cnt = 0 @@ -353,7 +778,7 @@ class FTraceCallGraph: stack[l.depth] = l cnt += 1 elif(l.freturn and not l.fcall): - if(not stack[l.depth]): + if(l.depth not in stack): return False stack[l.depth].length = l.length stack[l.depth] = 0 @@ -363,40 +788,51 @@ class FTraceCallGraph: return True return False def debugPrint(self, filename): - if(filename == "stdout"): - print("[%f - %f]") % (self.start, self.end) + if(filename == 'stdout'): + print('[%f - %f]') % (self.start, self.end) for l in self.list: if(l.freturn and l.fcall): - print("%f (%02d): %s(); (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000)) + print('%f (%02d): %s(); (%.3f us)' % (l.time, \ + l.depth, l.name, l.length*1000000)) elif(l.freturn): - print("%f (%02d): %s} (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000)) + print('%f (%02d): %s} (%.3f us)' % (l.time, \ + l.depth, l.name, l.length*1000000)) else: - print("%f (%02d): %s() { (%.3f us)" % (l.time, l.depth, l.name, l.length*1000000)) - print(" ") + print('%f (%02d): %s() { (%.3f us)' % (l.time, \ + l.depth, l.name, l.length*1000000)) + print(' ') else: fp = open(filename, 'w') print(filename) for l in self.list: if(l.freturn and l.fcall): - fp.write("%f (%02d): %s(); (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000)) + fp.write('%f (%02d): %s(); (%.3f us)\n' % (l.time, \ + l.depth, l.name, l.length*1000000)) elif(l.freturn): - fp.write("%f (%02d): %s} (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000)) + fp.write('%f (%02d): %s} (%.3f us)\n' % (l.time, \ + l.depth, l.name, l.length*1000000)) else: - fp.write("%f (%02d): %s() { (%.3f us)\n" % (l.time, l.depth, l.name, l.length*1000000)) + fp.write('%f (%02d): %s() { (%.3f us)\n' % (l.time, \ + l.depth, l.name, l.length*1000000)) fp.close() +# Class: Timeline +# Description: +# A container for a suspend/resume html timeline. In older versions +# of the script there were multiple timelines, but in the latest +# there is only one. class Timeline: html = {} - scaleH = 0.0 # height of the timescale row as a percent of the timeline height + scaleH = 0.0 # height of the row as a percent of the timeline height rowH = 0.0 # height of each row in percent of the timeline height row_height_pixels = 30 maxrows = 0 height = 0 def __init__(self): self.html = { - 'timeline': "", - 'legend': "", - 'scale': "" + 'timeline': '', + 'legend': '', + 'scale': '' } def setRows(self, rows): self.maxrows = int(rows) @@ -407,104 +843,261 @@ class Timeline: r = 1.0 self.rowH = (100.0 - self.scaleH)/r -# -- global objects -- +# Class: TestRun +# Description: +# A container for a suspend/resume test run. This is necessary as +# there could be more than one, and they need to be separate. +class TestRun: + ftrace_line_fmt_fg = \ + '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ + ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ + '[ +!]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)' + ftrace_line_fmt_nop = \ + ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\ + '(?P<flags>.{4}) *(?P<time>[0-9\.]*): *'+\ + '(?P<msg>.*)' + ftrace_line_fmt = ftrace_line_fmt_nop + cgformat = False + ftemp = dict() + ttemp = dict() + inthepipe = False + tracertype = '' + data = 0 + def __init__(self, dataobj): + self.data = dataobj + self.ftemp = dict() + self.ttemp = dict() + def isReady(self): + if(tracertype == '' or not data): + return False + return True + def setTracerType(self, tracer): + self.tracertype = tracer + if(tracer == 'function_graph'): + self.cgformat = True + self.ftrace_line_fmt = self.ftrace_line_fmt_fg + elif(tracer == 'nop'): + self.ftrace_line_fmt = self.ftrace_line_fmt_nop + else: + doError('Invalid tracer format: [%s]' % tracer, False) -sysvals = SystemValues() -data = Data() +# ----------------- FUNCTIONS -------------------- -# -- functions -- +# Function: vprint +# Description: +# verbose print (prints only with -verbose option) +# Arguments: +# msg: the debug/log message to print +def vprint(msg): + global sysvals + if(sysvals.verbose): + print(msg) # Function: initFtrace # Description: -# Configure ftrace to capture a function trace during suspend/resume +# Configure ftrace to use trace events and/or a callgraph def initFtrace(): global sysvals - print("INITIALIZING FTRACE...") - # turn trace off - os.system("echo 0 > "+sysvals.tpath+"tracing_on") - # set the trace clock to global - os.system("echo global > "+sysvals.tpath+"trace_clock") - # set trace buffer to a huge value - os.system("echo nop > "+sysvals.tpath+"current_tracer") - os.system("echo 100000 > "+sysvals.tpath+"buffer_size_kb") - # clear the trace buffer - os.system("echo \"\" > "+sysvals.tpath+"trace") - # set trace type - os.system("echo function_graph > "+sysvals.tpath+"current_tracer") - os.system("echo \"\" > "+sysvals.tpath+"set_ftrace_filter") - # set trace format options - os.system("echo funcgraph-abstime > "+sysvals.tpath+"trace_options") - os.system("echo funcgraph-proc > "+sysvals.tpath+"trace_options") - # focus only on device suspend and resume - os.system("cat "+sysvals.tpath+"available_filter_functions | grep dpm_run_callback > "+sysvals.tpath+"set_graph_function") + tp = sysvals.tpath + cf = 'dpm_run_callback' + if(sysvals.usetraceeventsonly): + cf = '-e dpm_prepare -e dpm_complete -e dpm_run_callback' + if(sysvals.usecallgraph or sysvals.usetraceevents): + print('INITIALIZING FTRACE...') + # turn trace off + os.system('echo 0 > '+tp+'tracing_on') + # set the trace clock to global + os.system('echo global > '+tp+'trace_clock') + # set trace buffer to a huge value + os.system('echo nop > '+tp+'current_tracer') + os.system('echo 100000 > '+tp+'buffer_size_kb') + # initialize the callgraph trace, unless this is an x2 run + if(sysvals.usecallgraph and sysvals.execcount == 1): + # set trace type + os.system('echo function_graph > '+tp+'current_tracer') + os.system('echo "" > '+tp+'set_ftrace_filter') + # set trace format options + os.system('echo funcgraph-abstime > '+tp+'trace_options') + os.system('echo funcgraph-proc > '+tp+'trace_options') + # focus only on device suspend and resume + os.system('cat '+tp+'available_filter_functions | grep '+\ + cf+' > '+tp+'set_graph_function') + if(sysvals.usetraceevents): + # turn trace events on + events = iter(sysvals.traceevents) + for e in events: + os.system('echo 1 > '+sysvals.epath+e+'/enable') + # clear the trace buffer + os.system('echo "" > '+tp+'trace') + +# Function: initFtraceAndroid +# Description: +# Configure ftrace to capture trace events +def initFtraceAndroid(): + global sysvals + + tp = sysvals.tpath + if(sysvals.usetraceevents): + print('INITIALIZING FTRACE...') + # turn trace off + os.system(sysvals.adb+" shell 'echo 0 > "+tp+"tracing_on'") + # set the trace clock to global + os.system(sysvals.adb+" shell 'echo global > "+tp+"trace_clock'") + # set trace buffer to a huge value + os.system(sysvals.adb+" shell 'echo nop > "+tp+"current_tracer'") + os.system(sysvals.adb+" shell 'echo 10000 > "+tp+"buffer_size_kb'") + # turn trace events on + events = iter(sysvals.traceevents) + for e in events: + os.system(sysvals.adb+" shell 'echo 1 > "+\ + sysvals.epath+e+"/enable'") + # clear the trace buffer + os.system(sysvals.adb+" shell 'echo \"\" > "+tp+"trace'") # Function: verifyFtrace # Description: # Check that ftrace is working on the system +# Output: +# True or False def verifyFtrace(): global sysvals - files = ["available_filter_functions", "buffer_size_kb", - "current_tracer", "set_ftrace_filter", - "trace", "trace_marker"] + # files needed for any trace data + files = ['buffer_size_kb', 'current_tracer', 'trace', 'trace_clock', + 'trace_marker', 'trace_options', 'tracing_on'] + # files needed for callgraph trace data + tp = sysvals.tpath + if(sysvals.usecallgraph): + files += [ + 'available_filter_functions', + 'set_ftrace_filter', + 'set_graph_function' + ] for f in files: - if(os.path.exists(sysvals.tpath+f) == False): - return False + if(sysvals.android): + out = os.popen(sysvals.adb+' shell ls '+tp+f).read().strip() + if(out != tp+f): + return False + else: + if(os.path.exists(tp+f) == False): + return False return True -def parseStamp(line): - global data, sysvals - stampfmt = r"# suspend-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-"+\ - "(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})"+\ - " (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$" - m = re.match(stampfmt, line) - if(m): - dt = datetime.datetime(int(m.group("y"))+2000, int(m.group("m")), - int(m.group("d")), int(m.group("H")), int(m.group("M")), - int(m.group("S"))) - data.stamp['time'] = dt.strftime("%B %d %Y, %I:%M:%S %p") - data.stamp['host'] = m.group("host") - data.stamp['mode'] = m.group("mode") - data.stamp['kernel'] = m.group("kernel") - sysvals.suspendmode = data.stamp['mode'] - -# Function: analyzeTraceLog +# Function: parseStamp # Description: -# Analyse an ftrace log output file generated from this app during -# the execution phase. Create an "ftrace" structure in memory for -# subsequent formatting in the html output file -def analyzeTraceLog(): - global sysvals, data - - # the ftrace data is tied to the dmesg data - if(not data.usedmesg): - return - - # read through the ftrace and parse the data - data.vprint("Analyzing the ftrace data...") - ftrace_line_fmt = r"^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)"+\ - " *(?P<proc>.*)-(?P<pid>[0-9]*) *\|"+\ - "[ +!]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)" - ftemp = dict() - inthepipe = False +# Pull in the stamp comment line from the data file(s), +# create the stamp, and add it to the global sysvals object +# Arguments: +# m: the valid re.match output for the stamp line +def parseStamp(m, data): + global sysvals + data.stamp = {'time': '', 'host': '', 'mode': ''} + dt = datetime(int(m.group('y'))+2000, int(m.group('m')), + int(m.group('d')), int(m.group('H')), int(m.group('M')), + int(m.group('S'))) + data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p') + data.stamp['host'] = m.group('host') + data.stamp['mode'] = m.group('mode') + data.stamp['kernel'] = m.group('kernel') + sysvals.suspendmode = data.stamp['mode'] + if not sysvals.stamp: + sysvals.stamp = data.stamp + +# Function: diffStamp +# Description: +# compare the host, kernel, and mode fields in 3 stamps +# Arguments: +# stamp1: string array with mode, kernel, and host +# stamp2: string array with mode, kernel, and host +# Return: +# True if stamps differ, False if they're the same +def diffStamp(stamp1, stamp2): + if 'host' in stamp1 and 'host' in stamp2: + if stamp1['host'] != stamp2['host']: + return True + if 'kernel' in stamp1 and 'kernel' in stamp2: + if stamp1['kernel'] != stamp2['kernel']: + return True + if 'mode' in stamp1 and 'mode' in stamp2: + if stamp1['mode'] != stamp2['mode']: + return True + return False + +# Function: doesTraceLogHaveTraceEvents +# Description: +# Quickly determine if the ftrace log has some or all of the trace events +# required for primary parsing. Set the usetraceevents and/or +# usetraceeventsonly flags in the global sysvals object +def doesTraceLogHaveTraceEvents(): + global sysvals + + sysvals.usetraceeventsonly = True + sysvals.usetraceevents = False + for e in sysvals.traceevents: + out = os.popen('cat '+sysvals.ftracefile+' | grep "'+e+': "').read() + if(not out): + sysvals.usetraceeventsonly = False + if(e == 'suspend_resume' and out): + sysvals.usetraceevents = True + +# Function: appendIncompleteTraceLog +# Description: +# [deprecated for kernel 3.15 or newer] +# Legacy support of ftrace outputs that lack the device_pm_callback +# and/or suspend_resume trace events. The primary data should be +# taken from dmesg, and this ftrace is used only for callgraph data +# or custom actions in the timeline. The data is appended to the Data +# objects provided. +# Arguments: +# testruns: the array of Data objects obtained from parseKernelLog +def appendIncompleteTraceLog(testruns): + global sysvals + + # create TestRun vessels for ftrace parsing + testcnt = len(testruns) + testidx = -1 + testrun = [] + for data in testruns: + testrun.append(TestRun(data)) + + # extract the callgraph and traceevent data + vprint('Analyzing the ftrace data...') tf = open(sysvals.ftracefile, 'r') - count = 0 for line in tf: - count = count + 1 - # grab the time stamp if it's valid - if(count == 1): - parseStamp(line) + # remove any latent carriage returns + line = line.replace('\r\n', '') + # grab the time stamp first (signifies the start of the test run) + m = re.match(sysvals.stampfmt, line) + if(m): + testidx += 1 + parseStamp(m, testrun[testidx].data) + continue + # pull out any firmware data + if(re.match(sysvals.firmwarefmt, line)): + continue + # if we havent found a test time stamp yet keep spinning til we do + if(testidx < 0): + continue + # determine the trace data type (required for further parsing) + m = re.match(sysvals.tracertypefmt, line) + if(m): + tracer = m.group('t') + testrun[testidx].setTracerType(tracer) continue - # parse only valid lines - m = re.match(ftrace_line_fmt, line) + # parse only valid lines, if this isnt one move on + m = re.match(testrun[testidx].ftrace_line_fmt, line) if(not m): continue - m_time = m.group("time") - m_pid = m.group("pid") - m_msg = m.group("msg") - m_dur = m.group("dur") + # gather the basic message data from the line + m_time = m.group('time') + m_pid = m.group('pid') + m_msg = m.group('msg') + if(testrun[testidx].cgformat): + m_param3 = m.group('dur') + else: + m_param3 = 'traceevent' if(m_time and m_pid and m_msg): - t = FTraceLine(m_time, m_msg, m_dur) + t = FTraceLine(m_time, m_msg, m_param3) pid = int(m_pid) else: continue @@ -512,265 +1105,840 @@ def analyzeTraceLog(): if(not t.fcall and not t.freturn and not t.fevent): continue # only parse the ftrace data during suspend/resume - if(not inthepipe): + data = testrun[testidx].data + if(not testrun[testidx].inthepipe): # look for the suspend start marker if(t.fevent): - if(t.name == "SUSPEND START"): - data.vprint("SUSPEND START %f %s:%d" % (t.time, sysvals.ftracefile, count)) - inthepipe = True + if(t.name == 'SUSPEND START'): + testrun[testidx].inthepipe = True + data.setStart(t.time) continue else: - # look for the resume end marker + # trace event processing if(t.fevent): - if(t.name == "RESUME COMPLETE"): - data.vprint("RESUME COMPLETE %f %s:%d" % (t.time, sysvals.ftracefile, count)) - inthepipe = False - break + if(t.name == 'RESUME COMPLETE'): + testrun[testidx].inthepipe = False + data.setEnd(t.time) + if(testidx == testcnt - 1): + break + continue + # general trace events have two types, begin and end + if(re.match('(?P<name>.*) begin$', t.name)): + isbegin = True + elif(re.match('(?P<name>.*) end$', t.name)): + isbegin = False + else: + continue + m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name) + if(m): + val = m.group('val') + if val == '0': + name = m.group('name') + else: + name = m.group('name')+'['+val+']' + else: + m = re.match('(?P<name>.*) .*', t.name) + name = m.group('name') + # special processing for trace events + if re.match('dpm_prepare\[.*', name): + continue + elif re.match('machine_suspend.*', name): + continue + elif re.match('suspend_enter\[.*', name): + if(not isbegin): + data.dmesg['suspend_prepare']['end'] = t.time + continue + elif re.match('dpm_suspend\[.*', name): + if(not isbegin): + data.dmesg['suspend']['end'] = t.time + continue + elif re.match('dpm_suspend_late\[.*', name): + if(isbegin): + data.dmesg['suspend_late']['start'] = t.time + else: + data.dmesg['suspend_late']['end'] = t.time + continue + elif re.match('dpm_suspend_noirq\[.*', name): + if(isbegin): + data.dmesg['suspend_noirq']['start'] = t.time + else: + data.dmesg['suspend_noirq']['end'] = t.time + continue + elif re.match('dpm_resume_noirq\[.*', name): + if(isbegin): + data.dmesg['resume_machine']['end'] = t.time + data.dmesg['resume_noirq']['start'] = t.time + else: + data.dmesg['resume_noirq']['end'] = t.time + continue + elif re.match('dpm_resume_early\[.*', name): + if(isbegin): + data.dmesg['resume_early']['start'] = t.time + else: + data.dmesg['resume_early']['end'] = t.time + continue + elif re.match('dpm_resume\[.*', name): + if(isbegin): + data.dmesg['resume']['start'] = t.time + else: + data.dmesg['resume']['end'] = t.time + continue + elif re.match('dpm_complete\[.*', name): + if(isbegin): + data.dmesg['resume_complete']['start'] = t.time + else: + data.dmesg['resume_complete']['end'] = t.time + continue + # is this trace event outside of the devices calls + if(data.isTraceEventOutsideDeviceCalls(pid, t.time)): + # global events (outside device calls) are simply graphed + if(isbegin): + # store each trace event in ttemp + if(name not in testrun[testidx].ttemp): + testrun[testidx].ttemp[name] = [] + testrun[testidx].ttemp[name].append(\ + {'begin': t.time, 'end': t.time}) + else: + # finish off matching trace event in ttemp + if(name in testrun[testidx].ttemp): + testrun[testidx].ttemp[name][-1]['end'] = t.time + else: + if(isbegin): + data.addIntraDevTraceEvent('', name, pid, t.time) + else: + data.capIntraDevTraceEvent('', name, pid, t.time) + # call/return processing + elif sysvals.usecallgraph: + # create a callgraph object for the data + if(pid not in testrun[testidx].ftemp): + testrun[testidx].ftemp[pid] = [] + testrun[testidx].ftemp[pid].append(FTraceCallGraph()) + # when the call is finished, see which device matches it + cg = testrun[testidx].ftemp[pid][-1] + if(cg.addLine(t, m)): + testrun[testidx].ftemp[pid].append(FTraceCallGraph()) + tf.close() + + for test in testrun: + # add the traceevent data to the device hierarchy + if(sysvals.usetraceevents): + for name in test.ttemp: + for event in test.ttemp[name]: + begin = event['begin'] + end = event['end'] + # if event starts before timeline start, expand timeline + if(begin < test.data.start): + test.data.setStart(begin) + # if event ends after timeline end, expand the timeline + if(end > test.data.end): + test.data.setEnd(end) + test.data.newActionGlobal(name, begin, end) + + # add the callgraph data to the device hierarchy + for pid in test.ftemp: + for cg in test.ftemp[pid]: + if(not cg.sanityCheck()): + id = 'task %s cpu %s' % (pid, m.group('cpu')) + vprint('Sanity check failed for '+\ + id+', ignoring this callback') + continue + callstart = cg.start + callend = cg.end + for p in test.data.phases: + if(test.data.dmesg[p]['start'] <= callstart and + callstart <= test.data.dmesg[p]['end']): + list = test.data.dmesg[p]['list'] + for devname in list: + dev = list[devname] + if(pid == dev['pid'] and + callstart <= dev['start'] and + callend >= dev['end']): + dev['ftrace'] = cg + break + + if(sysvals.verbose): + test.data.printDetails() + + + # add the time in between the tests as a new phase so we can see it + if(len(testruns) > 1): + t1e = testruns[0].getEnd() + t2s = testruns[-1].getStart() + testruns[-1].newPhaseWithSingleAction('user mode', \ + 'user mode', t1e, t2s, '#FF9966') + +# Function: parseTraceLog +# Description: +# Analyze an ftrace log output file generated from this app during +# the execution phase. Used when the ftrace log is the primary data source +# and includes the suspend_resume and device_pm_callback trace events +# The ftrace filename is taken from sysvals +# Output: +# An array of Data objects +def parseTraceLog(): + global sysvals + + vprint('Analyzing the ftrace data...') + if(os.path.exists(sysvals.ftracefile) == False): + doError('%s doesnt exist' % sysvals.ftracefile, False) + + # extract the callgraph and traceevent data + testruns = [] + testdata = [] + testrun = 0 + data = 0 + tf = open(sysvals.ftracefile, 'r') + phase = 'suspend_prepare' + for line in tf: + # remove any latent carriage returns + line = line.replace('\r\n', '') + # stamp line: each stamp means a new test run + m = re.match(sysvals.stampfmt, line) + if(m): + data = Data(len(testdata)) + testdata.append(data) + testrun = TestRun(data) + testruns.append(testrun) + parseStamp(m, data) + continue + if(not data): + continue + # firmware line: pull out any firmware data + m = re.match(sysvals.firmwarefmt, line) + if(m): + data.fwSuspend = int(m.group('s')) + data.fwResume = int(m.group('r')) + if(data.fwSuspend > 0 or data.fwResume > 0): + data.fwValid = True + continue + # tracer type line: determine the trace data type + m = re.match(sysvals.tracertypefmt, line) + if(m): + tracer = m.group('t') + testrun.setTracerType(tracer) + continue + # post resume time line: did this test run include post-resume data + m = re.match(sysvals.postresumefmt, line) + if(m): + t = int(m.group('t')) + if(t > 0): + sysvals.postresumetime = t + continue + # ftrace line: parse only valid lines + m = re.match(testrun.ftrace_line_fmt, line) + if(not m): + continue + # gather the basic message data from the line + m_time = m.group('time') + m_pid = m.group('pid') + m_msg = m.group('msg') + if(testrun.cgformat): + m_param3 = m.group('dur') + else: + m_param3 = 'traceevent' + if(m_time and m_pid and m_msg): + t = FTraceLine(m_time, m_msg, m_param3) + pid = int(m_pid) + else: + continue + # the line should be a call, return, or event + if(not t.fcall and not t.freturn and not t.fevent): + continue + # only parse the ftrace data during suspend/resume + if(not testrun.inthepipe): + # look for the suspend start marker + if(t.fevent): + if(t.name == 'SUSPEND START'): + testrun.inthepipe = True + data.setStart(t.time) + continue + # trace event processing + if(t.fevent): + if(t.name == 'RESUME COMPLETE'): + if(sysvals.postresumetime > 0): + phase = 'post_resume' + data.newPhase(phase, t.time, t.time, '#FF9966', -1) + else: + testrun.inthepipe = False + data.setEnd(t.time) + continue + if(phase == 'post_resume'): + data.setEnd(t.time) + if(t.type == 'suspend_resume'): + # suspend_resume trace events have two types, begin and end + if(re.match('(?P<name>.*) begin$', t.name)): + isbegin = True + elif(re.match('(?P<name>.*) end$', t.name)): + isbegin = False + else: + continue + m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name) + if(m): + val = m.group('val') + if val == '0': + name = m.group('name') + else: + name = m.group('name')+'['+val+']' + else: + m = re.match('(?P<name>.*) .*', t.name) + name = m.group('name') + # ignore these events + if(re.match('acpi_suspend\[.*', t.name) or + re.match('suspend_enter\[.*', name)): + continue + # -- phase changes -- + # suspend_prepare start + if(re.match('dpm_prepare\[.*', t.name)): + phase = 'suspend_prepare' + if(not isbegin): + data.dmesg[phase]['end'] = t.time + continue + # suspend start + elif(re.match('dpm_suspend\[.*', t.name)): + phase = 'suspend' + data.setPhase(phase, t.time, isbegin) + continue + # suspend_late start + elif(re.match('dpm_suspend_late\[.*', t.name)): + phase = 'suspend_late' + data.setPhase(phase, t.time, isbegin) + continue + # suspend_noirq start + elif(re.match('dpm_suspend_noirq\[.*', t.name)): + phase = 'suspend_noirq' + data.setPhase(phase, t.time, isbegin) + if(not isbegin): + phase = 'suspend_machine' + data.dmesg[phase]['start'] = t.time + continue + # suspend_machine/resume_machine + elif(re.match('machine_suspend\[.*', t.name)): + if(isbegin): + phase = 'suspend_machine' + data.dmesg[phase]['end'] = t.time + data.tSuspended = t.time + else: + if(sysvals.suspendmode in ['mem', 'disk']): + data.dmesg['suspend_machine']['end'] = t.time + data.tSuspended = t.time + phase = 'resume_machine' + data.dmesg[phase]['start'] = t.time + data.tResumed = t.time + data.tLow = data.tResumed - data.tSuspended + continue + # resume_noirq start + elif(re.match('dpm_resume_noirq\[.*', t.name)): + phase = 'resume_noirq' + data.setPhase(phase, t.time, isbegin) + if(isbegin): + data.dmesg['resume_machine']['end'] = t.time + continue + # resume_early start + elif(re.match('dpm_resume_early\[.*', t.name)): + phase = 'resume_early' + data.setPhase(phase, t.time, isbegin) + continue + # resume start + elif(re.match('dpm_resume\[.*', t.name)): + phase = 'resume' + data.setPhase(phase, t.time, isbegin) + continue + # resume complete start + elif(re.match('dpm_complete\[.*', t.name)): + phase = 'resume_complete' + if(isbegin): + data.dmesg[phase]['start'] = t.time + continue + + # is this trace event outside of the devices calls + if(data.isTraceEventOutsideDeviceCalls(pid, t.time)): + # global events (outside device calls) are simply graphed + if(name not in testrun.ttemp): + testrun.ttemp[name] = [] + if(isbegin): + # create a new list entry + testrun.ttemp[name].append(\ + {'begin': t.time, 'end': t.time}) + else: + if(len(testrun.ttemp[name]) > 0): + # if an antry exists, assume this is its end + testrun.ttemp[name][-1]['end'] = t.time + elif(phase == 'post_resume'): + # post resume events can just have ends + testrun.ttemp[name].append({ + 'begin': data.dmesg[phase]['start'], + 'end': t.time}) + else: + if(isbegin): + data.addIntraDevTraceEvent('', name, pid, t.time) + else: + data.capIntraDevTraceEvent('', name, pid, t.time) + # device callback start + elif(t.type == 'device_pm_callback_start'): + m = re.match('(?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*',\ + t.name); + if(not m): + continue + drv = m.group('drv') + n = m.group('d') + p = m.group('p') + if(n and p): + data.newAction(phase, n, pid, p, t.time, -1, drv) + # device callback finish + elif(t.type == 'device_pm_callback_end'): + m = re.match('(?P<drv>.*) (?P<d>.*), err.*', t.name); + if(not m): + continue + n = m.group('d') + list = data.dmesg[phase]['list'] + if(n in list): + dev = list[n] + dev['length'] = t.time - dev['start'] + dev['end'] = t.time + # callgraph processing + elif sysvals.usecallgraph: + # this shouldn't happen, but JIC, ignore callgraph data post-res + if(phase == 'post_resume'): continue # create a callgraph object for the data - if(pid not in ftemp): - ftemp[pid] = FTraceCallGraph() + if(pid not in testrun.ftemp): + testrun.ftemp[pid] = [] + testrun.ftemp[pid].append(FTraceCallGraph()) # when the call is finished, see which device matches it - if(ftemp[pid].addLine(t, m)): - if(not ftemp[pid].sanityCheck()): - id = "task %s cpu %s" % (pid, m.group("cpu")) - data.vprint("Sanity check failed for "+id+", ignoring this callback") + cg = testrun.ftemp[pid][-1] + if(cg.addLine(t, m)): + testrun.ftemp[pid].append(FTraceCallGraph()) + tf.close() + + for test in testruns: + # add the traceevent data to the device hierarchy + if(sysvals.usetraceevents): + for name in test.ttemp: + for event in test.ttemp[name]: + begin = event['begin'] + end = event['end'] + # if event starts before timeline start, expand timeline + if(begin < test.data.start): + test.data.setStart(begin) + # if event ends after timeline end, expand the timeline + if(end > test.data.end): + test.data.setEnd(end) + test.data.newActionGlobal(name, begin, end) + + # add the callgraph data to the device hierarchy + borderphase = { + 'dpm_prepare': 'suspend_prepare', + 'dpm_complete': 'resume_complete' + } + for pid in test.ftemp: + for cg in test.ftemp[pid]: + if len(cg.list) < 2: + continue + if(not cg.sanityCheck()): + id = 'task %s cpu %s' % (pid, m.group('cpu')) + vprint('Sanity check failed for '+\ + id+', ignoring this callback') + continue + callstart = cg.start + callend = cg.end + if(cg.list[0].name in borderphase): + p = borderphase[cg.list[0].name] + list = test.data.dmesg[p]['list'] + for devname in list: + dev = list[devname] + if(pid == dev['pid'] and + callstart <= dev['start'] and + callend >= dev['end']): + dev['ftrace'] = cg.slice(dev['start'], dev['end']) continue - callstart = ftemp[pid].start - callend = ftemp[pid].end - for p in data.phases: - if(data.dmesg[p]['start'] <= callstart and callstart <= data.dmesg[p]['end']): - list = data.dmesg[p]['list'] + if(cg.list[0].name != 'dpm_run_callback'): + continue + for p in test.data.phases: + if(test.data.dmesg[p]['start'] <= callstart and + callstart <= test.data.dmesg[p]['end']): + list = test.data.dmesg[p]['list'] for devname in list: dev = list[devname] - if(pid == dev['pid'] and callstart <= dev['start'] and callend >= dev['end']): - data.vprint("%15s [%f - %f] %s(%d)" % (p, callstart, callend, devname, pid)) - dev['ftrace'] = ftemp[pid] + if(pid == dev['pid'] and + callstart <= dev['start'] and + callend >= dev['end']): + dev['ftrace'] = cg break - ftemp[pid] = FTraceCallGraph() - tf.close() -# Function: sortKernelLog + # fill in any missing phases + for data in testdata: + lp = data.phases[0] + for p in data.phases: + if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0): + print('WARNING: phase "%s" is missing!' % p) + if(data.dmesg[p]['start'] < 0): + data.dmesg[p]['start'] = data.dmesg[lp]['end'] + if(p == 'resume_machine'): + data.tSuspended = data.dmesg[lp]['end'] + data.tResumed = data.dmesg[lp]['end'] + data.tLow = 0 + if(data.dmesg[p]['end'] < 0): + data.dmesg[p]['end'] = data.dmesg[p]['start'] + lp = p + + if(len(sysvals.devicefilter) > 0): + data.deviceFilter(sysvals.devicefilter) + data.fixupInitcallsThatDidntReturn() + if(sysvals.verbose): + data.printDetails() + + # add the time in between the tests as a new phase so we can see it + if(len(testdata) > 1): + t1e = testdata[0].getEnd() + t2s = testdata[-1].getStart() + testdata[-1].newPhaseWithSingleAction('user mode', \ + 'user mode', t1e, t2s, '#FF9966') + return testdata + +# Function: loadKernelLog # Description: -# The dmesg output log sometimes comes with with lines that have -# timestamps out of order. This could cause issues since a call -# could accidentally end up in the wrong phase -def sortKernelLog(): - global sysvals, data +# [deprecated for kernel 3.15.0 or newer] +# load the dmesg file into memory and fix up any ordering issues +# The dmesg filename is taken from sysvals +# Output: +# An array of empty Data objects with only their dmesgtext attributes set +def loadKernelLog(): + global sysvals + + vprint('Analyzing the dmesg data...') + if(os.path.exists(sysvals.dmesgfile) == False): + doError('%s doesnt exist' % sysvals.dmesgfile, False) + + # there can be multiple test runs in a single file delineated by stamps + testruns = [] + data = 0 lf = open(sysvals.dmesgfile, 'r') - dmesglist = [] - count = 0 for line in lf: - line = line.replace("\r\n", "") - if(count == 0): - parseStamp(line) - elif(count == 1): - m = re.match(r"# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$", line) - if(m): - data.fwSuspend = int(m.group("s")) - data.fwResume = int(m.group("r")) - if(data.fwSuspend > 0 or data.fwResume > 0): - data.fwValid = True - if(re.match(r".*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)", line)): - dmesglist.append(line) - count += 1 + line = line.replace('\r\n', '') + idx = line.find('[') + if idx > 1: + line = line[idx:] + m = re.match(sysvals.stampfmt, line) + if(m): + if(data): + testruns.append(data) + data = Data(len(testruns)) + parseStamp(m, data) + continue + if(not data): + continue + m = re.match(sysvals.firmwarefmt, line) + if(m): + data.fwSuspend = int(m.group('s')) + data.fwResume = int(m.group('r')) + if(data.fwSuspend > 0 or data.fwResume > 0): + data.fwValid = True + continue + m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) + if(m): + data.dmesgtext.append(line) + if(re.match('ACPI: resume from mwait', m.group('msg'))): + print('NOTE: This suspend appears to be freeze rather than'+\ + ' %s, it will be treated as such' % sysvals.suspendmode) + sysvals.suspendmode = 'freeze' + else: + vprint('ignoring dmesg line: %s' % line.replace('\n', '')) + testruns.append(data) lf.close() - last = "" - - # fix lines with the same time stamp and function with the call and return swapped - for line in dmesglist: - mc = re.match(r".*(\[ *)(?P<t>[0-9\.]*)(\]) calling (?P<f>.*)\+ @ .*, parent: .*", line) - mr = re.match(r".*(\[ *)(?P<t>[0-9\.]*)(\]) call (?P<f>.*)\+ returned .* after (?P<dt>.*) usecs", last) - if(mc and mr and (mc.group("t") == mr.group("t")) and (mc.group("f") == mr.group("f"))): - i = dmesglist.index(last) - j = dmesglist.index(line) - dmesglist[i] = line - dmesglist[j] = last - last = line - return dmesglist - -# Function: analyzeKernelLog + + if(not data): + print('ERROR: analyze_suspend header missing from dmesg log') + sys.exit() + + # fix lines with same timestamp/function with the call and return swapped + for data in testruns: + last = '' + for line in data.dmesgtext: + mc = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) calling '+\ + '(?P<f>.*)\+ @ .*, parent: .*', line) + mr = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) call '+\ + '(?P<f>.*)\+ returned .* after (?P<dt>.*) usecs', last) + if(mc and mr and (mc.group('t') == mr.group('t')) and + (mc.group('f') == mr.group('f'))): + i = data.dmesgtext.index(last) + j = data.dmesgtext.index(line) + data.dmesgtext[i] = line + data.dmesgtext[j] = last + last = line + return testruns + +# Function: parseKernelLog # Description: +# [deprecated for kernel 3.15.0 or newer] # Analyse a dmesg log output file generated from this app during # the execution phase. Create a set of device structures in memory # for subsequent formatting in the html output file -def analyzeKernelLog(): - global sysvals, data +# This call is only for legacy support on kernels where the ftrace +# data lacks the suspend_resume or device_pm_callbacks trace events. +# Arguments: +# data: an empty Data object (with dmesgtext) obtained from loadKernelLog +# Output: +# The filled Data object +def parseKernelLog(data): + global sysvals - print("PROCESSING DATA") - data.vprint("Analyzing the dmesg data...") - if(os.path.exists(sysvals.dmesgfile) == False): - print("ERROR: %s doesn't exist") % sysvals.dmesgfile - return False + phase = 'suspend_runtime' - lf = sortKernelLog() - phase = "suspend_runtime" + if(data.fwValid): + vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \ + (data.fwSuspend, data.fwResume)) + # dmesg phase match table dm = { - 'suspend_general': r"PM: Syncing filesystems.*", - 'suspend_early': r"PM: suspend of devices complete after.*", - 'suspend_noirq': r"PM: late suspend of devices complete after.*", - 'suspend_cpu': r"PM: noirq suspend of devices complete after.*", - 'resume_cpu': r"ACPI: Low-level resume complete.*", - 'resume_noirq': r"ACPI: Waking up from system sleep state.*", - 'resume_early': r"PM: noirq resume of devices complete after.*", - 'resume_general': r"PM: early resume of devices complete after.*", - 'resume_complete': r".*Restarting tasks \.\.\..*", + 'suspend_prepare': 'PM: Syncing filesystems.*', + 'suspend': 'PM: Entering [a-z]* sleep.*', + 'suspend_late': 'PM: suspend of devices complete after.*', + 'suspend_noirq': 'PM: late suspend of devices complete after.*', + 'suspend_machine': 'PM: noirq suspend of devices complete after.*', + 'resume_machine': 'ACPI: Low-level resume complete.*', + 'resume_noirq': 'ACPI: Waking up from system sleep state.*', + 'resume_early': 'PM: noirq resume of devices complete after.*', + 'resume': 'PM: early resume of devices complete after.*', + 'resume_complete': 'PM: resume of devices complete after.*', + 'post_resume': '.*Restarting tasks \.\.\..*', } - if(sysvals.suspendmode == "standby"): - dm['resume_cpu'] = r"PM: Restoring platform NVS memory" - elif(sysvals.suspendmode == "disk"): - dm['suspend_early'] = r"PM: freeze of devices complete after.*" - dm['suspend_noirq'] = r"PM: late freeze of devices complete after.*" - dm['suspend_cpu'] = r"PM: noirq freeze of devices complete after.*" - dm['resume_cpu'] = r"PM: Restoring platform NVS memory" - dm['resume_early'] = r"PM: noirq restore of devices complete after.*" - dm['resume_general'] = r"PM: early restore of devices complete after.*" - - action_start = 0.0 - for line in lf: + if(sysvals.suspendmode == 'standby'): + dm['resume_machine'] = 'PM: Restoring platform NVS memory' + elif(sysvals.suspendmode == 'disk'): + dm['suspend_late'] = 'PM: freeze of devices complete after.*' + dm['suspend_noirq'] = 'PM: late freeze of devices complete after.*' + dm['suspend_machine'] = 'PM: noirq freeze of devices complete after.*' + dm['resume_machine'] = 'PM: Restoring platform NVS memory' + dm['resume_early'] = 'PM: noirq restore of devices complete after.*' + dm['resume'] = 'PM: early restore of devices complete after.*' + dm['resume_complete'] = 'PM: restore of devices complete after.*' + elif(sysvals.suspendmode == 'freeze'): + dm['resume_machine'] = 'ACPI: resume from mwait' + + # action table (expected events that occur and show up in dmesg) + at = { + 'sync_filesystems': { + 'smsg': 'PM: Syncing filesystems.*', + 'emsg': 'PM: Preparing system for mem sleep.*' }, + 'freeze_user_processes': { + 'smsg': 'Freezing user space processes .*', + 'emsg': 'Freezing remaining freezable tasks.*' }, + 'freeze_tasks': { + 'smsg': 'Freezing remaining freezable tasks.*', + 'emsg': 'PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*' }, + 'ACPI prepare': { + 'smsg': 'ACPI: Preparing to enter system sleep state.*', + 'emsg': 'PM: Saving platform NVS memory.*' }, + 'PM vns': { + 'smsg': 'PM: Saving platform NVS memory.*', + 'emsg': 'Disabling non-boot CPUs .*' }, + } + + t0 = -1.0 + cpu_start = -1.0 + prevktime = -1.0 + actions = dict() + for line in data.dmesgtext: # -- preprocessing -- # parse each dmesg line into the time and message - m = re.match(r".*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)", line) + m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) if(m): - ktime = float(m.group("ktime")) - msg = m.group("msg") + val = m.group('ktime') + try: + ktime = float(val) + except: + doWarning('INVALID DMESG LINE: '+\ + line.replace('\n', ''), 'dmesg') + continue + msg = m.group('msg') + # initialize data start to first line time + if t0 < 0: + data.setStart(ktime) + t0 = ktime else: - print line continue + # hack for determining resume_machine end for freeze + if(not sysvals.usetraceevents and sysvals.suspendmode == 'freeze' \ + and phase == 'resume_machine' and \ + re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): + data.dmesg['resume_machine']['end'] = ktime + phase = 'resume_noirq' + data.dmesg[phase]['start'] = ktime + # -- phase changes -- - # suspend_general start - if(re.match(dm['suspend_general'], msg)): - phase = "suspend_general" + # suspend start + if(re.match(dm['suspend_prepare'], msg)): + phase = 'suspend_prepare' + data.dmesg[phase]['start'] = ktime + data.setStart(ktime) + # suspend start + elif(re.match(dm['suspend'], msg)): + data.dmesg['suspend_prepare']['end'] = ktime + phase = 'suspend' data.dmesg[phase]['start'] = ktime - data.start = ktime - # action start: syncing filesystems - action_start = ktime - # suspend_early start - elif(re.match(dm['suspend_early'], msg)): - data.dmesg["suspend_general"]['end'] = ktime - phase = "suspend_early" + # suspend_late start + elif(re.match(dm['suspend_late'], msg)): + data.dmesg['suspend']['end'] = ktime + phase = 'suspend_late' data.dmesg[phase]['start'] = ktime # suspend_noirq start elif(re.match(dm['suspend_noirq'], msg)): - data.dmesg["suspend_early"]['end'] = ktime - phase = "suspend_noirq" + data.dmesg['suspend_late']['end'] = ktime + phase = 'suspend_noirq' data.dmesg[phase]['start'] = ktime - # suspend_cpu start - elif(re.match(dm['suspend_cpu'], msg)): - data.dmesg["suspend_noirq"]['end'] = ktime - phase = "suspend_cpu" + # suspend_machine start + elif(re.match(dm['suspend_machine'], msg)): + data.dmesg['suspend_noirq']['end'] = ktime + phase = 'suspend_machine' data.dmesg[phase]['start'] = ktime - # resume_cpu start - elif(re.match(dm['resume_cpu'], msg)): - data.tSuspended = ktime - data.dmesg["suspend_cpu"]['end'] = ktime - phase = "resume_cpu" + # resume_machine start + elif(re.match(dm['resume_machine'], msg)): + if(sysvals.suspendmode in ['freeze', 'standby']): + data.tSuspended = prevktime + data.dmesg['suspend_machine']['end'] = prevktime + else: + data.tSuspended = ktime + data.dmesg['suspend_machine']['end'] = ktime + phase = 'resume_machine' + data.tResumed = ktime + data.tLow = data.tResumed - data.tSuspended data.dmesg[phase]['start'] = ktime # resume_noirq start elif(re.match(dm['resume_noirq'], msg)): - data.dmesg["resume_cpu"]['end'] = ktime - phase = "resume_noirq" + data.dmesg['resume_machine']['end'] = ktime + phase = 'resume_noirq' data.dmesg[phase]['start'] = ktime - # action end: ACPI resume - data.newAction("resume_cpu", "ACPI", -1, "", action_start, ktime) # resume_early start elif(re.match(dm['resume_early'], msg)): - data.dmesg["resume_noirq"]['end'] = ktime - phase = "resume_early" + data.dmesg['resume_noirq']['end'] = ktime + phase = 'resume_early' data.dmesg[phase]['start'] = ktime - # resume_general start - elif(re.match(dm['resume_general'], msg)): - data.dmesg["resume_early"]['end'] = ktime - phase = "resume_general" + # resume start + elif(re.match(dm['resume'], msg)): + data.dmesg['resume_early']['end'] = ktime + phase = 'resume' data.dmesg[phase]['start'] = ktime # resume complete start elif(re.match(dm['resume_complete'], msg)): - data.dmesg["resume_general"]['end'] = ktime - data.end = ktime - phase = "resume_runtime" + data.dmesg['resume']['end'] = ktime + phase = 'resume_complete' + data.dmesg[phase]['start'] = ktime + # post resume start + elif(re.match(dm['post_resume'], msg)): + data.dmesg['resume_complete']['end'] = ktime + data.setEnd(ktime) + phase = 'post_resume' break # -- device callbacks -- if(phase in data.phases): # device init call - if(re.match(r"calling (?P<f>.*)\+ @ .*, parent: .*", msg)): - sm = re.match(r"calling (?P<f>.*)\+ @ (?P<n>.*), parent: (?P<p>.*)", msg); - f = sm.group("f") - n = sm.group("n") - p = sm.group("p") + if(re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): + sm = re.match('calling (?P<f>.*)\+ @ '+\ + '(?P<n>.*), parent: (?P<p>.*)', msg); + f = sm.group('f') + n = sm.group('n') + p = sm.group('p') if(f and n and p): - data.newAction(phase, f, int(n), p, ktime, -1) + data.newAction(phase, f, int(n), p, ktime, -1, '') # device init return - elif(re.match(r"call (?P<f>.*)\+ returned .* after (?P<t>.*) usecs", msg)): - sm = re.match(r"call (?P<f>.*)\+ returned .* after (?P<t>.*) usecs(?P<a>.*)", msg); - f = sm.group("f") - t = sm.group("t") + elif(re.match('call (?P<f>.*)\+ returned .* after '+\ + '(?P<t>.*) usecs', msg)): + sm = re.match('call (?P<f>.*)\+ returned .* after '+\ + '(?P<t>.*) usecs(?P<a>.*)', msg); + f = sm.group('f') + t = sm.group('t') list = data.dmesg[phase]['list'] if(f in list): dev = list[f] dev['length'] = int(t) dev['end'] = ktime - data.vprint("%15s [%f - %f] %s(%d) %s" % - (phase, dev['start'], dev['end'], f, dev['pid'], dev['par'])) - - # -- phase specific actions -- - if(phase == "suspend_general"): - if(re.match(r"PM: Preparing system for mem sleep.*", msg)): - data.newAction(phase, "filesystem-sync", -1, "", action_start, ktime) - elif(re.match(r"Freezing user space processes .*", msg)): - action_start = ktime - elif(re.match(r"Freezing remaining freezable tasks.*", msg)): - data.newAction(phase, "freeze-user-processes", -1, "", action_start, ktime) - action_start = ktime - elif(re.match(r"PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*", msg)): - data.newAction(phase, "freeze-tasks", -1, "", action_start, ktime) - elif(phase == "suspend_cpu"): - m = re.match(r"smpboot: CPU (?P<cpu>[0-9]*) is now offline", msg) - if(m): - cpu = "CPU"+m.group("cpu") - data.newAction(phase, cpu, -1, "", action_start, ktime) - action_start = ktime - elif(re.match(r"ACPI: Preparing to enter system sleep state.*", msg)): - action_start = ktime - elif(re.match(r"Disabling non-boot CPUs .*", msg)): - data.newAction(phase, "ACPI", -1, "", action_start, ktime) - action_start = ktime - elif(phase == "resume_cpu"): - m = re.match(r"CPU(?P<cpu>[0-9]*) is up", msg) - if(m): - cpu = "CPU"+m.group("cpu") - data.newAction(phase, cpu, -1, "", action_start, ktime) - action_start = ktime - elif(re.match(r"Enabling non-boot CPUs .*", msg)): - action_start = ktime + + # -- non-devicecallback actions -- + # if trace events are not available, these are better than nothing + if(not sysvals.usetraceevents): + # look for known actions + for a in at: + if(re.match(at[a]['smsg'], msg)): + if(a not in actions): + actions[a] = [] + actions[a].append({'begin': ktime, 'end': ktime}) + if(re.match(at[a]['emsg'], msg)): + actions[a][-1]['end'] = ktime + # now look for CPU on/off events + if(re.match('Disabling non-boot CPUs .*', msg)): + # start of first cpu suspend + cpu_start = ktime + elif(re.match('Enabling non-boot CPUs .*', msg)): + # start of first cpu resume + cpu_start = ktime + elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)): + # end of a cpu suspend, start of the next + m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg) + cpu = 'CPU'+m.group('cpu') + if(cpu not in actions): + actions[cpu] = [] + actions[cpu].append({'begin': cpu_start, 'end': ktime}) + cpu_start = ktime + elif(re.match('CPU(?P<cpu>[0-9]*) is up', msg)): + # end of a cpu resume, start of the next + m = re.match('CPU(?P<cpu>[0-9]*) is up', msg) + cpu = 'CPU'+m.group('cpu') + if(cpu not in actions): + actions[cpu] = [] + actions[cpu].append({'begin': cpu_start, 'end': ktime}) + cpu_start = ktime + prevktime = ktime # fill in any missing phases - lp = "suspend_general" + lp = data.phases[0] for p in data.phases: - if(p == "suspend_general"): - continue + if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0): + print('WARNING: phase "%s" is missing, something went wrong!' % p) + print(' In %s, this dmesg line denotes the start of %s:' % \ + (sysvals.suspendmode, p)) + print(' "%s"' % dm[p]) if(data.dmesg[p]['start'] < 0): data.dmesg[p]['start'] = data.dmesg[lp]['end'] - if(p == "resume_cpu"): + if(p == 'resume_machine'): data.tSuspended = data.dmesg[lp]['end'] + data.tResumed = data.dmesg[lp]['end'] + data.tLow = 0 if(data.dmesg[p]['end'] < 0): data.dmesg[p]['end'] = data.dmesg[p]['start'] lp = p + # fill in any actions we've found + for name in actions: + for event in actions[name]: + begin = event['begin'] + end = event['end'] + # if event starts before timeline start, expand timeline + if(begin < data.start): + data.setStart(begin) + # if event ends after timeline end, expand the timeline + if(end > data.end): + data.setEnd(end) + data.newActionGlobal(name, begin, end) + + if(sysvals.verbose): + data.printDetails() + if(len(sysvals.devicefilter) > 0): + data.deviceFilter(sysvals.devicefilter) data.fixupInitcallsThatDidntReturn() return True # Function: setTimelineRows # Description: -# Organize the device or thread lists into the smallest +# Organize the timeline entries into the smallest # number of rows possible, with no entry overlapping # Arguments: -# list: the list to sort (dmesg or ftrace) -# sortedkeys: sorted key list to use +# list: the list of devices/actions for a single phase +# sortedkeys: cronologically sorted key list to use +# Output: +# The total number of rows needed to display this phase of the timeline def setTimelineRows(list, sortedkeys): - global data # clear all rows and set them to undefined remaining = len(list) @@ -791,7 +1959,8 @@ def setTimelineRows(list, sortedkeys): for ritem in rowdata[row]: rs = ritem['start'] re = ritem['end'] - if(not (((s <= rs) and (e <= rs)) or ((s >= re) and (e >= re)))): + if(not (((s <= rs) and (e <= rs)) or + ((s >= re) and (e >= re)))): valid = False break if(valid): @@ -803,14 +1972,15 @@ def setTimelineRows(list, sortedkeys): # Function: createTimeScale # Description: -# Create timescale lines for the dmesg and ftrace timelines +# Create the timescale header for the html timeline # Arguments: # t0: start time (suspend begin) # tMax: end time (resume end) -# tSuspend: time when suspend occurs +# tSuspend: time when suspend occurs, i.e. the zero time +# Output: +# The html code needed to display the time scale def createTimeScale(t0, tMax, tSuspended): - global data - timescale = "<div class=\"t\" style=\"right:{0}%\">{1}</div>\n" + timescale = '<div class="t" style="right:{0}%">{1}</div>\n' output = '<div id="timescale">\n' # set scale for timeline @@ -822,11 +1992,11 @@ def createTimeScale(t0, tMax, tSuspended): tS = 1 if(tSuspended < 0): for i in range(int(tTotal/tS)+1): - pos = "%0.3f" % (100 - ((float(i)*tS*100)/tTotal)) + pos = '%0.3f' % (100 - ((float(i)*tS*100)/tTotal)) if(i > 0): - val = "%0.f" % (float(i)*tS*1000) + val = '%0.fms' % (float(i)*tS*1000) else: - val = "" + val = '' output += timescale.format(pos, val) else: tSuspend = tSuspended - t0 @@ -834,69 +2004,253 @@ def createTimeScale(t0, tMax, tSuspended): divSuspend = int(tSuspend/tS) s0 = (tSuspend - tS*divSuspend)*100/tTotal for i in range(divTotal): - pos = "%0.3f" % (100 - ((float(i)*tS*100)/tTotal) - s0) + pos = '%0.3f' % (100 - ((float(i)*tS*100)/tTotal) - s0) if((i == 0) and (s0 < 3)): - val = "" + val = '' elif(i == divSuspend): - val = "S/R" + val = 'S/R' else: - val = "%0.f" % (float(i-divSuspend)*tS*1000) + val = '%0.fms' % (float(i-divSuspend)*tS*1000) output += timescale.format(pos, val) output += '</div>\n' return output +# Function: createHTMLSummarySimple +# Description: +# Create summary html file for a series of tests +# Arguments: +# testruns: array of Data objects from parseTraceLog +def createHTMLSummarySimple(testruns, htmlfile): + global sysvals + + # print out the basic summary of all the tests + hf = open(htmlfile, 'w') + + # write the html header first (html head, css code, up to body start) + html = '<!DOCTYPE html>\n<html>\n<head>\n\ + <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\ + <title>AnalyzeSuspend Summary</title>\n\ + <style type=\'text/css\'>\n\ + body {overflow-y: scroll;}\n\ + .stamp {width: 100%;text-align:center;background-color:#495E09;line-height:30px;color:white;font: 25px Arial;}\n\ + table {width:100%;border-collapse: collapse;}\n\ + .summary {font: 22px Arial;border:1px solid;}\n\ + th {border: 1px solid black;background-color:#A7C942;color:white;}\n\ + td {text-align: center;}\n\ + tr.alt td {background-color:#EAF2D3;}\n\ + tr.avg td {background-color:#BDE34C;}\n\ + a:link {color: #90B521;}\n\ + a:visited {color: #495E09;}\n\ + a:hover {color: #B1DF28;}\n\ + a:active {color: #FFFFFF;}\n\ + </style>\n</head>\n<body>\n' + + # group test header + count = len(testruns) + headline_stamp = '<div class="stamp">{0} {1} {2} {3} ({4} tests)</div>\n' + html += headline_stamp.format(sysvals.stamp['host'], + sysvals.stamp['kernel'], sysvals.stamp['mode'], + sysvals.stamp['time'], count) + + # check to see if all the tests have the same value + stampcolumns = False + for data in testruns: + if diffStamp(sysvals.stamp, data.stamp): + stampcolumns = True + break + + th = '\t<th>{0}</th>\n' + td = '\t<td>{0}</td>\n' + tdlink = '\t<td><a href="{0}">Click Here</a></td>\n' + + # table header + html += '<table class="summary">\n<tr>\n' + html += th.format("Test #") + if stampcolumns: + html += th.format("Hostname") + html += th.format("Kernel Version") + html += th.format("Suspend Mode") + html += th.format("Test Time") + html += th.format("Suspend Time") + html += th.format("Resume Time") + html += th.format("Detail") + html += '</tr>\n' + + # test data, 1 row per test + sTimeAvg = 0.0 + rTimeAvg = 0.0 + num = 1 + for data in testruns: + # data.end is the end of post_resume + resumeEnd = data.dmesg['resume_complete']['end'] + if num % 2 == 1: + html += '<tr class="alt">\n' + else: + html += '<tr>\n' + + # test num + html += td.format("test %d" % num) + num += 1 + if stampcolumns: + # host name + val = "unknown" + if('host' in data.stamp): + val = data.stamp['host'] + html += td.format(val) + # host kernel + val = "unknown" + if('kernel' in data.stamp): + val = data.stamp['kernel'] + html += td.format(val) + # suspend mode + val = "unknown" + if('mode' in data.stamp): + val = data.stamp['mode'] + html += td.format(val) + # test time + val = "unknown" + if('time' in data.stamp): + val = data.stamp['time'] + html += td.format(val) + # suspend time + sTime = (data.tSuspended - data.start)*1000 + sTimeAvg += sTime + html += td.format("%3.3f ms" % sTime) + # resume time + rTime = (resumeEnd - data.tResumed)*1000 + rTimeAvg += rTime + html += td.format("%3.3f ms" % rTime) + # link to the output html + html += tdlink.format(data.outfile) + + html += '</tr>\n' + + # last line: test average + if(count > 0): + sTimeAvg /= count + rTimeAvg /= count + html += '<tr class="avg">\n' + html += td.format('Average') # name + if stampcolumns: + html += td.format('') # host + html += td.format('') # kernel + html += td.format('') # mode + html += td.format('') # time + html += td.format("%3.3f ms" % sTimeAvg) # suspend time + html += td.format("%3.3f ms" % rTimeAvg) # resume time + html += td.format('') # output link + html += '</tr>\n' + + # flush the data to file + hf.write(html+'</table>\n') + hf.write('</body>\n</html>\n') + hf.close() + # Function: createHTML # Description: -# Create the output html file. -def createHTML(): - global sysvals, data +# Create the output html file from the resident test data +# Arguments: +# testruns: array of Data objects from parseKernelLog or parseTraceLog +# Output: +# True if the html file was created, false if it failed +def createHTML(testruns): + global sysvals - data.normalizeTime() + for data in testruns: + data.normalizeTime(testruns[-1].tSuspended) + x2changes = ['', 'absolute'] + if len(testruns) > 1: + x2changes = ['1', 'relative'] # html function templates headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' - html_zoombox = '<center><button id="zoomin">ZOOM IN</button><button id="zoomout">ZOOM OUT</button><button id="zoomdef">ZOOM 1:1</button></center>\n<div id="dmesgzoombox" class="zoombox">\n' - html_timeline = '<div id="{0}" class="timeline" style="height:{1}px">\n' + html_devlist1 = '<button id="devlist1" class="devlist" style="float:left;">Device Detail%s</button>' % x2changes[0] + html_zoombox = '<center><button id="zoomin">ZOOM IN</button><button id="zoomout">ZOOM OUT</button><button id="zoomdef">ZOOM 1:1</button></center>\n' + html_devlist2 = '<button id="devlist2" class="devlist" style="float:right;">Device Detail2</button>\n' + html_timeline = '<div id="dmesgzoombox" class="zoombox">\n<div id="{0}" class="timeline" style="height:{1}px">\n' html_device = '<div id="{0}" title="{1}" class="thread" style="left:{2}%;top:{3}%;height:{4}%;width:{5}%;">{6}</div>\n' + html_traceevent = '<div title="{0}" class="traceevent" style="left:{1}%;top:{2}%;height:{3}%;width:{4}%;border:1px solid {5};background-color:{5}">{6}</div>\n' html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}%;height:{3}%;background-color:{4}">{5}</div>\n' + html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background-color:{3}"></div>\n' html_legend = '<div class="square" style="left:{0}%;background-color:{1}"> {2}</div>\n' html_timetotal = '<table class="time1">\n<tr>'\ - '<td class="gray">{2} Suspend Time: <b>{0} ms</b></td>'\ - '<td class="gray">{2} Resume Time: <b>{1} ms</b></td>'\ + '<td class="green">{2} Suspend Time: <b>{0} ms</b></td>'\ + '<td class="yellow">{2} Resume Time: <b>{1} ms</b></td>'\ + '</tr>\n</table>\n' + html_timetotal2 = '<table class="time1">\n<tr>'\ + '<td class="green">{3} Suspend Time: <b>{0} ms</b></td>'\ + '<td class="gray">'+sysvals.suspendmode+' time: <b>{1} ms</b></td>'\ + '<td class="yellow">{3} Resume Time: <b>{2} ms</b></td>'\ '</tr>\n</table>\n' html_timegroups = '<table class="time2">\n<tr>'\ - '<td class="green">Kernel Suspend: {0} ms</td>'\ - '<td class="purple">Firmware Suspend: {1} ms</td>'\ - '<td class="purple">Firmware Resume: {2} ms</td>'\ - '<td class="yellow">Kernel Resume: {3} ms</td>'\ + '<td class="green">{4}Kernel Suspend: {0} ms</td>'\ + '<td class="purple">{4}Firmware Suspend: {1} ms</td>'\ + '<td class="purple">{4}Firmware Resume: {2} ms</td>'\ + '<td class="yellow">{4}Kernel Resume: {3} ms</td>'\ '</tr>\n</table>\n' - # device timeline (dmesg) - if(data.usedmesg): - data.vprint("Creating Device Timeline...") - devtl = Timeline() + # device timeline + vprint('Creating Device Timeline...') + devtl = Timeline() - # Generate the header for this timeline - t0 = data.start - tMax = data.end - tTotal = tMax - t0 + # Generate the header for this timeline + textnum = ['First', 'Second'] + for data in testruns: + tTotal = data.end - data.start + tEnd = data.dmesg['resume_complete']['end'] if(tTotal == 0): - print("ERROR: No timeline data") + print('ERROR: No timeline data') sys.exit() - suspend_time = "%.0f"%(-data.start*1000) - resume_time = "%.0f"%(data.end*1000) + if(data.tLow > 0): + low_time = '%.0f'%(data.tLow*1000) if data.fwValid: - devtl.html['timeline'] = html_timetotal.format(suspend_time, resume_time, "Total") - sktime = "%.3f"%((data.dmesg['suspend_cpu']['end'] - data.dmesg['suspend_general']['start'])*1000) - sftime = "%.3f"%(data.fwSuspend / 1000000.0) - rftime = "%.3f"%(data.fwResume / 1000000.0) - rktime = "%.3f"%((data.dmesg['resume_general']['end'] - data.dmesg['resume_cpu']['start'])*1000) - devtl.html['timeline'] += html_timegroups.format(sktime, sftime, rftime, rktime) + suspend_time = '%.0f'%((data.tSuspended-data.start)*1000 + \ + (data.fwSuspend/1000000.0)) + resume_time = '%.0f'%((tEnd-data.tSuspended)*1000 + \ + (data.fwResume/1000000.0)) + testdesc1 = 'Total' + testdesc2 = '' + if(len(testruns) > 1): + testdesc1 = testdesc2 = textnum[data.testnumber] + testdesc2 += ' ' + if(data.tLow == 0): + thtml = html_timetotal.format(suspend_time, \ + resume_time, testdesc1) + else: + thtml = html_timetotal2.format(suspend_time, low_time, \ + resume_time, testdesc1) + devtl.html['timeline'] += thtml + sktime = '%.3f'%((data.dmesg['suspend_machine']['end'] - \ + data.getStart())*1000) + sftime = '%.3f'%(data.fwSuspend / 1000000.0) + rftime = '%.3f'%(data.fwResume / 1000000.0) + rktime = '%.3f'%((data.getEnd() - \ + data.dmesg['resume_machine']['start'])*1000) + devtl.html['timeline'] += html_timegroups.format(sktime, \ + sftime, rftime, rktime, testdesc2) else: - devtl.html['timeline'] = html_timetotal.format(suspend_time, resume_time, "Kernel") + suspend_time = '%.0f'%((data.tSuspended-data.start)*1000) + resume_time = '%.0f'%((tEnd-data.tSuspended)*1000) + testdesc = 'Kernel' + if(len(testruns) > 1): + testdesc = textnum[data.testnumber]+' '+testdesc + if(data.tLow == 0): + thtml = html_timetotal.format(suspend_time, \ + resume_time, testdesc) + else: + thtml = html_timetotal2.format(suspend_time, low_time, \ + resume_time, testdesc) + devtl.html['timeline'] += thtml + + # time scale for potentially multiple datasets + t0 = testruns[0].start + tMax = testruns[-1].end + tSuspended = testruns[-1].tSuspended + tTotal = tMax - t0 - # determine the maximum number of rows we need to draw - timelinerows = 0 + # determine the maximum number of rows we need to draw + timelinerows = 0 + for data in testruns: for phase in data.dmesg: list = data.dmesg[phase]['list'] rows = setTimelineRows(list, list) @@ -904,62 +2258,104 @@ def createHTML(): if(rows > timelinerows): timelinerows = rows - # calculate the timeline height and create its bounding box - devtl.setRows(timelinerows + 1) - devtl.html['timeline'] += html_zoombox; - devtl.html['timeline'] += html_timeline.format("dmesg", devtl.height); + # calculate the timeline height and create bounding box, add buttons + devtl.setRows(timelinerows + 1) + devtl.html['timeline'] += html_devlist1 + if len(testruns) > 1: + devtl.html['timeline'] += html_devlist2 + devtl.html['timeline'] += html_zoombox + devtl.html['timeline'] += html_timeline.format('dmesg', devtl.height) - # draw the colored boxes for each of the phases + # draw the colored boxes for each of the phases + for data in testruns: for b in data.dmesg: phase = data.dmesg[b] - left = "%.3f" % (((phase['start']-data.start)*100)/tTotal) - width = "%.3f" % (((phase['end']-phase['start'])*100)/tTotal) - devtl.html['timeline'] += html_phase.format(left, width, "%.3f"%devtl.scaleH, "%.3f"%(100-devtl.scaleH), data.dmesg[b]['color'], "") - - # draw the time scale, try to make the number of labels readable - devtl.html['scale'] = createTimeScale(t0, tMax, data.tSuspended) - devtl.html['timeline'] += devtl.html['scale'] + length = phase['end']-phase['start'] + left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal) + width = '%.3f' % ((length*100.0)/tTotal) + devtl.html['timeline'] += html_phase.format(left, width, \ + '%.3f'%devtl.scaleH, '%.3f'%(100-devtl.scaleH), \ + data.dmesg[b]['color'], '') + + # draw the time scale, try to make the number of labels readable + devtl.html['scale'] = createTimeScale(t0, tMax, tSuspended) + devtl.html['timeline'] += devtl.html['scale'] + for data in testruns: for b in data.dmesg: phaselist = data.dmesg[b]['list'] for d in phaselist: name = d - if(d in data.altdevname): - name = data.altdevname[d] + drv = '' dev = phaselist[d] + if(d in sysvals.altdevname): + name = sysvals.altdevname[d] + if('drv' in dev and dev['drv']): + drv = ' {%s}' % dev['drv'] height = (100.0 - devtl.scaleH)/data.dmesg[b]['row'] - top = "%.3f" % ((dev['row']*height) + devtl.scaleH) - left = "%.3f" % (((dev['start']-data.start)*100)/tTotal) - width = "%.3f" % (((dev['end']-dev['start'])*100)/tTotal) - len = " (%0.3f ms) " % ((dev['end']-dev['start'])*1000) - color = "rgba(204,204,204,0.5)" - devtl.html['timeline'] += html_device.format(dev['id'], name+len+b, left, top, "%.3f"%height, width, name) - - # timeline is finished - devtl.html['timeline'] += "</div>\n</div>\n" - - # draw a legend which describes the phases by color - devtl.html['legend'] = "<div class=\"legend\">\n" - pdelta = 100.0/data.phases.__len__() - pmargin = pdelta / 4.0 - for phase in data.phases: - order = "%.2f" % ((data.dmesg[phase]['order'] * pdelta) + pmargin) - name = string.replace(phase, "_", " ") - devtl.html['legend'] += html_legend.format(order, data.dmesg[phase]['color'], name) - devtl.html['legend'] += "</div>\n" + top = '%.3f' % ((dev['row']*height) + devtl.scaleH) + left = '%.3f' % (((dev['start']-t0)*100)/tTotal) + width = '%.3f' % (((dev['end']-dev['start'])*100)/tTotal) + length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000) + color = 'rgba(204,204,204,0.5)' + devtl.html['timeline'] += html_device.format(dev['id'], \ + d+drv+length+b, left, top, '%.3f'%height, width, name+drv) + + # draw any trace events found + for data in testruns: + for b in data.dmesg: + phaselist = data.dmesg[b]['list'] + for name in phaselist: + dev = phaselist[name] + if('traceevents' in dev): + vprint('Debug trace events found for device %s' % name) + vprint('%20s %20s %10s %8s' % ('action', \ + 'name', 'time(ms)', 'length(ms)')) + for e in dev['traceevents']: + vprint('%20s %20s %10.3f %8.3f' % (e.action, \ + e.name, e.time*1000, e.length*1000)) + height = (100.0 - devtl.scaleH)/data.dmesg[b]['row'] + top = '%.3f' % ((dev['row']*height) + devtl.scaleH) + left = '%.3f' % (((e.time-t0)*100)/tTotal) + width = '%.3f' % (e.length*100/tTotal) + color = 'rgba(204,204,204,0.5)' + devtl.html['timeline'] += \ + html_traceevent.format(e.action+' '+e.name, \ + left, top, '%.3f'%height, \ + width, e.color, '') + + # timeline is finished + devtl.html['timeline'] += '</div>\n</div>\n' + + # draw a legend which describes the phases by color + data = testruns[-1] + devtl.html['legend'] = '<div class="legend">\n' + pdelta = 100.0/len(data.phases) + pmargin = pdelta / 4.0 + for phase in data.phases: + order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin) + name = string.replace(phase, '_', ' ') + devtl.html['legend'] += html_legend.format(order, \ + data.dmesg[phase]['color'], name) + devtl.html['legend'] += '</div>\n' hf = open(sysvals.htmlfile, 'w') thread_height = 0 - # write the html header first (html head, css code, everything up to the start of body) - html_header = "<!DOCTYPE html>\n<html>\n<head>\n\ - <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n\ + # write the html header first (html head, css code, up to body start) + html_header = '<!DOCTYPE html>\n<html>\n<head>\n\ + <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\ <title>AnalyzeSuspend</title>\n\ - <style type='text/css'>\n\ + <style type=\'text/css\'>\n\ body {overflow-y: scroll;}\n\ .stamp {width: 100%;text-align:center;background-color:gray;line-height:30px;color:white;font: 25px Arial;}\n\ .callgraph {margin-top: 30px;box-shadow: 5px 5px 20px black;}\n\ .callgraph article * {padding-left: 28px;}\n\ h1 {color:black;font: bold 30px Times;}\n\ + t0 {color:black;font: bold 30px Times;}\n\ + t1 {color:black;font: 30px Times;}\n\ + t2 {color:black;font: 25px Times;}\n\ + t3 {color:black;font: 20px Times;white-space:nowrap;}\n\ + t4 {color:black;font: bold 30px Times;line-height:60px;white-space:nowrap;}\n\ table {width:100%;}\n\ .gray {background-color:rgba(80,80,80,0.1);}\n\ .green {background-color:rgba(204,255,204,0.4);}\n\ @@ -968,38 +2364,58 @@ def createHTML(): .time1 {font: 22px Arial;border:1px solid;}\n\ .time2 {font: 15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\ td {text-align: center;}\n\ + r {color:#500000;font:15px Tahoma;}\n\ + n {color:#505050;font:15px Tahoma;}\n\ .tdhl {color: red;}\n\ .hide {display: none;}\n\ .pf {display: none;}\n\ - .pf:checked + label {background: url(\'data:image/svg+xml;utf,<?xml version=\"1.0\" standalone=\"no\"?><svg xmlns=\"http://www.w3.org/2000/svg\" height=\"18\" width=\"18\" version=\"1.1\"><circle cx=\"9\" cy=\"9\" r=\"8\" stroke=\"black\" stroke-width=\"1\" fill=\"white\"/><rect x=\"4\" y=\"8\" width=\"10\" height=\"2\" style=\"fill:black;stroke-width:0\"/><rect x=\"8\" y=\"4\" width=\"2\" height=\"10\" style=\"fill:black;stroke-width:0\"/></svg>\') no-repeat left center;}\n\ - .pf:not(:checked) ~ label {background: url(\'data:image/svg+xml;utf,<?xml version=\"1.0\" standalone=\"no\"?><svg xmlns=\"http://www.w3.org/2000/svg\" height=\"18\" width=\"18\" version=\"1.1\"><circle cx=\"9\" cy=\"9\" r=\"8\" stroke=\"black\" stroke-width=\"1\" fill=\"white\"/><rect x=\"4\" y=\"8\" width=\"10\" height=\"2\" style=\"fill:black;stroke-width:0\"/></svg>\') no-repeat left center;}\n\ + .pf:checked + label {background: url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/><rect x="8" y="4" width="2" height="10" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\ + .pf:not(:checked) ~ label {background: url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\ .pf:checked ~ *:not(:nth-child(2)) {display: none;}\n\ .zoombox {position: relative; width: 100%; overflow-x: scroll;}\n\ .timeline {position: relative; font-size: 14px;cursor: pointer;width: 100%; overflow: hidden; background-color:#dddddd;}\n\ - .thread {position: absolute; height: "+"%.3f"%thread_height+"%; overflow: hidden; line-height: 30px; border:1px solid;text-align:center;white-space:nowrap;background-color:rgba(204,204,204,0.5);}\n\ + .thread {position: absolute; height: '+'%.3f'%thread_height+'%; overflow: hidden; line-height: 30px; border:1px solid;text-align:center;white-space:nowrap;background-color:rgba(204,204,204,0.5);}\n\ .thread:hover {background-color:white;border:1px solid red;z-index:10;}\n\ + .hover {background-color:white;border:1px solid red;z-index:10;}\n\ + .traceevent {position: absolute;opacity: 0.3;height: '+'%.3f'%thread_height+'%;width:0;overflow:hidden;line-height:30px;text-align:center;white-space:nowrap;}\n\ .phase {position: absolute;overflow: hidden;border:0px;text-align:center;}\n\ - .t {position: absolute; top: 0%; height: 100%; border-right:1px solid black;}\n\ + .phaselet {position:absolute;overflow:hidden;border:0px;text-align:center;height:100px;font-size:24px;}\n\ + .t {position:absolute;top:0%;height:100%;border-right:1px solid black;}\n\ .legend {position: relative; width: 100%; height: 40px; text-align: center;margin-bottom:20px}\n\ .legend .square {position:absolute;top:10px; width: 0px;height: 20px;border:1px solid;padding-left:20px;}\n\ button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\ - </style>\n</head>\n<body>\n" + .devlist {position:'+x2changes[1]+';width:190px;}\n\ + #devicedetail {height:100px;box-shadow: 5px 5px 20px black;}\n\ + </style>\n</head>\n<body>\n' hf.write(html_header) # write the test title and general info header - if(data.stamp['time'] != ""): - hf.write(headline_stamp.format(data.stamp['host'], - data.stamp['kernel'], data.stamp['mode'], data.stamp['time'])) - - # write the dmesg data (device timeline) - if(data.usedmesg): - hf.write(devtl.html['timeline']) - hf.write(devtl.html['legend']) - hf.write('<div id="devicedetail"></div>\n') - hf.write('<div id="devicetree"></div>\n') + if(sysvals.stamp['time'] != ""): + hf.write(headline_stamp.format(sysvals.stamp['host'], + sysvals.stamp['kernel'], sysvals.stamp['mode'], \ + sysvals.stamp['time'])) + + # write the device timeline + hf.write(devtl.html['timeline']) + hf.write(devtl.html['legend']) + hf.write('<div id="devicedetailtitle"></div>\n') + hf.write('<div id="devicedetail" style="display:none;">\n') + # draw the colored boxes for the device detail section + for data in testruns: + hf.write('<div id="devicedetail%d">\n' % data.testnumber) + for b in data.phases: + phase = data.dmesg[b] + length = phase['end']-phase['start'] + left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal) + width = '%.3f' % ((length*100.0)/tTotal) + hf.write(html_phaselet.format(b, left, width, \ + data.dmesg[b]['color'])) + hf.write('</div>\n') + hf.write('</div>\n') # write the ftrace data (callgraph) - if(data.useftrace): + data = testruns[-1] + if(sysvals.usecallgraph): hf.write('<section id="callgraphs" class="callgraph">\n') # write out the ftrace data converted to html html_func_top = '<article id="{0}" class="atop" style="background-color:{1}">\n<input type="checkbox" class="pf" id="f{2}" checked/><label for="f{2}">{3} {4}</label>\n' @@ -1013,18 +2429,21 @@ def createHTML(): if('ftrace' not in list[devname]): continue name = devname - if(devname in data.altdevname): - name = data.altdevname[devname] + if(devname in sysvals.altdevname): + name = sysvals.altdevname[devname] devid = list[devname]['id'] cg = list[devname]['ftrace'] - flen = "(%.3f ms)" % ((cg.end - cg.start)*1000) - hf.write(html_func_top.format(devid, data.dmesg[p]['color'], num, name+" "+p, flen)) + flen = '<r>(%.3f ms @ %.3f to %.3f)</r>' % \ + ((cg.end - cg.start)*1000, cg.start*1000, cg.end*1000) + hf.write(html_func_top.format(devid, data.dmesg[p]['color'], \ + num, name+' '+p, flen)) num += 1 for line in cg.list: if(line.length < 0.000000001): - flen = "" + flen = '' else: - flen = "(%.3f ms)" % (line.length*1000) + flen = '<n>(%.3f ms @ %.3f)</n>' % (line.length*1000, \ + line.time*1000) if(line.freturn and line.fcall): hf.write(html_func_leaf.format(line.name, flen)) elif(line.freturn): @@ -1033,96 +2452,31 @@ def createHTML(): hf.write(html_func_start.format(num, line.name, flen)) num += 1 hf.write(html_func_end) - hf.write("\n\n </section>\n") + hf.write('\n\n </section>\n') # write the footer and close - addScriptCode(hf) - hf.write("</body>\n</html>\n") + addScriptCode(hf, testruns) + hf.write('</body>\n</html>\n') hf.close() return True -def addScriptCode(hf): - global data - - t0 = (data.start - data.tSuspended) * 1000 - tMax = (data.end - data.tSuspended) * 1000 +# Function: addScriptCode +# Description: +# Adds the javascript code to the output html +# Arguments: +# hf: the open html file pointer +# testruns: array of Data objects from parseKernelLog or parseTraceLog +def addScriptCode(hf, testruns): + t0 = (testruns[0].start - testruns[-1].tSuspended) * 1000 + tMax = (testruns[-1].end - testruns[-1].tSuspended) * 1000 # create an array in javascript memory with the device details - detail = ' var bounds = [%f,%f];\n' % (t0, tMax) - detail += ' var d = [];\n' - dfmt = ' d["%s"] = { n:"%s", p:"%s", c:[%s] };\n'; - for p in data.dmesg: - list = data.dmesg[p]['list'] - for d in list: - parent = data.deviceParentID(d, p) - idlist = data.deviceChildrenIDs(d, p) - idstr = "" - for i in idlist: - if(idstr == ""): - idstr += '"'+i+'"' - else: - idstr += ', '+'"'+i+'"' - detail += dfmt % (list[d]['id'], d, parent, idstr) - + detail = ' var devtable = [];\n' + for data in testruns: + topo = data.deviceTopology() + detail += ' devtable[%d] = "%s";\n' % (data.testnumber, topo) + detail += ' var bounds = [%f,%f];\n' % (t0, tMax) # add the code which will manipulate the data in the browser script_code = \ '<script type="text/javascript">\n'+detail+\ - ' var filter = [];\n'\ - ' var table = [];\n'\ - ' function deviceParent(devid) {\n'\ - ' var devlist = [];\n'\ - ' if(filter.indexOf(devid) < 0) filter[filter.length] = devid;\n'\ - ' if(d[devid].p in d)\n'\ - ' devlist = deviceParent(d[devid].p);\n'\ - ' else if(d[devid].p != "")\n'\ - ' devlist = [d[devid].p];\n'\ - ' devlist[devlist.length] = d[devid].n;\n'\ - ' return devlist;\n'\ - ' }\n'\ - ' function deviceChildren(devid, column, row) {\n'\ - ' if(!(devid in d)) return;\n'\ - ' if(filter.indexOf(devid) < 0) filter[filter.length] = devid;\n'\ - ' var cell = {name: d[devid].n, span: 1};\n'\ - ' var span = 0;\n'\ - ' if(column >= table.length) table[column] = [];\n'\ - ' table[column][row] = cell;\n'\ - ' for(var i = 0; i < d[devid].c.length; i++) {\n'\ - ' var cid = d[devid].c[i];\n'\ - ' span += deviceChildren(cid, column+1, row+span);\n'\ - ' }\n'\ - ' if(span == 0) span = 1;\n'\ - ' table[column][row].span = span;\n'\ - ' return span;\n'\ - ' }\n'\ - ' function deviceTree(devid, resume) {\n'\ - ' var html = "<table border=1>";\n'\ - ' filter = [];\n'\ - ' table = [];\n'\ - ' plist = deviceParent(devid);\n'\ - ' var devidx = plist.length - 1;\n'\ - ' for(var i = 0; i < devidx; i++)\n'\ - ' table[i] = [{name: plist[i], span: 1}];\n'\ - ' deviceChildren(devid, devidx, 0);\n'\ - ' for(var i = 0; i < devidx; i++)\n'\ - ' table[i][0].span = table[devidx][0].span;\n'\ - ' for(var row = 0; row < table[0][0].span; row++) {\n'\ - ' html += "<tr>";\n'\ - ' for(var col = 0; col < table.length; col++)\n'\ - ' if(row in table[col]) {\n'\ - ' var cell = table[col][row];\n'\ - ' var args = "";\n'\ - ' if(cell.span > 1)\n'\ - ' args += " rowspan="+cell.span;\n'\ - ' if((col == devidx) && (row == 0))\n'\ - ' args += " class=tdhl";\n'\ - ' if(resume)\n'\ - ' html += "<td"+args+">"+cell.name+" →</td>";\n'\ - ' else\n'\ - ' html += "<td"+args+">← "+cell.name+"</td>";\n'\ - ' }\n'\ - ' html += "</tr>";\n'\ - ' }\n'\ - ' html += "</table>";\n'\ - ' return html;\n'\ - ' }\n'\ ' function zoomTimeline() {\n'\ ' var timescale = document.getElementById("timescale");\n'\ ' var dmesg = document.getElementById("dmesg");\n'\ @@ -1154,35 +2508,170 @@ def addScriptCode(hf): ' for(var s = ((t0 / tS)|0) * tS; s < tMax; s += tS) {\n'\ ' var pos = (tMax - s) * 100.0 / tTotal;\n'\ ' var name = (s == 0)?"S/R":(s+"ms");\n'\ - ' html += \"<div class=\\\"t\\\" style=\\\"right:\"+pos+\"%\\\">\"+name+\"</div>\";\n'\ + ' html += "<div class=\\"t\\" style=\\"right:"+pos+"%\\">"+name+"</div>";\n'\ ' }\n'\ ' timescale.innerHTML = html;\n'\ ' }\n'\ + ' function deviceHover() {\n'\ + ' var name = this.title.slice(0, this.title.indexOf(" ("));\n'\ + ' var dmesg = document.getElementById("dmesg");\n'\ + ' var dev = dmesg.getElementsByClassName("thread");\n'\ + ' var cpu = -1;\n'\ + ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\ + ' cpu = parseInt(name.slice(7));\n'\ + ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\ + ' cpu = parseInt(name.slice(8));\n'\ + ' for (var i = 0; i < dev.length; i++) {\n'\ + ' dname = dev[i].title.slice(0, dev[i].title.indexOf(" ("));\n'\ + ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\ + ' (name == dname))\n'\ + ' {\n'\ + ' dev[i].className = "thread hover";\n'\ + ' } else {\n'\ + ' dev[i].className = "thread";\n'\ + ' }\n'\ + ' }\n'\ + ' }\n'\ + ' function deviceUnhover() {\n'\ + ' var dmesg = document.getElementById("dmesg");\n'\ + ' var dev = dmesg.getElementsByClassName("thread");\n'\ + ' for (var i = 0; i < dev.length; i++) {\n'\ + ' dev[i].className = "thread";\n'\ + ' }\n'\ + ' }\n'\ + ' function deviceTitle(title, total, cpu) {\n'\ + ' var prefix = "Total";\n'\ + ' if(total.length > 3) {\n'\ + ' prefix = "Average";\n'\ + ' total[1] = (total[1]+total[3])/2;\n'\ + ' total[2] = (total[2]+total[4])/2;\n'\ + ' }\n'\ + ' var devtitle = document.getElementById("devicedetailtitle");\n'\ + ' var name = title.slice(0, title.indexOf(" "));\n'\ + ' if(cpu >= 0) name = "CPU"+cpu;\n'\ + ' var driver = "";\n'\ + ' var tS = "<t2>(</t2>";\n'\ + ' var tR = "<t2>)</t2>";\n'\ + ' if(total[1] > 0)\n'\ + ' tS = "<t2>("+prefix+" Suspend:</t2><t0> "+total[1].toFixed(3)+" ms</t0> ";\n'\ + ' if(total[2] > 0)\n'\ + ' tR = " <t2>"+prefix+" Resume:</t2><t0> "+total[2].toFixed(3)+" ms<t2>)</t2></t0>";\n'\ + ' var s = title.indexOf("{");\n'\ + ' var e = title.indexOf("}");\n'\ + ' if((s >= 0) && (e >= 0))\n'\ + ' driver = title.slice(s+1, e) + " <t1>@</t1> ";\n'\ + ' if(total[1] > 0 && total[2] > 0)\n'\ + ' devtitle.innerHTML = "<t0>"+driver+name+"</t0> "+tS+tR;\n'\ + ' else\n'\ + ' devtitle.innerHTML = "<t0>"+title+"</t0>";\n'\ + ' return name;\n'\ + ' }\n'\ ' function deviceDetail() {\n'\ - ' var devtitle = document.getElementById("devicedetail");\n'\ - ' devtitle.innerHTML = "<h1>"+this.title+"</h1>";\n'\ - ' var devtree = document.getElementById("devicetree");\n'\ - ' devtree.innerHTML = deviceTree(this.id, (this.title.indexOf("resume") >= 0));\n'\ + ' var devinfo = document.getElementById("devicedetail");\n'\ + ' devinfo.style.display = "block";\n'\ + ' var name = this.title.slice(0, this.title.indexOf(" ("));\n'\ + ' var cpu = -1;\n'\ + ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\ + ' cpu = parseInt(name.slice(7));\n'\ + ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\ + ' cpu = parseInt(name.slice(8));\n'\ + ' var dmesg = document.getElementById("dmesg");\n'\ + ' var dev = dmesg.getElementsByClassName("thread");\n'\ + ' var idlist = [];\n'\ + ' var pdata = [[]];\n'\ + ' var pd = pdata[0];\n'\ + ' var total = [0.0, 0.0, 0.0];\n'\ + ' for (var i = 0; i < dev.length; i++) {\n'\ + ' dname = dev[i].title.slice(0, dev[i].title.indexOf(" ("));\n'\ + ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\ + ' (name == dname))\n'\ + ' {\n'\ + ' idlist[idlist.length] = dev[i].id;\n'\ + ' var tidx = 1;\n'\ + ' if(dev[i].id[0] == "a") {\n'\ + ' pd = pdata[0];\n'\ + ' } else {\n'\ + ' if(pdata.length == 1) pdata[1] = [];\n'\ + ' if(total.length == 3) total[3]=total[4]=0.0;\n'\ + ' pd = pdata[1];\n'\ + ' tidx = 3;\n'\ + ' }\n'\ + ' var info = dev[i].title.split(" ");\n'\ + ' var pname = info[info.length-1];\n'\ + ' pd[pname] = parseFloat(info[info.length-3].slice(1));\n'\ + ' total[0] += pd[pname];\n'\ + ' if(pname.indexOf("suspend") >= 0)\n'\ + ' total[tidx] += pd[pname];\n'\ + ' else\n'\ + ' total[tidx+1] += pd[pname];\n'\ + ' }\n'\ + ' }\n'\ + ' var devname = deviceTitle(this.title, total, cpu);\n'\ + ' var left = 0.0;\n'\ + ' for (var t = 0; t < pdata.length; t++) {\n'\ + ' pd = pdata[t];\n'\ + ' devinfo = document.getElementById("devicedetail"+t);\n'\ + ' var phases = devinfo.getElementsByClassName("phaselet");\n'\ + ' for (var i = 0; i < phases.length; i++) {\n'\ + ' if(phases[i].id in pd) {\n'\ + ' var w = 100.0*pd[phases[i].id]/total[0];\n'\ + ' var fs = 32;\n'\ + ' if(w < 8) fs = 4*w | 0;\n'\ + ' var fs2 = fs*3/4;\n'\ + ' phases[i].style.width = w+"%";\n'\ + ' phases[i].style.left = left+"%";\n'\ + ' phases[i].title = phases[i].id+" "+pd[phases[i].id]+" ms";\n'\ + ' left += w;\n'\ + ' var time = "<t4 style=\\"font-size:"+fs+"px\\">"+pd[phases[i].id]+" ms<br></t4>";\n'\ + ' var pname = "<t3 style=\\"font-size:"+fs2+"px\\">"+phases[i].id.replace("_", " ")+"</t3>";\n'\ + ' phases[i].innerHTML = time+pname;\n'\ + ' } else {\n'\ + ' phases[i].style.width = "0%";\n'\ + ' phases[i].style.left = left+"%";\n'\ + ' }\n'\ + ' }\n'\ + ' }\n'\ ' var cglist = document.getElementById("callgraphs");\n'\ ' if(!cglist) return;\n'\ ' var cg = cglist.getElementsByClassName("atop");\n'\ ' for (var i = 0; i < cg.length; i++) {\n'\ - ' if(filter.indexOf(cg[i].id) >= 0) {\n'\ + ' if(idlist.indexOf(cg[i].id) >= 0) {\n'\ ' cg[i].style.display = "block";\n'\ ' } else {\n'\ ' cg[i].style.display = "none";\n'\ ' }\n'\ ' }\n'\ ' }\n'\ + ' function devListWindow(e) {\n'\ + ' var sx = e.clientX;\n'\ + ' if(sx > window.innerWidth - 440)\n'\ + ' sx = window.innerWidth - 440;\n'\ + ' var cfg="top="+e.screenY+", left="+sx+", width=440, height=720, scrollbars=yes";\n'\ + ' var win = window.open("", "_blank", cfg);\n'\ + ' if(window.chrome) win.moveBy(sx, 0);\n'\ + ' var html = "<title>"+e.target.innerHTML+"</title>"+\n'\ + ' "<style type=\\"text/css\\">"+\n'\ + ' " ul {list-style-type:circle;padding-left:10px;margin-left:10px;}"+\n'\ + ' "</style>"\n'\ + ' var dt = devtable[0];\n'\ + ' if(e.target.id != "devlist1")\n'\ + ' dt = devtable[1];\n'\ + ' win.document.write(html+dt);\n'\ + ' }\n'\ ' window.addEventListener("load", function () {\n'\ ' var dmesg = document.getElementById("dmesg");\n'\ ' dmesg.style.width = "100%"\n'\ ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\ ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\ ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\ + ' var devlist = document.getElementsByClassName("devlist");\n'\ + ' for (var i = 0; i < devlist.length; i++)\n'\ + ' devlist[i].onclick = devListWindow;\n'\ ' var dev = dmesg.getElementsByClassName("thread");\n'\ ' for (var i = 0; i < dev.length; i++) {\n'\ ' dev[i].onclick = deviceDetail;\n'\ + ' dev[i].onmouseover = deviceHover;\n'\ + ' dev[i].onmouseout = deviceUnhover;\n'\ ' }\n'\ ' zoomTimeline();\n'\ ' });\n'\ @@ -1191,256 +2680,912 @@ def addScriptCode(hf): # Function: executeSuspend # Description: -# Execute system suspend through the sysfs interface +# Execute system suspend through the sysfs interface, then copy the output +# dmesg and ftrace files to the test output directory. def executeSuspend(): - global sysvals, data - - detectUSB() - pf = open(sysvals.powerfile, 'w') - # clear the kernel ring buffer just as we start - os.system("dmesg -C") - # start ftrace - if(data.useftrace): - print("START TRACING") - os.system("echo 1 > "+sysvals.tpath+"tracing_on") - os.system("echo SUSPEND START > "+sysvals.tpath+"trace_marker") - # initiate suspend - if(sysvals.rtcwake): - print("SUSPEND START") - os.system("rtcwake -s 10 -m "+sysvals.suspendmode) - else: - print("SUSPEND START (press a key to resume)") + global sysvals + + detectUSB(False) + t0 = time.time()*1000 + tp = sysvals.tpath + # execute however many s/r runs requested + for count in range(1,sysvals.execcount+1): + # clear the kernel ring buffer just as we start + os.system('dmesg -C') + # enable callgraph ftrace only for the second run + if(sysvals.usecallgraph and count == 2): + # set trace type + os.system('echo function_graph > '+tp+'current_tracer') + os.system('echo "" > '+tp+'set_ftrace_filter') + # set trace format options + os.system('echo funcgraph-abstime > '+tp+'trace_options') + os.system('echo funcgraph-proc > '+tp+'trace_options') + # focus only on device suspend and resume + os.system('cat '+tp+'available_filter_functions | '+\ + 'grep dpm_run_callback > '+tp+'set_graph_function') + # if this is test2 and there's a delay, start here + if(count > 1 and sysvals.x2delay > 0): + tN = time.time()*1000 + while (tN - t0) < sysvals.x2delay: + tN = time.time()*1000 + time.sleep(0.001) + # start ftrace + if(sysvals.usecallgraph or sysvals.usetraceevents): + print('START TRACING') + os.system('echo 1 > '+tp+'tracing_on') + # initiate suspend + if(sysvals.usecallgraph or sysvals.usetraceevents): + os.system('echo SUSPEND START > '+tp+'trace_marker') + if(sysvals.rtcwake): + print('SUSPEND START') + print('will autoresume in %d seconds' % sysvals.rtcwaketime) + sysvals.rtcWakeAlarm() + else: + print('SUSPEND START (press a key to resume)') + pf = open(sysvals.powerfile, 'w') pf.write(sysvals.suspendmode) - # execution will pause here - pf.close() - # return from suspend - print("RESUME COMPLETE") - # stop ftrace - if(data.useftrace): - os.system("echo RESUME COMPLETE > "+sysvals.tpath+"trace_marker") - os.system("echo 0 > "+sysvals.tpath+"tracing_on") - print("CAPTURING FTRACE") - os.system("echo \""+sysvals.teststamp+"\" > "+sysvals.ftracefile) - os.system("cat "+sysvals.tpath+"trace >> "+sysvals.ftracefile) - # grab a copy of the dmesg output - print("CAPTURING DMESG") - os.system("echo \""+sysvals.teststamp+"\" > "+sysvals.dmesgfile) - os.system("dmesg -c >> "+sysvals.dmesgfile) + # execution will pause here + pf.close() + t0 = time.time()*1000 + # return from suspend + print('RESUME COMPLETE') + if(sysvals.usecallgraph or sysvals.usetraceevents): + os.system('echo RESUME COMPLETE > '+tp+'trace_marker') + # see if there's firmware timing data to be had + t = sysvals.postresumetime + if(t > 0): + print('Waiting %d seconds for POST-RESUME trace events...' % t) + time.sleep(t) + # stop ftrace + if(sysvals.usecallgraph or sysvals.usetraceevents): + os.system('echo 0 > '+tp+'tracing_on') + print('CAPTURING TRACE') + writeDatafileHeader(sysvals.ftracefile) + os.system('cat '+tp+'trace >> '+sysvals.ftracefile) + os.system('echo "" > '+tp+'trace') + # grab a copy of the dmesg output + print('CAPTURING DMESG') + writeDatafileHeader(sysvals.dmesgfile) + os.system('dmesg -c >> '+sysvals.dmesgfile) + +def writeDatafileHeader(filename): + global sysvals + + fw = getFPDT(False) + prt = sysvals.postresumetime + fp = open(filename, 'a') + fp.write(sysvals.teststamp+'\n') + if(fw): + fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1])) + if(prt > 0): + fp.write('# post resume time %u\n' % prt) + fp.close() + +# Function: executeAndroidSuspend +# Description: +# Execute system suspend through the sysfs interface +# on a remote android device, then transfer the output +# dmesg and ftrace files to the local output directory. +def executeAndroidSuspend(): + global sysvals + + # check to see if the display is currently off + tp = sysvals.tpath + out = os.popen(sysvals.adb+\ + ' shell dumpsys power | grep mScreenOn').read().strip() + # if so we need to turn it on so we can issue a new suspend + if(out.endswith('false')): + print('Waking the device up for the test...') + # send the KEYPAD_POWER keyevent to wake it up + os.system(sysvals.adb+' shell input keyevent 26') + # wait a few seconds so the user can see the device wake up + time.sleep(3) + # execute however many s/r runs requested + for count in range(1,sysvals.execcount+1): + # clear the kernel ring buffer just as we start + os.system(sysvals.adb+' shell dmesg -c > /dev/null 2>&1') + # start ftrace + if(sysvals.usetraceevents): + print('START TRACING') + os.system(sysvals.adb+" shell 'echo 1 > "+tp+"tracing_on'") + # initiate suspend + for count in range(1,sysvals.execcount+1): + if(sysvals.usetraceevents): + os.system(sysvals.adb+\ + " shell 'echo SUSPEND START > "+tp+"trace_marker'") + print('SUSPEND START (press a key on the device to resume)') + os.system(sysvals.adb+" shell 'echo "+sysvals.suspendmode+\ + " > "+sysvals.powerfile+"'") + # execution will pause here, then adb will exit + while(True): + check = os.popen(sysvals.adb+\ + ' shell pwd 2>/dev/null').read().strip() + if(len(check) > 0): + break + time.sleep(1) + if(sysvals.usetraceevents): + os.system(sysvals.adb+" shell 'echo RESUME COMPLETE > "+tp+\ + "trace_marker'") + # return from suspend + print('RESUME COMPLETE') + # stop ftrace + if(sysvals.usetraceevents): + os.system(sysvals.adb+" shell 'echo 0 > "+tp+"tracing_on'") + print('CAPTURING TRACE') + os.system('echo "'+sysvals.teststamp+'" > '+sysvals.ftracefile) + os.system(sysvals.adb+' shell cat '+tp+\ + 'trace >> '+sysvals.ftracefile) + # grab a copy of the dmesg output + print('CAPTURING DMESG') + os.system('echo "'+sysvals.teststamp+'" > '+sysvals.dmesgfile) + os.system(sysvals.adb+' shell dmesg >> '+sysvals.dmesgfile) + +# Function: setUSBDevicesAuto +# Description: +# Set the autosuspend control parameter of all USB devices to auto +# This can be dangerous, so use at your own risk, most devices are set +# to always-on since the kernel cant determine if the device can +# properly autosuspend +def setUSBDevicesAuto(): + global sysvals + + rootCheck() + for dirname, dirnames, filenames in os.walk('/sys/devices'): + if(re.match('.*/usb[0-9]*.*', dirname) and + 'idVendor' in filenames and 'idProduct' in filenames): + os.system('echo auto > %s/power/control' % dirname) + name = dirname.split('/')[-1] + desc = os.popen('cat %s/product 2>/dev/null' % \ + dirname).read().replace('\n', '') + ctrl = os.popen('cat %s/power/control 2>/dev/null' % \ + dirname).read().replace('\n', '') + print('control is %s for %6s: %s' % (ctrl, name, desc)) + +# Function: yesno +# Description: +# Print out an equivalent Y or N for a set of known parameter values +# Output: +# 'Y', 'N', or ' ' if the value is unknown +def yesno(val): + yesvals = ['auto', 'enabled', 'active', '1'] + novals = ['on', 'disabled', 'suspended', 'forbidden', 'unsupported'] + if val in yesvals: + return 'Y' + elif val in novals: + return 'N' + return ' ' + +# Function: ms2nice +# Description: +# Print out a very concise time string in minutes and seconds +# Output: +# The time string, e.g. "1901m16s" +def ms2nice(val): + ms = 0 + try: + ms = int(val) + except: + return 0.0 + m = ms / 60000 + s = (ms / 1000) - (m * 60) + return '%3dm%2ds' % (m, s) # Function: detectUSB # Description: -# Detect all the USB hosts and devices currently connected -def detectUSB(): - global sysvals, data - - for dirname, dirnames, filenames in os.walk("/sys/devices"): - if(re.match(r".*/usb[0-9]*.*", dirname) and - "idVendor" in filenames and "idProduct" in filenames): - vid = os.popen("cat %s/idVendor 2>/dev/null" % dirname).read().replace('\n', '') - pid = os.popen("cat %s/idProduct 2>/dev/null" % dirname).read().replace('\n', '') - product = os.popen("cat %s/product 2>/dev/null" % dirname).read().replace('\n', '') +# Detect all the USB hosts and devices currently connected and add +# a list of USB device names to sysvals for better timeline readability +# Arguments: +# output: True to output the info to stdout, False otherwise +def detectUSB(output): + global sysvals + + field = {'idVendor':'', 'idProduct':'', 'product':'', 'speed':''} + power = {'async':'', 'autosuspend':'', 'autosuspend_delay_ms':'', + 'control':'', 'persist':'', 'runtime_enabled':'', + 'runtime_status':'', 'runtime_usage':'', + 'runtime_active_time':'', + 'runtime_suspended_time':'', + 'active_duration':'', + 'connected_duration':''} + if(output): + print('LEGEND') + print('---------------------------------------------------------------------------------------------') + print(' A = async/sync PM queue Y/N D = autosuspend delay (seconds)') + print(' S = autosuspend Y/N rACTIVE = runtime active (min/sec)') + print(' P = persist across suspend Y/N rSUSPEN = runtime suspend (min/sec)') + print(' E = runtime suspend enabled/forbidden Y/N ACTIVE = active duration (min/sec)') + print(' R = runtime status active/suspended Y/N CONNECT = connected duration (min/sec)') + print(' U = runtime usage count') + print('---------------------------------------------------------------------------------------------') + print(' NAME ID DESCRIPTION SPEED A S P E R U D rACTIVE rSUSPEN ACTIVE CONNECT') + print('---------------------------------------------------------------------------------------------') + + for dirname, dirnames, filenames in os.walk('/sys/devices'): + if(re.match('.*/usb[0-9]*.*', dirname) and + 'idVendor' in filenames and 'idProduct' in filenames): + for i in field: + field[i] = os.popen('cat %s/%s 2>/dev/null' % \ + (dirname, i)).read().replace('\n', '') name = dirname.split('/')[-1] - if(len(product) > 0): - data.altdevname[name] = "%s [%s]" % (product, name) + if(len(field['product']) > 0): + sysvals.altdevname[name] = \ + '%s [%s]' % (field['product'], name) else: - data.altdevname[name] = "%s:%s [%s]" % (vid, pid, name) - + sysvals.altdevname[name] = \ + '%s:%s [%s]' % (field['idVendor'], \ + field['idProduct'], name) + if(output): + for i in power: + power[i] = os.popen('cat %s/power/%s 2>/dev/null' % \ + (dirname, i)).read().replace('\n', '') + if(re.match('usb[0-9]*', name)): + first = '%-8s' % name + else: + first = '%8s' % name + print('%s [%s:%s] %-20s %-4s %1s %1s %1s %1s %1s %1s %1s %s %s %s %s' % \ + (first, field['idVendor'], field['idProduct'], \ + field['product'][0:20], field['speed'], \ + yesno(power['async']), \ + yesno(power['control']), \ + yesno(power['persist']), \ + yesno(power['runtime_enabled']), \ + yesno(power['runtime_status']), \ + power['runtime_usage'], \ + power['autosuspend'], \ + ms2nice(power['runtime_active_time']), \ + ms2nice(power['runtime_suspended_time']), \ + ms2nice(power['active_duration']), \ + ms2nice(power['connected_duration']))) + +# Function: getModes +# Description: +# Determine the supported power modes on this system +# Output: +# A string list of the available modes def getModes(): global sysvals - modes = "" - if(os.path.exists(sysvals.powerfile)): - fp = open(sysvals.powerfile, 'r') - modes = string.split(fp.read()) - fp.close() + modes = '' + if(not sysvals.android): + if(os.path.exists(sysvals.powerfile)): + fp = open(sysvals.powerfile, 'r') + modes = string.split(fp.read()) + fp.close() + else: + line = os.popen(sysvals.adb+' shell cat '+\ + sysvals.powerfile).read().strip() + modes = string.split(line) return modes +# Function: getFPDT +# Description: +# Read the acpi bios tables and pull out FPDT, the firmware data +# Arguments: +# output: True to output the info to stdout, False otherwise +def getFPDT(output): + global sysvals + + rectype = {} + rectype[0] = 'Firmware Basic Boot Performance Record' + rectype[1] = 'S3 Performance Table Record' + prectype = {} + prectype[0] = 'Basic S3 Resume Performance Record' + prectype[1] = 'Basic S3 Suspend Performance Record' + + rootCheck() + if(not os.path.exists(sysvals.fpdtpath)): + if(output): + doError('file doesnt exist: %s' % sysvals.fpdtpath, False) + return False + if(not os.access(sysvals.fpdtpath, os.R_OK)): + if(output): + doError('file isnt readable: %s' % sysvals.fpdtpath, False) + return False + if(not os.path.exists(sysvals.mempath)): + if(output): + doError('file doesnt exist: %s' % sysvals.mempath, False) + return False + if(not os.access(sysvals.mempath, os.R_OK)): + if(output): + doError('file isnt readable: %s' % sysvals.mempath, False) + return False + + fp = open(sysvals.fpdtpath, 'rb') + buf = fp.read() + fp.close() + + if(len(buf) < 36): + if(output): + doError('Invalid FPDT table data, should '+\ + 'be at least 36 bytes', False) + return False + + table = struct.unpack('4sIBB6s8sI4sI', buf[0:36]) + if(output): + print('') + print('Firmware Performance Data Table (%s)' % table[0]) + print(' Signature : %s' % table[0]) + print(' Table Length : %u' % table[1]) + print(' Revision : %u' % table[2]) + print(' Checksum : 0x%x' % table[3]) + print(' OEM ID : %s' % table[4]) + print(' OEM Table ID : %s' % table[5]) + print(' OEM Revision : %u' % table[6]) + print(' Creator ID : %s' % table[7]) + print(' Creator Revision : 0x%x' % table[8]) + print('') + + if(table[0] != 'FPDT'): + if(output): + doError('Invalid FPDT table') + return False + if(len(buf) <= 36): + return False + i = 0 + fwData = [0, 0] + records = buf[36:] + fp = open(sysvals.mempath, 'rb') + while(i < len(records)): + header = struct.unpack('HBB', records[i:i+4]) + if(header[0] not in rectype): + continue + if(header[1] != 16): + continue + addr = struct.unpack('Q', records[i+8:i+16])[0] + try: + fp.seek(addr) + first = fp.read(8) + except: + doError('Bad address 0x%x in %s' % (addr, sysvals.mempath), False) + rechead = struct.unpack('4sI', first) + recdata = fp.read(rechead[1]-8) + if(rechead[0] == 'FBPT'): + record = struct.unpack('HBBIQQQQQ', recdata) + if(output): + print('%s (%s)' % (rectype[header[0]], rechead[0])) + print(' Reset END : %u ns' % record[4]) + print(' OS Loader LoadImage Start : %u ns' % record[5]) + print(' OS Loader StartImage Start : %u ns' % record[6]) + print(' ExitBootServices Entry : %u ns' % record[7]) + print(' ExitBootServices Exit : %u ns' % record[8]) + elif(rechead[0] == 'S3PT'): + if(output): + print('%s (%s)' % (rectype[header[0]], rechead[0])) + j = 0 + while(j < len(recdata)): + prechead = struct.unpack('HBB', recdata[j:j+4]) + if(prechead[0] not in prectype): + continue + if(prechead[0] == 0): + record = struct.unpack('IIQQ', recdata[j:j+prechead[1]]) + fwData[1] = record[2] + if(output): + print(' %s' % prectype[prechead[0]]) + print(' Resume Count : %u' % \ + record[1]) + print(' FullResume : %u ns' % \ + record[2]) + print(' AverageResume : %u ns' % \ + record[3]) + elif(prechead[0] == 1): + record = struct.unpack('QQ', recdata[j+4:j+prechead[1]]) + fwData[0] = record[1] - record[0] + if(output): + print(' %s' % prectype[prechead[0]]) + print(' SuspendStart : %u ns' % \ + record[0]) + print(' SuspendEnd : %u ns' % \ + record[1]) + print(' SuspendTime : %u ns' % \ + fwData[0]) + j += prechead[1] + if(output): + print('') + i += header[1] + fp.close() + return fwData + # Function: statusCheck # Description: -# Verify that the requested command and options will work -def statusCheck(dryrun): - global sysvals, data - res = dict() +# Verify that the requested command and options will work, and +# print the results to the terminal +# Output: +# True if the test will work, False if not +def statusCheck(): + global sysvals + status = True - if(data.notestrun): - print("SUCCESS: The command should run!") - return + if(sysvals.android): + print('Checking the android system ...') + else: + print('Checking this system (%s)...' % platform.node()) + + # check if adb is connected to a device + if(sysvals.android): + res = 'NO' + out = os.popen(sysvals.adb+' get-state').read().strip() + if(out == 'device'): + res = 'YES' + print(' is android device connected: %s' % res) + if(res != 'YES'): + print(' Please connect the device before using this tool') + return False # check we have root access - check = "YES" - if(os.environ['USER'] != "root"): - if(not dryrun): - doError("root access is required", False) - check = "NO" - res[" have root access: "] = check + res = 'NO (No features of this tool will work!)' + if(sysvals.android): + out = os.popen(sysvals.adb+' shell id').read().strip() + if('root' in out): + res = 'YES' + else: + if(os.environ['USER'] == 'root'): + res = 'YES' + print(' have root access: %s' % res) + if(res != 'YES'): + if(sysvals.android): + print(' Try running "adb root" to restart the daemon as root') + else: + print(' Try running this script with sudo') + return False # check sysfs is mounted - check = "YES" - if(not os.path.exists(sysvals.powerfile)): - if(not dryrun): - doError("sysfs must be mounted", False) - check = "NO" - res[" is sysfs mounted: "] = check + res = 'NO (No features of this tool will work!)' + if(sysvals.android): + out = os.popen(sysvals.adb+' shell ls '+\ + sysvals.powerfile).read().strip() + if(out == sysvals.powerfile): + res = 'YES' + else: + if(os.path.exists(sysvals.powerfile)): + res = 'YES' + print(' is sysfs mounted: %s' % res) + if(res != 'YES'): + return False # check target mode is a valid mode - check = "YES" + res = 'NO' modes = getModes() - if(sysvals.suspendmode not in modes): - if(not dryrun): - doError("%s is not a value power mode" % sysvals.suspendmode, False) - check = "NO" - res[" is "+sysvals.suspendmode+" a power mode: "] = check + if(sysvals.suspendmode in modes): + res = 'YES' + else: + status = False + print(' is "%s" a valid power mode: %s' % (sysvals.suspendmode, res)) + if(res == 'NO'): + print(' valid power modes are: %s' % modes) + print(' please choose one with -m') + + # check if the tool can unlock the device + if(sysvals.android): + res = 'YES' + out1 = os.popen(sysvals.adb+\ + ' shell dumpsys power | grep mScreenOn').read().strip() + out2 = os.popen(sysvals.adb+\ + ' shell input').read().strip() + if(not out1.startswith('mScreenOn') or not out2.startswith('usage')): + res = 'NO (wake the android device up before running the test)' + print(' can I unlock the screen: %s' % res) # check if ftrace is available - if(data.useftrace): - check = "YES" - if(not verifyFtrace()): - if(not dryrun): - doError("ftrace is not configured", False) - check = "NO" - res[" is ftrace usable: "] = check + res = 'NO' + ftgood = verifyFtrace() + if(ftgood): + res = 'YES' + elif(sysvals.usecallgraph): + status = False + print(' is ftrace supported: %s' % res) + + # what data source are we using + res = 'DMESG' + if(ftgood): + sysvals.usetraceeventsonly = True + sysvals.usetraceevents = False + for e in sysvals.traceevents: + check = False + if(sysvals.android): + out = os.popen(sysvals.adb+' shell ls -d '+\ + sysvals.epath+e).read().strip() + if(out == sysvals.epath+e): + check = True + else: + if(os.path.exists(sysvals.epath+e)): + check = True + if(not check): + sysvals.usetraceeventsonly = False + if(e == 'suspend_resume' and check): + sysvals.usetraceevents = True + if(sysvals.usetraceevents and sysvals.usetraceeventsonly): + res = 'FTRACE (all trace events found)' + elif(sysvals.usetraceevents): + res = 'DMESG and FTRACE (suspend_resume trace event found)' + print(' timeline data source: %s' % res) # check if rtcwake - if(sysvals.rtcwake): - check = "YES" - version = os.popen("rtcwake -V 2>/dev/null").read() - if(not version.startswith("rtcwake")): - if(not dryrun): - doError("rtcwake is not installed", False) - check = "NO" - res[" is rtcwake usable: "] = check - - if(dryrun): - status = True - print("Checking if system can run the current command:") - for r in res: - print("%s\t%s" % (r, res[r])) - if(res[r] != "YES"): - status = False - if(status): - print("SUCCESS: The command should run!") - else: - print("FAILURE: The command won't run!") + res = 'NO' + if(sysvals.rtcpath != ''): + res = 'YES' + elif(sysvals.rtcwake): + status = False + print(' is rtcwake supported: %s' % res) -def printHelp(): - global sysvals - modes = getModes() - - print("") - print("AnalyzeSuspend") - print("Usage: sudo analyze_suspend.py <options>") - print("") - print("Description:") - print(" Initiates a system suspend/resume while capturing dmesg") - print(" and (optionally) ftrace data to analyze device timing") - print("") - print(" Generates output files in subdirectory: suspend-mmddyy-HHMMSS") - print(" HTML output: <hostname>_<mode>.html") - print(" raw dmesg output: <hostname>_<mode>_dmesg.txt") - print(" raw ftrace output (with -f): <hostname>_<mode>_ftrace.txt") - print("") - print("Options:") - print(" [general]") - print(" -h Print this help text") - print(" -verbose Print extra information during execution and analysis") - print(" -status Test to see if the system is enabled to run this tool") - print(" -modes List available suspend modes") - print(" -m mode Mode to initiate for suspend %s (default: %s)") % (modes, sysvals.suspendmode) - print(" -rtcwake Use rtcwake to autoresume after 10 seconds (default: disabled)") - print(" -f Use ftrace to create device callgraphs (default: disabled)") - print(" [re-analyze data from previous runs]") - print(" -dmesg dmesgfile Create HTML timeline from dmesg file") - print(" -ftrace ftracefile Create HTML callgraph from ftrace file") - print("") - return True + return status +# Function: doError +# Description: +# generic error function for catastrphic failures +# Arguments: +# msg: the error message to print +# help: True if printHelp should be called after, False otherwise def doError(msg, help): - print("ERROR: %s") % msg if(help == True): printHelp() + print('ERROR: %s\n') % msg sys.exit() -# -- script main -- -# loop through the command line arguments -cmd = "" -args = iter(sys.argv[1:]) -for arg in args: - if(arg == "-m"): - try: - val = args.next() - except: - doError("No mode supplied", True) - sysvals.suspendmode = val - elif(arg == "-f"): - data.useftrace = True - elif(arg == "-modes"): - cmd = "modes" - elif(arg == "-status"): - cmd = "status" - elif(arg == "-verbose"): - data.verbose = True - elif(arg == "-rtcwake"): - sysvals.rtcwake = True - elif(arg == "-dmesg"): - try: - val = args.next() - except: - doError("No dmesg file supplied", True) - data.notestrun = True - data.usedmesg = True - sysvals.dmesgfile = val - elif(arg == "-ftrace"): - try: - val = args.next() - except: - doError("No ftrace file supplied", True) - data.notestrun = True - data.useftrace = True - sysvals.ftracefile = val - elif(arg == "-h"): - printHelp() - sys.exit() - else: - doError("Invalid argument: "+arg, True) - -# just run a utility command and exit -if(cmd != ""): - if(cmd == "status"): - statusCheck(True) - elif(cmd == "modes"): - modes = getModes() - print modes - sys.exit() +# Function: doWarning +# Description: +# generic warning function for non-catastrophic anomalies +# Arguments: +# msg: the warning message to print +# file: If not empty, a filename to request be sent to the owner for debug +def doWarning(msg, file): + print('/* %s */') % msg + if(file): + print('/* For a fix, please send this'+\ + ' %s file to <todd.e.brandt@intel.com> */' % file) + +# Function: rootCheck +# Description: +# quick check to see if we have root access +def rootCheck(): + if(os.environ['USER'] != 'root'): + doError('This script must be run as root', False) -data.initialize() +# Function: getArgInt +# Description: +# pull out an integer argument from the command line with checks +def getArgInt(name, args, min, max): + try: + arg = args.next() + except: + doError(name+': no argument supplied', True) + try: + val = int(arg) + except: + doError(name+': non-integer value given', True) + if(val < min or val > max): + doError(name+': value should be between %d and %d' % (min, max), True) + return val + +# Function: rerunTest +# Description: +# generate an output from an existing set of ftrace/dmesg logs +def rerunTest(): + global sysvals -# if instructed, re-analyze existing data files -if(data.notestrun): + if(sysvals.ftracefile != ''): + doesTraceLogHaveTraceEvents() + if(sysvals.dmesgfile == '' and not sysvals.usetraceeventsonly): + doError('recreating this html output '+\ + 'requires a dmesg file', False) sysvals.setOutputFile() - data.vprint("Output file: %s" % sysvals.htmlfile) - if(sysvals.dmesgfile != ""): - analyzeKernelLog() - if(sysvals.ftracefile != ""): - analyzeTraceLog() - createHTML() - sys.exit() + vprint('Output file: %s' % sysvals.htmlfile) + print('PROCESSING DATA') + if(sysvals.usetraceeventsonly): + testruns = parseTraceLog() + else: + testruns = loadKernelLog() + for data in testruns: + parseKernelLog(data) + if(sysvals.ftracefile != ''): + appendIncompleteTraceLog(testruns) + createHTML(testruns) + +# Function: runTest +# Description: +# execute a suspend/resume, gather the logs, and generate the output +def runTest(subdir): + global sysvals + + # prepare for the test + if(not sysvals.android): + initFtrace() + else: + initFtraceAndroid() + sysvals.initTestOutput(subdir) + + vprint('Output files:\n %s' % sysvals.dmesgfile) + if(sysvals.usecallgraph or + sysvals.usetraceevents or + sysvals.usetraceeventsonly): + vprint(' %s' % sysvals.ftracefile) + vprint(' %s' % sysvals.htmlfile) + + # execute the test + if(not sysvals.android): + executeSuspend() + else: + executeAndroidSuspend() + + # analyze the data and create the html output + print('PROCESSING DATA') + if(sysvals.usetraceeventsonly): + # data for kernels 3.15 or newer is entirely in ftrace + testruns = parseTraceLog() + else: + # data for kernels older than 3.15 is primarily in dmesg + testruns = loadKernelLog() + for data in testruns: + parseKernelLog(data) + if(sysvals.usecallgraph or sysvals.usetraceevents): + appendIncompleteTraceLog(testruns) + createHTML(testruns) + +# Function: runSummary +# Description: +# create a summary of tests in a sub-directory +def runSummary(subdir, output): + global sysvals + + # get a list of ftrace output files + files = [] + for dirname, dirnames, filenames in os.walk(subdir): + for filename in filenames: + if(re.match('.*_ftrace.txt', filename)): + files.append("%s/%s" % (dirname, filename)) + + # process the files in order and get an array of data objects + testruns = [] + for file in sorted(files): + if output: + print("Test found in %s" % os.path.dirname(file)) + sysvals.ftracefile = file + sysvals.dmesgfile = file.replace('_ftrace.txt', '_dmesg.txt') + doesTraceLogHaveTraceEvents() + sysvals.usecallgraph = False + if not sysvals.usetraceeventsonly: + if(not os.path.exists(sysvals.dmesgfile)): + print("Skipping %s: not a valid test input" % file) + continue + else: + if output: + f = os.path.basename(sysvals.ftracefile) + d = os.path.basename(sysvals.dmesgfile) + print("\tInput files: %s and %s" % (f, d)) + testdata = loadKernelLog() + data = testdata[0] + parseKernelLog(data) + testdata = [data] + appendIncompleteTraceLog(testdata) + else: + if output: + print("\tInput file: %s" % os.path.basename(sysvals.ftracefile)) + testdata = parseTraceLog() + data = testdata[0] + data.normalizeTime(data.tSuspended) + link = file.replace(subdir+'/', '').replace('_ftrace.txt', '.html') + data.outfile = link + testruns.append(data) + + createHTMLSummarySimple(testruns, subdir+'/summary.html') + +# Function: printHelp +# Description: +# print out the help text +def printHelp(): + global sysvals + modes = getModes() + + print('') + print('AnalyzeSuspend v%.1f' % sysvals.version) + print('Usage: sudo analyze_suspend.py <options>') + print('') + print('Description:') + print(' This tool is designed to assist kernel and OS developers in optimizing') + print(' their linux stack\'s suspend/resume time. Using a kernel image built') + print(' with a few extra options enabled, the tool will execute a suspend and') + print(' capture dmesg and ftrace data until resume is complete. This data is') + print(' transformed into a device timeline and an optional callgraph to give') + print(' a detailed view of which devices/subsystems are taking the most') + print(' time in suspend/resume.') + print('') + print(' Generates output files in subdirectory: suspend-mmddyy-HHMMSS') + print(' HTML output: <hostname>_<mode>.html') + print(' raw dmesg output: <hostname>_<mode>_dmesg.txt') + print(' raw ftrace output: <hostname>_<mode>_ftrace.txt') + print('') + print('Options:') + print(' [general]') + print(' -h Print this help text') + print(' -v Print the current tool version') + print(' -verbose Print extra information during execution and analysis') + print(' -status Test to see if the system is enabled to run this tool') + print(' -modes List available suspend modes') + print(' -m mode Mode to initiate for suspend %s (default: %s)') % (modes, sysvals.suspendmode) + print(' -rtcwake t Use rtcwake to autoresume after <t> seconds (default: disabled)') + print(' [advanced]') + print(' -f Use ftrace to create device callgraphs (default: disabled)') + print(' -filter "d1 d2 ..." Filter out all but this list of dev names') + print(' -x2 Run two suspend/resumes back to back (default: disabled)') + print(' -x2delay t Minimum millisecond delay <t> between the two test runs (default: 0 ms)') + print(' -postres t Time after resume completion to wait for post-resume events (default: 0 S)') + print(' -multi n d Execute <n> consecutive tests at <d> seconds intervals. The outputs will') + print(' be created in a new subdirectory with a summary page.') + print(' [utilities]') + print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table') + print(' -usbtopo Print out the current USB topology with power info') + print(' -usbauto Enable autosuspend for all connected USB devices') + print(' [android testing]') + print(' -adb binary Use the given adb binary to run the test on an android device.') + print(' The device should already be connected and with root access.') + print(' Commands will be executed on the device using "adb shell"') + print(' [re-analyze data from previous runs]') + print(' -ftrace ftracefile Create HTML output using ftrace input') + print(' -dmesg dmesgfile Create HTML output using dmesg (not needed for kernel >= 3.15)') + print(' -summary directory Create a summary of all test in this dir') + print('') + return True -# verify that we can run a test -data.usedmesg = True -statusCheck(False) - -# prepare for the test -if(data.useftrace): - initFtrace() -sysvals.initTestOutput() - -data.vprint("Output files:\n %s" % sysvals.dmesgfile) -if(data.useftrace): - data.vprint(" %s" % sysvals.ftracefile) -data.vprint(" %s" % sysvals.htmlfile) - -# execute the test -executeSuspend() -analyzeKernelLog() -if(data.useftrace): - analyzeTraceLog() -createHTML() +# ----------------- MAIN -------------------- +# exec start (skipped if script is loaded as library) +if __name__ == '__main__': + cmd = '' + cmdarg = '' + multitest = {'run': False, 'count': 0, 'delay': 0} + # loop through the command line arguments + args = iter(sys.argv[1:]) + for arg in args: + if(arg == '-m'): + try: + val = args.next() + except: + doError('No mode supplied', True) + sysvals.suspendmode = val + elif(arg == '-adb'): + try: + val = args.next() + except: + doError('No adb binary supplied', True) + if(not os.path.exists(val)): + doError('file doesnt exist: %s' % val, False) + if(not os.access(val, os.X_OK)): + doError('file isnt executable: %s' % val, False) + try: + check = os.popen(val+' version').read().strip() + except: + doError('adb version failed to execute', False) + if(not re.match('Android Debug Bridge .*', check)): + doError('adb version failed to execute', False) + sysvals.adb = val + sysvals.android = True + elif(arg == '-x2'): + if(sysvals.postresumetime > 0): + doError('-x2 is not compatible with -postres', False) + sysvals.execcount = 2 + elif(arg == '-x2delay'): + sysvals.x2delay = getArgInt('-x2delay', args, 0, 60000) + elif(arg == '-postres'): + if(sysvals.execcount != 1): + doError('-x2 is not compatible with -postres', False) + sysvals.postresumetime = getArgInt('-postres', args, 0, 3600) + elif(arg == '-f'): + sysvals.usecallgraph = True + elif(arg == '-modes'): + cmd = 'modes' + elif(arg == '-fpdt'): + cmd = 'fpdt' + elif(arg == '-usbtopo'): + cmd = 'usbtopo' + elif(arg == '-usbauto'): + cmd = 'usbauto' + elif(arg == '-status'): + cmd = 'status' + elif(arg == '-verbose'): + sysvals.verbose = True + elif(arg == '-v'): + print("Version %.1f" % sysvals.version) + sys.exit() + elif(arg == '-rtcwake'): + sysvals.rtcwake = True + sysvals.rtcwaketime = getArgInt('-rtcwake', args, 0, 3600) + elif(arg == '-multi'): + multitest['run'] = True + multitest['count'] = getArgInt('-multi n (exec count)', args, 2, 1000000) + multitest['delay'] = getArgInt('-multi d (delay between tests)', args, 0, 3600) + elif(arg == '-dmesg'): + try: + val = args.next() + except: + doError('No dmesg file supplied', True) + sysvals.notestrun = True + sysvals.dmesgfile = val + if(os.path.exists(sysvals.dmesgfile) == False): + doError('%s doesnt exist' % sysvals.dmesgfile, False) + elif(arg == '-ftrace'): + try: + val = args.next() + except: + doError('No ftrace file supplied', True) + sysvals.notestrun = True + sysvals.usecallgraph = True + sysvals.ftracefile = val + if(os.path.exists(sysvals.ftracefile) == False): + doError('%s doesnt exist' % sysvals.ftracefile, False) + elif(arg == '-summary'): + try: + val = args.next() + except: + doError('No directory supplied', True) + cmd = 'summary' + cmdarg = val + sysvals.notestrun = True + if(os.path.isdir(val) == False): + doError('%s isnt accesible' % val, False) + elif(arg == '-filter'): + try: + val = args.next() + except: + doError('No devnames supplied', True) + sysvals.setDeviceFilter(val) + elif(arg == '-h'): + printHelp() + sys.exit() + else: + doError('Invalid argument: '+arg, True) + + # just run a utility command and exit + if(cmd != ''): + if(cmd == 'status'): + statusCheck() + elif(cmd == 'fpdt'): + if(sysvals.android): + doError('cannot read FPDT on android device', False) + getFPDT(True) + elif(cmd == 'usbtopo'): + if(sysvals.android): + doError('cannot read USB topology '+\ + 'on an android device', False) + detectUSB(True) + elif(cmd == 'modes'): + modes = getModes() + print modes + elif(cmd == 'usbauto'): + setUSBDevicesAuto() + elif(cmd == 'summary'): + print("Generating a summary of folder \"%s\"" % cmdarg) + runSummary(cmdarg, True) + sys.exit() + + # run test on android device + if(sysvals.android): + if(sysvals.usecallgraph): + doError('ftrace (-f) is not yet supported '+\ + 'in the android kernel', False) + if(sysvals.notestrun): + doError('cannot analyze test files on the '+\ + 'android device', False) + + # if instructed, re-analyze existing data files + if(sysvals.notestrun): + rerunTest() + sys.exit() + + # verify that we can run a test + if(not statusCheck()): + print('Check FAILED, aborting the test run!') + sys.exit() + + if multitest['run']: + # run multiple tests in a separte subdirectory + s = 'x%d' % multitest['count'] + subdir = datetime.now().strftime('suspend-'+s+'-%m%d%y-%H%M%S') + os.mkdir(subdir) + for i in range(multitest['count']): + if(i != 0): + print('Waiting %d seconds...' % (multitest['delay'])) + time.sleep(multitest['delay']) + print('TEST (%d/%d) START' % (i+1, multitest['count'])) + runTest(subdir) + print('TEST (%d/%d) COMPLETE' % (i+1, multitest['count'])) + runSummary(subdir, False) + else: + # run the test in the current directory + runTest(".") diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c index 12be1fb512dd..c4b0434c7604 100644 --- a/sound/oss/kahlua.c +++ b/sound/oss/kahlua.c @@ -197,7 +197,7 @@ MODULE_LICENSE("GPL"); * 5530 only. The 5510/5520 decode is different. */ -static DEFINE_PCI_DEVICE_TABLE(id_tbl) = { +static const struct pci_device_id id_tbl[] = { { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO), 0 }, { } }; diff --git a/sound/oss/uart401.c b/sound/oss/uart401.c index 62b8869f5a4c..279bc565ac7e 100644 --- a/sound/oss/uart401.c +++ b/sound/oss/uart401.c @@ -30,7 +30,7 @@ #include "mpu401.h" -typedef struct uart401_devc +struct uart401_devc { int base; int irq; @@ -41,14 +41,13 @@ typedef struct uart401_devc int my_dev; int share_irq; spinlock_t lock; -} -uart401_devc; +}; #define DATAPORT (devc->base) #define COMDPORT (devc->base+1) #define STATPORT (devc->base+1) -static int uart401_status(uart401_devc * devc) +static int uart401_status(struct uart401_devc *devc) { return inb(STATPORT); } @@ -56,17 +55,17 @@ static int uart401_status(uart401_devc * devc) #define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL)) #define output_ready(devc) (!(uart401_status(devc)&OUTPUT_READY)) -static void uart401_cmd(uart401_devc * devc, unsigned char cmd) +static void uart401_cmd(struct uart401_devc *devc, unsigned char cmd) { outb((cmd), COMDPORT); } -static int uart401_read(uart401_devc * devc) +static int uart401_read(struct uart401_devc *devc) { return inb(DATAPORT); } -static void uart401_write(uart401_devc * devc, unsigned char byte) +static void uart401_write(struct uart401_devc *devc, unsigned char byte) { outb((byte), DATAPORT); } @@ -77,10 +76,10 @@ static void uart401_write(uart401_devc * devc, unsigned char byte) #define MPU_RESET 0xFF #define UART_MODE_ON 0x3F -static int reset_uart401(uart401_devc * devc); -static void enter_uart_mode(uart401_devc * devc); +static int reset_uart401(struct uart401_devc *devc); +static void enter_uart_mode(struct uart401_devc *devc); -static void uart401_input_loop(uart401_devc * devc) +static void uart401_input_loop(struct uart401_devc *devc) { int work_limit=30000; @@ -99,7 +98,7 @@ static void uart401_input_loop(uart401_devc * devc) irqreturn_t uart401intr(int irq, void *dev_id) { - uart401_devc *devc = dev_id; + struct uart401_devc *devc = dev_id; if (devc == NULL) { @@ -118,7 +117,8 @@ uart401_open(int dev, int mode, void (*output) (int dev) ) { - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; + struct uart401_devc *devc = (struct uart401_devc *) + midi_devs[dev]->devc; if (devc->opened) return -EBUSY; @@ -138,7 +138,8 @@ uart401_open(int dev, int mode, static void uart401_close(int dev) { - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; + struct uart401_devc *devc = (struct uart401_devc *) + midi_devs[dev]->devc; reset_uart401(devc); devc->opened = 0; @@ -148,7 +149,8 @@ static int uart401_out(int dev, unsigned char midi_byte) { int timeout; unsigned long flags; - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; + struct uart401_devc *devc = (struct uart401_devc *) + midi_devs[dev]->devc; if (devc->disabled) return 1; @@ -219,7 +221,7 @@ static const struct midi_operations uart401_operations = .buffer_status = uart401_buffer_status, }; -static void enter_uart_mode(uart401_devc * devc) +static void enter_uart_mode(struct uart401_devc *devc) { int ok, timeout; unsigned long flags; @@ -241,7 +243,7 @@ static void enter_uart_mode(uart401_devc * devc) spin_unlock_irqrestore(&devc->lock,flags); } -static int reset_uart401(uart401_devc * devc) +static int reset_uart401(struct uart401_devc *devc) { int ok, timeout, n; @@ -285,7 +287,7 @@ static int reset_uart401(uart401_devc * devc) int probe_uart401(struct address_info *hw_config, struct module *owner) { - uart401_devc *devc; + struct uart401_devc *devc; char *name = "MPU-401 (UART) MIDI"; int ok = 0; unsigned long flags; @@ -300,7 +302,7 @@ int probe_uart401(struct address_info *hw_config, struct module *owner) return 0; } - devc = kmalloc(sizeof(uart401_devc), GFP_KERNEL); + devc = kmalloc(sizeof(struct uart401_devc), GFP_KERNEL); if (!devc) { printk(KERN_WARNING "uart401: Can't allocate memory\n"); goto cleanup_region; @@ -392,7 +394,7 @@ cleanup_region: void unload_uart401(struct address_info *hw_config) { - uart401_devc *devc; + struct uart401_devc *devc; int n=hw_config->slots[4]; /* Not set up */ diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c index 672af8b56542..b36ea47527e8 100644 --- a/sound/oss/waveartist.c +++ b/sound/oss/waveartist.c @@ -92,7 +92,7 @@ static unsigned short levels[SOUND_MIXER_NRDEVICES] = { 0x0000 /* Monitor */ }; -typedef struct { +struct wavnc_info { struct address_info hw; /* hardware */ char *chip_name; @@ -119,7 +119,7 @@ typedef struct { unsigned int line_mute_state :1;/* set by ioctl or autoselect */ unsigned int use_slider :1;/* use slider setting for o/p vol */ #endif -} wavnc_info; +}; /* * This is the implementation specific mixer information. @@ -129,29 +129,30 @@ struct waveartist_mixer_info { unsigned int recording_devs; /* Recordable devies */ unsigned int stereo_devs; /* Stereo devices */ - unsigned int (*select_input)(wavnc_info *, unsigned int, + unsigned int (*select_input)(struct wavnc_info *, unsigned int, unsigned char *, unsigned char *); - int (*decode_mixer)(wavnc_info *, int, + int (*decode_mixer)(struct wavnc_info *, int, unsigned char, unsigned char); - int (*get_mixer)(wavnc_info *, int); + int (*get_mixer)(struct wavnc_info *, int); }; -typedef struct wavnc_port_info { +struct wavnc_port_info { int open_mode; int speed; int channels; int audio_format; -} wavnc_port_info; +}; static int nr_waveartist_devs; -static wavnc_info adev_info[MAX_AUDIO_DEV]; +static struct wavnc_info adev_info[MAX_AUDIO_DEV]; static DEFINE_SPINLOCK(waveartist_lock); #ifndef CONFIG_ARCH_NETWINDER #define machine_is_netwinder() 0 #else static struct timer_list vnc_timer; -static void vnc_configure_mixer(wavnc_info *devc, unsigned int input_mask); +static void vnc_configure_mixer(struct wavnc_info *devc, + unsigned int input_mask); static int vnc_private_ioctl(int dev, unsigned int cmd, int __user *arg); static void vnc_slider_tick(unsigned long data); #endif @@ -169,7 +170,7 @@ waveartist_set_ctlr(struct address_info *hw, unsigned char clear, unsigned char /* Toggle IRQ acknowledge line */ static inline void -waveartist_iack(wavnc_info *devc) +waveartist_iack(struct wavnc_info *devc) { unsigned int ctlr_port = devc->hw.io_base + CTLR; int old_ctlr; @@ -188,7 +189,7 @@ waveartist_sleep(int timeout_ms) } static int -waveartist_reset(wavnc_info *devc) +waveartist_reset(struct wavnc_info *devc) { struct address_info *hw = &devc->hw; unsigned int timeout, res = -1; @@ -223,7 +224,7 @@ waveartist_reset(wavnc_info *devc) * and can send or receive multiple words. */ static int -waveartist_cmd(wavnc_info *devc, +waveartist_cmd(struct wavnc_info *devc, int nr_cmd, unsigned int *cmd, int nr_resp, unsigned int *resp) { @@ -299,7 +300,7 @@ waveartist_cmd(wavnc_info *devc, * Send one command word */ static inline int -waveartist_cmd1(wavnc_info *devc, unsigned int cmd) +waveartist_cmd1(struct wavnc_info *devc, unsigned int cmd) { return waveartist_cmd(devc, 1, &cmd, 0, NULL); } @@ -308,7 +309,7 @@ waveartist_cmd1(wavnc_info *devc, unsigned int cmd) * Send one command, receive one word */ static inline unsigned int -waveartist_cmd1_r(wavnc_info *devc, unsigned int cmd) +waveartist_cmd1_r(struct wavnc_info *devc, unsigned int cmd) { unsigned int ret; @@ -322,7 +323,7 @@ waveartist_cmd1_r(wavnc_info *devc, unsigned int cmd) * word (and throw it away) */ static inline int -waveartist_cmd2(wavnc_info *devc, unsigned int cmd, unsigned int arg) +waveartist_cmd2(struct wavnc_info *devc, unsigned int cmd, unsigned int arg) { unsigned int vals[2]; @@ -336,7 +337,7 @@ waveartist_cmd2(wavnc_info *devc, unsigned int cmd, unsigned int arg) * Send a triple command */ static inline int -waveartist_cmd3(wavnc_info *devc, unsigned int cmd, +waveartist_cmd3(struct wavnc_info *devc, unsigned int cmd, unsigned int arg1, unsigned int arg2) { unsigned int vals[3]; @@ -349,7 +350,7 @@ waveartist_cmd3(wavnc_info *devc, unsigned int cmd, } static int -waveartist_getrev(wavnc_info *devc, char *rev) +waveartist_getrev(struct wavnc_info *devc, char *rev) { unsigned int temp[2]; unsigned int cmd = WACMD_GETREV; @@ -371,15 +372,15 @@ static void waveartist_trigger(int dev, int state); static int waveartist_open(int dev, int mode) { - wavnc_info *devc; - wavnc_port_info *portc; + struct wavnc_info *devc; + struct wavnc_port_info *portc; unsigned long flags; if (dev < 0 || dev >= num_audiodevs) return -ENXIO; - devc = (wavnc_info *) audio_devs[dev]->devc; - portc = (wavnc_port_info *) audio_devs[dev]->portc; + devc = (struct wavnc_info *) audio_devs[dev]->devc; + portc = (struct wavnc_port_info *) audio_devs[dev]->portc; spin_lock_irqsave(&waveartist_lock, flags); if (portc->open_mode || (devc->open_mode & mode)) { @@ -404,8 +405,10 @@ waveartist_open(int dev, int mode) static void waveartist_close(int dev) { - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; + struct wavnc_info *devc = (struct wavnc_info *) + audio_devs[dev]->devc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; unsigned long flags; spin_lock_irqsave(&waveartist_lock, flags); @@ -422,8 +425,10 @@ waveartist_close(int dev) static void waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag) { - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; + struct wavnc_info *devc = (struct wavnc_info *) + audio_devs[dev]->devc; unsigned long flags; unsigned int count = __count; @@ -467,8 +472,10 @@ waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag) static void waveartist_start_input(int dev, unsigned long buf, int __count, int intrflag) { - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; + struct wavnc_info *devc = (struct wavnc_info *) + audio_devs[dev]->devc; unsigned long flags; unsigned int count = __count; @@ -514,7 +521,7 @@ waveartist_ioctl(int dev, unsigned int cmd, void __user * arg) } static unsigned int -waveartist_get_speed(wavnc_port_info *portc) +waveartist_get_speed(struct wavnc_port_info *portc) { unsigned int speed; @@ -542,7 +549,7 @@ waveartist_get_speed(wavnc_port_info *portc) } static unsigned int -waveartist_get_bits(wavnc_port_info *portc) +waveartist_get_bits(struct wavnc_port_info *portc) { unsigned int bits; @@ -560,8 +567,10 @@ static int waveartist_prepare_for_input(int dev, int bsize, int bcount) { unsigned long flags; - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; + struct wavnc_info *devc = (struct wavnc_info *) + audio_devs[dev]->devc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; unsigned int speed, bits; if (devc->audio_mode) @@ -615,8 +624,10 @@ static int waveartist_prepare_for_output(int dev, int bsize, int bcount) { unsigned long flags; - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; + struct wavnc_info *devc = (struct wavnc_info *) + audio_devs[dev]->devc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; unsigned int speed, bits; /* @@ -660,8 +671,9 @@ waveartist_prepare_for_output(int dev, int bsize, int bcount) static void waveartist_halt(int dev) { - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - wavnc_info *devc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; + struct wavnc_info *devc; if (portc->open_mode & OPEN_WRITE) waveartist_halt_output(dev); @@ -669,14 +681,15 @@ waveartist_halt(int dev) if (portc->open_mode & OPEN_READ) waveartist_halt_input(dev); - devc = (wavnc_info *) audio_devs[dev]->devc; + devc = (struct wavnc_info *) audio_devs[dev]->devc; devc->audio_mode = 0; } static void waveartist_halt_input(int dev) { - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; + struct wavnc_info *devc = (struct wavnc_info *) + audio_devs[dev]->devc; unsigned long flags; spin_lock_irqsave(&waveartist_lock, flags); @@ -703,7 +716,8 @@ waveartist_halt_input(int dev) static void waveartist_halt_output(int dev) { - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; + struct wavnc_info *devc = (struct wavnc_info *) + audio_devs[dev]->devc; unsigned long flags; spin_lock_irqsave(&waveartist_lock, flags); @@ -727,8 +741,10 @@ waveartist_halt_output(int dev) static void waveartist_trigger(int dev, int state) { - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; + struct wavnc_info *devc = (struct wavnc_info *) + audio_devs[dev]->devc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; unsigned long flags; if (debug_flg & DEBUG_TRIGGER) { @@ -764,7 +780,8 @@ waveartist_trigger(int dev, int state) static int waveartist_set_speed(int dev, int arg) { - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; if (arg <= 0) return portc->speed; @@ -782,7 +799,8 @@ waveartist_set_speed(int dev, int arg) static short waveartist_set_channels(int dev, short arg) { - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; if (arg != 1 && arg != 2) return portc->channels; @@ -794,7 +812,8 @@ waveartist_set_channels(int dev, short arg) static unsigned int waveartist_set_bits(int dev, unsigned int arg) { - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; + struct wavnc_port_info *portc = (struct wavnc_port_info *) + audio_devs[dev]->portc; if (arg == 0) return portc->audio_format; @@ -829,7 +848,7 @@ static struct audio_driver waveartist_audio_driver = { static irqreturn_t waveartist_intr(int irq, void *dev_id) { - wavnc_info *devc = dev_id; + struct wavnc_info *devc = dev_id; int irqstatus, status; spin_lock(&waveartist_lock); @@ -912,7 +931,7 @@ static const struct mix_ent mix_devs[SOUND_MIXER_NRDEVICES] = { }; static void -waveartist_mixer_update(wavnc_info *devc, int whichDev) +waveartist_mixer_update(struct wavnc_info *devc, int whichDev) { unsigned int lev_left, lev_right; @@ -973,7 +992,8 @@ waveartist_mixer_update(wavnc_info *devc, int whichDev) * relevant *_select_input function has done that for us. */ static void -waveartist_set_adc_mux(wavnc_info *devc, char left_dev, char right_dev) +waveartist_set_adc_mux(struct wavnc_info *devc, char left_dev, + char right_dev) { unsigned int reg_08, reg_09; @@ -996,7 +1016,7 @@ waveartist_set_adc_mux(wavnc_info *devc, char left_dev, char right_dev) * SOUND_MASK_MIC Mic Microphone */ static unsigned int -waveartist_select_input(wavnc_info *devc, unsigned int recmask, +waveartist_select_input(struct wavnc_info *devc, unsigned int recmask, unsigned char *dev_l, unsigned char *dev_r) { unsigned int recdev = ADC_MUX_NONE; @@ -1024,7 +1044,8 @@ waveartist_select_input(wavnc_info *devc, unsigned int recmask, } static int -waveartist_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, +waveartist_decode_mixer(struct wavnc_info *devc, int dev, + unsigned char lev_l, unsigned char lev_r) { switch (dev) { @@ -1050,7 +1071,7 @@ waveartist_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, return dev; } -static int waveartist_get_mixer(wavnc_info *devc, int dev) +static int waveartist_get_mixer(struct wavnc_info *devc, int dev) { return devc->levels[dev]; } @@ -1068,7 +1089,7 @@ static const struct waveartist_mixer_info waveartist_mixer = { }; static void -waveartist_set_recmask(wavnc_info *devc, unsigned int recmask) +waveartist_set_recmask(struct wavnc_info *devc, unsigned int recmask) { unsigned char dev_l, dev_r; @@ -1092,7 +1113,7 @@ waveartist_set_recmask(wavnc_info *devc, unsigned int recmask) } static int -waveartist_set_mixer(wavnc_info *devc, int dev, unsigned int level) +waveartist_set_mixer(struct wavnc_info *devc, int dev, unsigned int level) { unsigned int lev_left = level & 0x00ff; unsigned int lev_right = (level & 0xff00) >> 8; @@ -1120,7 +1141,7 @@ waveartist_set_mixer(wavnc_info *devc, int dev, unsigned int level) static int waveartist_mixer_ioctl(int dev, unsigned int cmd, void __user * arg) { - wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc; + struct wavnc_info *devc = (struct wavnc_info *)audio_devs[dev]->devc; int ret = 0, val, nr; /* @@ -1204,7 +1225,7 @@ static struct mixer_operations waveartist_mixer_operations = }; static void -waveartist_mixer_reset(wavnc_info *devc) +waveartist_mixer_reset(struct wavnc_info *devc) { int i; @@ -1241,9 +1262,9 @@ waveartist_mixer_reset(wavnc_info *devc) waveartist_mixer_update(devc, i); } -static int __init waveartist_init(wavnc_info *devc) +static int __init waveartist_init(struct wavnc_info *devc) { - wavnc_port_info *portc; + struct wavnc_port_info *portc; char rev[3], dev_name[64]; int my_dev; @@ -1261,7 +1282,7 @@ static int __init waveartist_init(wavnc_info *devc) conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq, devc->hw.dma, devc->hw.dma2); - portc = kzalloc(sizeof(wavnc_port_info), GFP_KERNEL); + portc = kzalloc(sizeof(struct wavnc_port_info), GFP_KERNEL); if (portc == NULL) goto nomem; @@ -1330,7 +1351,7 @@ nomem: static int __init probe_waveartist(struct address_info *hw_config) { - wavnc_info *devc = &adev_info[nr_waveartist_devs]; + struct wavnc_info *devc = &adev_info[nr_waveartist_devs]; if (nr_waveartist_devs >= MAX_AUDIO_DEV) { printk(KERN_WARNING "waveartist: too many audio devices\n"); @@ -1367,7 +1388,7 @@ static int __init probe_waveartist(struct address_info *hw_config) static void __init attach_waveartist(struct address_info *hw, const struct waveartist_mixer_info *mix) { - wavnc_info *devc = &adev_info[nr_waveartist_devs]; + struct wavnc_info *devc = &adev_info[nr_waveartist_devs]; /* * NOTE! If irq < 0, there is another driver which has allocated the @@ -1410,7 +1431,7 @@ attach_waveartist(struct address_info *hw, const struct waveartist_mixer_info *m static void __exit unload_waveartist(struct address_info *hw) { - wavnc_info *devc = NULL; + struct wavnc_info *devc = NULL; int i; for (i = 0; i < nr_waveartist_devs; i++) @@ -1478,7 +1499,7 @@ static void __exit unload_waveartist(struct address_info *hw) #define VNC_DISABLE_AUTOSWITCH 0x80 static inline void -vnc_mute_spkr(wavnc_info *devc) +vnc_mute_spkr(struct wavnc_info *devc) { unsigned long flags; @@ -1488,7 +1509,7 @@ vnc_mute_spkr(wavnc_info *devc) } static void -vnc_mute_lout(wavnc_info *devc) +vnc_mute_lout(struct wavnc_info *devc) { unsigned int left, right; @@ -1507,7 +1528,7 @@ vnc_mute_lout(wavnc_info *devc) } static int -vnc_volume_slider(wavnc_info *devc) +vnc_volume_slider(struct wavnc_info *devc) { static signed int old_slider_volume; unsigned long flags; @@ -1567,7 +1588,7 @@ vnc_volume_slider(wavnc_info *devc) * SOUND_MASK_MIC Right Mic Builtin microphone */ static unsigned int -netwinder_select_input(wavnc_info *devc, unsigned int recmask, +netwinder_select_input(struct wavnc_info *devc, unsigned int recmask, unsigned char *dev_l, unsigned char *dev_r) { unsigned int recdev_l = ADC_MUX_NONE, recdev_r = ADC_MUX_NONE; @@ -1604,7 +1625,7 @@ netwinder_select_input(wavnc_info *devc, unsigned int recmask, } static int -netwinder_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, +netwinder_decode_mixer(struct wavnc_info *devc, int dev, unsigned char lev_l, unsigned char lev_r) { switch (dev) { @@ -1643,7 +1664,7 @@ netwinder_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, return dev; } -static int netwinder_get_mixer(wavnc_info *devc, int dev) +static int netwinder_get_mixer(struct wavnc_info *devc, int dev) { int levels; @@ -1703,7 +1724,7 @@ static const struct waveartist_mixer_info netwinder_mixer = { }; static void -vnc_configure_mixer(wavnc_info *devc, unsigned int recmask) +vnc_configure_mixer(struct wavnc_info *devc, unsigned int recmask) { if (!devc->no_autoselect) { if (devc->handset_detect) { @@ -1729,7 +1750,7 @@ vnc_configure_mixer(wavnc_info *devc, unsigned int recmask) } static int -vnc_slider(wavnc_info *devc) +vnc_slider(struct wavnc_info *devc) { signed int slider_volume; unsigned int temp, old_hs, old_td; @@ -1795,7 +1816,7 @@ vnc_slider_tick(unsigned long data) static int vnc_private_ioctl(int dev, unsigned int cmd, int __user * arg) { - wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc; + struct wavnc_info *devc = (struct wavnc_info *)audio_devs[dev]->devc; int val; switch (cmd) { diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 488f966adde3..7bfdf9c51416 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -1045,7 +1045,7 @@ snd_ad1889_remove(struct pci_dev *pci) snd_card_free(pci_get_drvdata(pci)); } -static DEFINE_PCI_DEVICE_TABLE(snd_ad1889_ids) = { +static const struct pci_device_id snd_ad1889_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) }, { 0, }, }; diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index feb29c24cab1..af89e42b2160 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -263,7 +263,7 @@ struct snd_ali { #endif }; -static DEFINE_PCI_DEVICE_TABLE(snd_ali_ids) = { +static const struct pci_device_id snd_ali_ids[] = { {PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0}, {0, } }; diff --git a/sound/pci/als300.c b/sound/pci/als300.c index cc9a15a1304b..7bb6ac565107 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -141,7 +141,7 @@ struct snd_als300_substream_data { int block_counter_register; }; -static DEFINE_PCI_DEVICE_TABLE(snd_als300_ids) = { +static const struct pci_device_id snd_als300_ids[] = { { 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 }, { 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS }, { 0, } diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index b751c381d25e..d3e6424ee656 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -116,7 +116,7 @@ struct snd_card_als4000 { #endif }; -static DEFINE_PCI_DEVICE_TABLE(snd_als4000_ids) = { +static const struct pci_device_id snd_als4000_ids[] = { { 0x4005, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ALS4000 */ { 0, } }; diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 901c9490398a..5017176bfaa1 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -2955,7 +2955,7 @@ static void snd_asihpi_remove(struct pci_dev *pci_dev) asihpi_adapter_remove(pci_dev); } -static DEFINE_PCI_DEVICE_TABLE(asihpi_pci_tbl) = { +static const struct pci_device_id asihpi_pci_tbl[] = { {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205, HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, (kernel_ulong_t)HPI_6205}, diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index ae07b4926dc2..7895c5d300c7 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -286,7 +286,7 @@ struct atiixp { /* */ -static DEFINE_PCI_DEVICE_TABLE(snd_atiixp_ids) = { +static const struct pci_device_id snd_atiixp_ids[] = { { PCI_VDEVICE(ATI, 0x4341), 0 }, /* SB200 */ { PCI_VDEVICE(ATI, 0x4361), 0 }, /* SB300 */ { PCI_VDEVICE(ATI, 0x4370), 0 }, /* SB400 */ diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index b9dc96c5d21e..3c3241309a30 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -261,7 +261,7 @@ struct atiixp_modem { /* */ -static DEFINE_PCI_DEVICE_TABLE(snd_atiixp_ids) = { +static const struct pci_device_id snd_atiixp_ids[] = { { PCI_VDEVICE(ATI, 0x434d), 0 }, /* SB200 */ { PCI_VDEVICE(ATI, 0x4378), 0 }, /* SB400 */ { 0, } diff --git a/sound/pci/au88x0/au8810.c b/sound/pci/au88x0/au8810.c index aa51cc7771dd..1b2e34069eb3 100644 --- a/sound/pci/au88x0/au8810.c +++ b/sound/pci/au88x0/au8810.c @@ -1,6 +1,6 @@ #include "au8810.h" #include "au88x0.h" -static DEFINE_PCI_DEVICE_TABLE(snd_vortex_ids) = { +static const struct pci_device_id snd_vortex_ids[] = { {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE), 1,}, {0,} }; diff --git a/sound/pci/au88x0/au8820.c b/sound/pci/au88x0/au8820.c index 2f321e7306cd..74c53fa5f06b 100644 --- a/sound/pci/au88x0/au8820.c +++ b/sound/pci/au88x0/au8820.c @@ -1,6 +1,6 @@ #include "au8820.h" #include "au88x0.h" -static DEFINE_PCI_DEVICE_TABLE(snd_vortex_ids) = { +static const struct pci_device_id snd_vortex_ids[] = { {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1), 0,}, {0,} }; diff --git a/sound/pci/au88x0/au8830.c b/sound/pci/au88x0/au8830.c index 279b78f06d22..56f675aad3ad 100644 --- a/sound/pci/au88x0/au8830.c +++ b/sound/pci/au88x0/au8830.c @@ -1,6 +1,6 @@ #include "au8830.h" #include "au88x0.h" -static DEFINE_PCI_DEVICE_TABLE(snd_vortex_ids) = { +static const struct pci_device_id snd_vortex_ids[] = { {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2), 0,}, {0,} }; diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 120d0d320a60..3878cf5de9a4 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -160,7 +160,7 @@ MODULE_PARM_DESC(id, "ID string for the Audiowerk2 soundcard."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard."); -static DEFINE_PCI_DEVICE_TABLE(snd_aw2_ids) = { +static const struct pci_device_id snd_aw2_ids[] = { {PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0, 0, 0, 0, 0}, {0} diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index c9216c0a9c8b..5a69e26cb2fb 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -321,7 +321,7 @@ struct snd_azf3328 { #endif }; -static DEFINE_PCI_DEVICE_TABLE(snd_azf3328_ids) = { +static const struct pci_device_id snd_azf3328_ids[] = { { 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */ { 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */ { 0, } diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 70951fd9b354..058b9973c09c 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -796,7 +796,7 @@ fail: .driver_data = SND_BT87X_BOARD_ ## id } /* driver_data is the card id for that device */ -static DEFINE_PCI_DEVICE_TABLE(snd_bt87x_ids) = { +static const struct pci_device_id snd_bt87x_ids[] = { /* Hauppauge WinTV series */ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, GENERIC), /* Hauppauge WinTV series */ @@ -966,7 +966,7 @@ static void snd_bt87x_remove(struct pci_dev *pci) /* default entries for all Bt87x cards - it's not exported */ /* driver_data is set to 0 to call detection */ -static DEFINE_PCI_DEVICE_TABLE(snd_bt87x_default_ids) = { +static const struct pci_device_id snd_bt87x_default_ids[] = { BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), { } diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index f94cc6e97d4a..96af33965b51 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1968,7 +1968,7 @@ static SIMPLE_DEV_PM_OPS(snd_ca0106_pm, snd_ca0106_suspend, snd_ca0106_resume); #endif // PCI IDs -static DEFINE_PCI_DEVICE_TABLE(snd_ca0106_ids) = { +static const struct pci_device_id snd_ca0106_ids[] = { { PCI_VDEVICE(CREATIVE, 0x0007), 0 }, /* Audigy LS or Live 24bit */ { 0, } }; diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 12c318e175f4..85ed40339db9 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2803,7 +2803,7 @@ static inline void snd_cmipci_proc_init(struct cmipci *cm) {} #endif -static DEFINE_PCI_DEVICE_TABLE(snd_cmipci_ids) = { +static const struct pci_device_id snd_cmipci_ids[] = { {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A), 0}, {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B), 0}, {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738), 0}, @@ -3026,7 +3026,7 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, int integrated_midi = 0; char modelstr[16]; int pcm_index, pcm_spdif_index; - static DEFINE_PCI_DEVICE_TABLE(intel_82437vx) = { + static const struct pci_device_id intel_82437vx[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX) }, { }, }; diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 43d1f912c641..4c49b5c8a7b3 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -494,7 +494,7 @@ struct cs4281 { static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id); -static DEFINE_PCI_DEVICE_TABLE(snd_cs4281_ids) = { +static const struct pci_device_id snd_cs4281_ids[] = { { PCI_VDEVICE(CIRRUS, 0x6005), 0, }, /* CS4281 */ { 0, } }; diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index af0eacbc8bd2..6a6858c07826 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c @@ -64,7 +64,7 @@ MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control."); module_param_array(mmap_valid, bool, NULL, 0444); MODULE_PARM_DESC(mmap_valid, "Support OSS mmap."); -static DEFINE_PCI_DEVICE_TABLE(snd_cs46xx_ids) = { +static const struct pci_device_id snd_cs46xx_ids[] = { { PCI_VDEVICE(CIRRUS, 0x6001), 0, }, /* CS4280 */ { PCI_VDEVICE(CIRRUS, 0x6003), 0, }, /* CS4612 */ { PCI_VDEVICE(CIRRUS, 0x6004), 0, }, /* CS4615 */ diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index b4e0ff6a99a3..b1025507a467 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c @@ -66,7 +66,7 @@ struct snd_cs5530 { unsigned long pci_base; }; -static DEFINE_PCI_DEVICE_TABLE(snd_cs5530_ids) = { +static const struct pci_device_id snd_cs5530_ids[] = { {PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0}, {0,} diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index edcbbda5c488..16288e4d338a 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -66,7 +66,7 @@ MODULE_PARM_DESC(id, "ID string for " DRIVER_NAME); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable " DRIVER_NAME); -static DEFINE_PCI_DEVICE_TABLE(snd_cs5535audio_ids) = { +static const struct pci_device_id snd_cs5535audio_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO) }, {} diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index 98426d09c8bd..8f8b566a1b35 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c @@ -44,7 +44,7 @@ MODULE_PARM_DESC(enable, "Enable Creative X-Fi driver"); module_param_array(subsystem, int, NULL, 0444); MODULE_PARM_DESC(subsystem, "Override subsystem ID for Creative X-Fi driver"); -static DEFINE_PCI_DEVICE_TABLE(ct_pci_dev_ids) = { +static const struct pci_device_id ct_pci_dev_ids[] = { /* only X-Fi is supported, so... */ { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_20K1), .driver_data = ATC20K1, diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c index d47e72ae2ab3..4632946205a8 100644 --- a/sound/pci/echoaudio/darla20.c +++ b/sound/pci/echoaudio/darla20.c @@ -63,7 +63,7 @@ static const struct firmware card_fw[] = { {0, "darla20_dsp.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x1801, 0xECC0, 0x0010, 0, 0, 0}, /* DSP 56301 Darla20 rev.0 */ {0,} }; diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c index 413acf702e3b..f81c839cc887 100644 --- a/sound/pci/echoaudio/darla24.c +++ b/sound/pci/echoaudio/darla24.c @@ -67,7 +67,7 @@ static const struct firmware card_fw[] = { {0, "darla24_dsp.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x1801, 0xECC0, 0x0040, 0, 0, 0}, /* DSP 56301 Darla24 rev.0 */ {0x1057, 0x1801, 0xECC0, 0x0041, 0, 0, 0}, /* DSP 56301 Darla24 rev.1 */ {0,} diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c index 1ec4edca060d..3a5346c33d76 100644 --- a/sound/pci/echoaudio/echo3g.c +++ b/sound/pci/echoaudio/echo3g.c @@ -81,7 +81,7 @@ static const struct firmware card_fw[] = { {0, "3g_asic.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x3410, 0xECC0, 0x0100, 0, 0, 0}, /* Echo 3G */ {0,} }; diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c index 039125b7e475..9cb81c500824 100644 --- a/sound/pci/echoaudio/gina20.c +++ b/sound/pci/echoaudio/gina20.c @@ -67,7 +67,7 @@ static const struct firmware card_fw[] = { {0, "gina20_dsp.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x1801, 0xECC0, 0x0020, 0, 0, 0}, /* DSP 56301 Gina20 rev.0 */ {0,} }; diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c index 5e966f6ffaa3..35d3e6eac990 100644 --- a/sound/pci/echoaudio/gina24.c +++ b/sound/pci/echoaudio/gina24.c @@ -85,7 +85,7 @@ static const struct firmware card_fw[] = { {0, "gina24_361_asic.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x1801, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56301 Gina24 rev.0 */ {0x1057, 0x1801, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56301 Gina24 rev.1 */ {0x1057, 0x3410, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56361 Gina24 rev.0 */ diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c index c166b7eea268..8d91842d1268 100644 --- a/sound/pci/echoaudio/indigo.c +++ b/sound/pci/echoaudio/indigo.c @@ -68,7 +68,7 @@ static const struct firmware card_fw[] = { {0, "indigo_dsp.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x3410, 0xECC0, 0x0090, 0, 0, 0}, /* Indigo */ {0,} }; diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c index a3ef3b992f40..289cb969f5b9 100644 --- a/sound/pci/echoaudio/indigodj.c +++ b/sound/pci/echoaudio/indigodj.c @@ -68,7 +68,7 @@ static const struct firmware card_fw[] = { {0, "indigo_dj_dsp.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x3410, 0xECC0, 0x00B0, 0, 0, 0}, /* Indigo DJ*/ {0,} }; diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c index f516444fc02d..201688ee50fa 100644 --- a/sound/pci/echoaudio/indigodjx.c +++ b/sound/pci/echoaudio/indigodjx.c @@ -68,7 +68,7 @@ static const struct firmware card_fw[] = { {0, "indigo_djx_dsp.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x3410, 0xECC0, 0x00E0, 0, 0, 0}, /* Indigo DJx*/ {0,} }; diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c index c22c82fd1f99..405a3f2e496f 100644 --- a/sound/pci/echoaudio/indigoio.c +++ b/sound/pci/echoaudio/indigoio.c @@ -69,7 +69,7 @@ static const struct firmware card_fw[] = { {0, "indigo_io_dsp.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x3410, 0xECC0, 0x00A0, 0, 0, 0}, /* Indigo IO*/ {0,} }; diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c index 86cf2d071758..e145b688148a 100644 --- a/sound/pci/echoaudio/indigoiox.c +++ b/sound/pci/echoaudio/indigoiox.c @@ -69,7 +69,7 @@ static const struct firmware card_fw[] = { {0, "indigo_iox_dsp.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x3410, 0xECC0, 0x00D0, 0, 0, 0}, /* Indigo IOx */ {0,} }; diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c index 6a027f3931cc..b392dd776b71 100644 --- a/sound/pci/echoaudio/layla20.c +++ b/sound/pci/echoaudio/layla20.c @@ -76,7 +76,7 @@ static const struct firmware card_fw[] = { {0, "layla20_asic.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x1801, 0xECC0, 0x0030, 0, 0, 0}, /* DSP 56301 Layla20 rev.0 */ {0x1057, 0x1801, 0xECC0, 0x0031, 0, 0, 0}, /* DSP 56301 Layla20 rev.1 */ {0,} diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c index 96a5991aca8f..bc7f730b0ec6 100644 --- a/sound/pci/echoaudio/layla24.c +++ b/sound/pci/echoaudio/layla24.c @@ -87,7 +87,7 @@ static const struct firmware card_fw[] = { {0, "layla24_2S_asic.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x3410, 0xECC0, 0x0060, 0, 0, 0}, /* DSP 56361 Layla24 rev.0 */ {0,} }; diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c index b8ce27e67e3a..27a9a6e5db2d 100644 --- a/sound/pci/echoaudio/mia.c +++ b/sound/pci/echoaudio/mia.c @@ -77,7 +77,7 @@ static const struct firmware card_fw[] = { {0, "mia_dsp.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x3410, 0xECC0, 0x0080, 0, 0, 0}, /* DSP 56361 Mia rev.0 */ {0x1057, 0x3410, 0xECC0, 0x0081, 0, 0, 0}, /* DSP 56361 Mia rev.1 */ {0,} diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c index 1283bfb26b2e..3d13875c303d 100644 --- a/sound/pci/echoaudio/mona.c +++ b/sound/pci/echoaudio/mona.c @@ -92,7 +92,7 @@ static const struct firmware card_fw[] = { {0, "mona_2_asic.fw"} }; -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { +static const struct pci_device_id snd_echo_ids[] = { {0x1057, 0x1801, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56301 Mona rev.0 */ {0x1057, 0x1801, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56301 Mona rev.1 */ {0x1057, 0x1801, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56301 Mona rev.2 */ diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index ad9d9f8b48ed..4c171636efcd 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -79,7 +79,7 @@ MODULE_PARM_DESC(delay_pcm_irq, "Delay PCM interrupt by specified number of samp /* * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 */ -static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1_ids) = { +static const struct pci_device_id snd_emu10k1_ids[] = { { PCI_VDEVICE(CREATIVE, 0x0002), 0 }, /* EMU10K1 */ { PCI_VDEVICE(CREATIVE, 0x0004), 1 }, /* Audigy */ { PCI_VDEVICE(CREATIVE, 0x0008), 1 }, /* Audigy 2 Value SB0400 */ diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index efe017526977..e223de1408c0 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -1634,7 +1634,7 @@ static void snd_emu10k1x_remove(struct pci_dev *pci) } // PCI IDs -static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1x_ids) = { +static const struct pci_device_id snd_emu10k1x_ids[] = { { PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */ { 0, } }; diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 29cd339ffc37..d94cb3ca7a64 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -446,7 +446,7 @@ struct ensoniq { static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id); -static DEFINE_PCI_DEVICE_TABLE(snd_audiopci_ids) = { +static const struct pci_device_id snd_audiopci_ids[] = { #ifdef CHIP1370 { PCI_VDEVICE(ENSONIQ, 0x5000), 0, }, /* ES1370 */ #endif diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 34d95bf916b5..639962443ccc 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -243,7 +243,7 @@ struct es1938 { static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id); -static DEFINE_PCI_DEVICE_TABLE(snd_es1938_ids) = { +static const struct pci_device_id snd_es1938_ids[] = { { PCI_VDEVICE(ESS, 0x1969), 0, }, /* Solo-1 */ { 0, } }; diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5bb1cf603301..a9956a7c5677 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -570,7 +570,7 @@ struct es1968 { static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); -static DEFINE_PCI_DEVICE_TABLE(snd_es1968_ids) = { +static const struct pci_device_id snd_es1968_ids[] = { /* Maestro 1 */ { 0x1285, 0x0100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO }, /* Maestro 2 */ diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 529f5f4f4c9c..c5038303a126 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -218,7 +218,7 @@ struct fm801 { #endif }; -static DEFINE_PCI_DEVICE_TABLE(snd_fm801_ids) = { +static const struct pci_device_id snd_fm801_ids[] = { { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */ { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */ { 0, } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 5db1948699d8..aa302fb03fc5 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -265,6 +265,7 @@ enum { AZX_DRIVER_TERA, AZX_DRIVER_CTX, AZX_DRIVER_CTHDA, + AZX_DRIVER_CMEDIA, AZX_DRIVER_GENERIC, AZX_NUM_DRIVERS, /* keep this as last entry */ }; @@ -330,6 +331,7 @@ static char *driver_short_names[] = { [AZX_DRIVER_TERA] = "HDA Teradici", [AZX_DRIVER_CTX] = "HDA Creative", [AZX_DRIVER_CTHDA] = "HDA Creative", + [AZX_DRIVER_CMEDIA] = "HDA C-Media", [AZX_DRIVER_GENERIC] = "HD-Audio Generic", }; @@ -1373,6 +1375,7 @@ static void azx_check_snoop_available(struct azx *chip) snoop = false; break; case AZX_DRIVER_CTHDA: + case AZX_DRIVER_CMEDIA: snoop = false; break; } @@ -2154,6 +2157,10 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, #endif + /* CM8888 */ + { PCI_DEVICE(0x13f6, 0x5011), + .driver_data = AZX_DRIVER_CMEDIA | + AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB }, /* Vortex86MX */ { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, /* VMware HDAudio */ diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 4f3aba78f720..5d8455e2dacd 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -4376,6 +4376,9 @@ static void ca0132_download_dsp(struct hda_codec *codec) return; /* NOP */ #endif + if (spec->dsp_state == DSP_DOWNLOAD_FAILED) + return; /* don't retry failures */ + chipio_enable_clocks(codec); spec->dsp_state = DSP_DOWNLOADING; if (!ca0132_download_dsp_images(codec)) @@ -4552,7 +4555,8 @@ static int ca0132_init(struct hda_codec *codec) struct auto_pin_cfg *cfg = &spec->autocfg; int i; - spec->dsp_state = DSP_DOWNLOAD_INIT; + if (spec->dsp_state != DSP_DOWNLOAD_FAILED) + spec->dsp_state = DSP_DOWNLOAD_INIT; spec->curr_chip_addx = INVALID_CHIP_ADDRESS; snd_hda_power_up(codec); @@ -4663,6 +4667,7 @@ static int patch_ca0132(struct hda_codec *codec) codec->spec = spec; spec->codec = codec; + spec->dsp_state = DSP_DOWNLOAD_INIT; spec->num_mixers = 1; spec->mixers[0] = ca0132_mixer; diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index ed3d133ffbb6..c895a8f21192 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c @@ -75,15 +75,62 @@ static int patch_cmi9880(struct hda_codec *codec) return err; } +static int patch_cmi8888(struct hda_codec *codec) +{ + struct cmi_spec *spec; + struct auto_pin_cfg *cfg; + int err; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + codec->spec = spec; + cfg = &spec->gen.autocfg; + snd_hda_gen_spec_init(&spec->gen); + + /* mask NID 0x10 from the playback volume selection; + * it's a headphone boost volume handled manually below + */ + spec->gen.out_vol_mask = (1ULL << 0x10); + + err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); + if (err < 0) + goto error; + err = snd_hda_gen_parse_auto_config(codec, cfg); + if (err < 0) + goto error; + + if (get_defcfg_device(snd_hda_codec_get_pincfg(codec, 0x10)) == + AC_JACK_HP_OUT) { + static const struct snd_kcontrol_new amp_kctl = + HDA_CODEC_VOLUME("Headphone Amp Playback Volume", + 0x10, 0, HDA_OUTPUT); + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &_kctl)) { + err = -ENOMEM; + goto error; + } + } + + codec->patch_ops = cmi_auto_patch_ops; + return 0; + + error: + snd_hda_gen_free(codec); + return err; +} + /* * patch entries */ static const struct hda_codec_preset snd_hda_preset_cmedia[] = { + { .id = 0x13f68888, .name = "CMI8888", .patch = patch_cmi8888 }, { .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 }, { .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 }, {} /* terminator */ }; +MODULE_ALIAS("snd-hda-codec-id:13f68888"); MODULE_ALIAS("snd-hda-codec-id:13f69880"); MODULE_ALIAS("snd-hda-codec-id:434d4980"); diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 7627a69ca6d7..6f2fa838b635 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -26,6 +26,7 @@ #include <linux/module.h> #include <sound/core.h> #include <sound/jack.h> +#include <sound/tlv.h> #include "hda_codec.h" #include "hda_local.h" @@ -859,6 +860,11 @@ static int patch_conexant_auto(struct hda_codec *codec) if (err < 0) goto error; + if (codec->vendor_id == 0x14f15051) { + /* minimum value is actually mute */ + spec->gen.vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; + } + codec->patch_ops = cx_auto_patch_ops; /* Some laptops with Conexant chips show stalls in S3 resume, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 654c8f16d150..6b38ec3c6e57 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2782,6 +2782,27 @@ static int alc269_parse_auto_config(struct hda_codec *codec) return alc_parse_auto_config(codec, alc269_ignore, ssids); } +static int find_ext_mic_pin(struct hda_codec *codec); + +static void alc286_shutup(struct hda_codec *codec) +{ + int i; + int mic_pin = find_ext_mic_pin(codec); + /* don't shut up pins when unloading the driver; otherwise it breaks + * the default pin setup at the next load of the driver + */ + if (codec->bus->shutdown) + return; + for (i = 0; i < codec->init_pins.used; i++) { + struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); + /* use read here for syncing after issuing each verb */ + if (pin->nid != mic_pin) + snd_hda_codec_read(codec, pin->nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + } + codec->pins_shutup = 1; +} + static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) { int val = alc_read_coef_idx(codec, 0x04); @@ -4072,7 +4093,7 @@ static unsigned int alc_power_filter_xps13(struct hda_codec *codec, /* Avoid pop noises when headphones are plugged in */ if (spec->gen.hp_jack_present) - if (nid == codec->afg || nid == 0x02) + if (nid == codec->afg || nid == 0x02 || nid == 0x15) return AC_PWRST_D0; return power_state; } @@ -4082,8 +4103,19 @@ static void alc_fixup_dell_xps13(struct hda_codec *codec, { if (action == HDA_FIXUP_ACT_PROBE) { struct alc_spec *spec = codec->spec; + struct hda_input_mux *imux = &spec->gen.input_mux; + int i; + spec->shutup = alc_no_shutup; codec->power_filter = alc_power_filter_xps13; + + /* Make the internal mic the default input source. */ + for (i = 0; i < imux->num_items; i++) { + if (spec->gen.imux_pins[i] == 0x12) { + spec->gen.cur_mux[0] = i; + break; + } + } } } @@ -5384,6 +5416,7 @@ static int patch_alc269(struct hda_codec *codec) case 0x10ec0286: case 0x10ec0288: spec->codec_variant = ALC269_TYPE_ALC286; + spec->shutup = alc286_shutup; break; case 0x10ec0255: spec->codec_variant = ALC269_TYPE_ALC255; diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index d9b9e4595f17..87f7fc41d4f2 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -105,7 +105,7 @@ module_param_array(dxr_enable, int, NULL, 0444); MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE."); -static DEFINE_PCI_DEVICE_TABLE(snd_ice1712_ids) = { +static const struct pci_device_id snd_ice1712_ids[] = { { PCI_VDEVICE(ICE, PCI_DEVICE_ID_ICE_1712), 0 }, /* ICE1712 */ { 0, } }; diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 5e7948f3efe9..08cb08ac85e6 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -94,7 +94,7 @@ MODULE_PARM_DESC(model, "Use the given board model."); /* Both VT1720 and VT1724 have the same PCI IDs */ -static DEFINE_PCI_DEVICE_TABLE(snd_vt1724_ids) = { +static const struct pci_device_id snd_vt1724_ids[] = { { PCI_VDEVICE(ICE, PCI_DEVICE_ID_VT1724), 0 }, { 0, } }; diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index c91860e0a28d..4a28252a42b9 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -430,7 +430,7 @@ struct intel8x0 { u32 int_sta_mask; /* interrupt status mask */ }; -static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0_ids) = { +static const struct pci_device_id snd_intel8x0_ids[] = { { PCI_VDEVICE(INTEL, 0x2415), DEVICE_INTEL }, /* 82801AA */ { PCI_VDEVICE(INTEL, 0x2425), DEVICE_INTEL }, /* 82901AB */ { PCI_VDEVICE(INTEL, 0x2445), DEVICE_INTEL }, /* 82801BA */ diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index b54d3e93cab1..6b40235be13c 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -219,7 +219,7 @@ struct intel8x0m { unsigned int pcm_pos_shift; }; -static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0m_ids) = { +static const struct pci_device_id snd_intel8x0m_ids[] = { { PCI_VDEVICE(INTEL, 0x2416), DEVICE_INTEL }, /* 82801AA */ { PCI_VDEVICE(INTEL, 0x2426), DEVICE_INTEL }, /* 82901AB */ { PCI_VDEVICE(INTEL, 0x2446), DEVICE_INTEL }, /* 82801BA */ diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 8f36d77f01e5..9fe549b2efdf 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -418,7 +418,7 @@ module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard."); MODULE_AUTHOR("Haroldo Gamal <gamal@alternex.com.br>"); -static DEFINE_PCI_DEVICE_TABLE(snd_korg1212_ids) = { +static const struct pci_device_id snd_korg1212_ids[] = { { .vendor = 0x10b5, .device = 0x906d, diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c index 68824cdd137d..a75c8dc66dec 100644 --- a/sound/pci/lola/lola.c +++ b/sound/pci/lola/lola.c @@ -760,7 +760,7 @@ static void lola_remove(struct pci_dev *pci) } /* PCI IDs */ -static DEFINE_PCI_DEVICE_TABLE(lola_ids) = { +static const struct pci_device_id lola_ids[] = { { PCI_VDEVICE(DIGIGRAM, 0x0001) }, { 0, } }; diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 27f60ce8a55c..a671f0865f71 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c @@ -56,7 +56,7 @@ static const char card_name[] = "LX6464ES"; #define PCI_DEVICE_ID_PLX_LX6464ES PCI_DEVICE_ID_PLX_9056 -static DEFINE_PCI_DEVICE_TABLE(snd_lx6464es_ids) = { +static const struct pci_device_id snd_lx6464es_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES), .subvendor = PCI_VENDOR_ID_DIGIGRAM, .subdevice = PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_SERIAL_SUBSYSTEM diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 0d3ea3e79952..98823d11d485 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -800,7 +800,7 @@ struct snd_m3 { /* * pci ids */ -static DEFINE_PCI_DEVICE_TABLE(snd_m3_ids) = { +static const struct pci_device_id snd_m3_ids[] = { {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID, diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index a93e7af51eed..75fc342cff2a 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -61,7 +61,7 @@ MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard."); /* */ -static DEFINE_PCI_DEVICE_TABLE(snd_mixart_ids) = { +static const struct pci_device_id snd_mixart_ids[] = { { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */ { 0, } }; diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index ddc60215cc10..4e41a4e29a1e 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -262,7 +262,7 @@ struct nm256 { /* * PCI ids */ -static DEFINE_PCI_DEVICE_TABLE(snd_nm256_ids) = { +static const struct pci_device_id snd_nm256_ids[] = { {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO), 0}, {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO), 0}, {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO), 0}, diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index ada6c256378e..74afb6b75976 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c @@ -97,7 +97,7 @@ enum { MODEL_XONAR_DGX, }; -static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = { +static const struct pci_device_id oxygen_ids[] = { /* C-Media's reference design */ { OXYGEN_PCI_SUBID(0x10b0, 0x0216), .driver_data = MODEL_CMEDIA_REF }, { OXYGEN_PCI_SUBID(0x10b0, 0x0217), .driver_data = MODEL_CMEDIA_REF }, diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index dbbbacfd535e..7b317a28a19c 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c @@ -41,7 +41,7 @@ MODULE_PARM_DESC(id, "ID string"); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "enable card"); -static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = { +static const struct pci_device_id xonar_ids[] = { { OXYGEN_PCI_SUBID(0x1043, 0x8269) }, { OXYGEN_PCI_SUBID(0x1043, 0x8275) }, { OXYGEN_PCI_SUBID(0x1043, 0x82b7) }, diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 8d09444ff88b..68a37a7906c1 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -102,7 +102,7 @@ enum { PCI_ID_LAST }; -static DEFINE_PCI_DEVICE_TABLE(pcxhr_ids) = { +static const struct pci_device_id pcxhr_ids[] = { { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, }, { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, }, { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, }, diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index f0315c3f7de4..6abc2ac8fffb 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -508,7 +508,7 @@ static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip); /* */ -static DEFINE_PCI_DEVICE_TABLE(snd_riptide_ids) = { +static const struct pci_device_id snd_riptide_ids[] = { { PCI_DEVICE(0x127a, 0x4310) }, { PCI_DEVICE(0x127a, 0x4320) }, { PCI_DEVICE(0x127a, 0x4330) }, @@ -517,7 +517,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_riptide_ids) = { }; #ifdef SUPPORT_JOYSTICK -static DEFINE_PCI_DEVICE_TABLE(snd_riptide_joystick_ids) = { +static const struct pci_device_id snd_riptide_joystick_ids[] = { { PCI_DEVICE(0x127a, 0x4312) }, { PCI_DEVICE(0x127a, 0x4322) }, { PCI_DEVICE(0x127a, 0x4332) }, diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index cc2f0c1b6484..4afd3cab775b 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -226,7 +226,7 @@ struct rme32 { struct snd_kcontrol *spdif_ctl; }; -static DEFINE_PCI_DEVICE_TABLE(snd_rme32_ids) = { +static const struct pci_device_id snd_rme32_ids[] = { {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32), 0,}, {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8), 0,}, {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO), 0,}, diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 76169929770d..5a395c87c6fc 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -263,7 +263,7 @@ struct rme96 { struct snd_kcontrol *spdif_ctl; }; -static DEFINE_PCI_DEVICE_TABLE(snd_rme96_ids) = { +static const struct pci_device_id snd_rme96_ids[] = { { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96), 0, }, { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8), 0, }, { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO), 0, }, diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 4c6f5d1c9882..7646ba1664eb 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -597,7 +597,7 @@ static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_d } -static DEFINE_PCI_DEVICE_TABLE(snd_hdsp_ids) = { +static const struct pci_device_id snd_hdsp_ids[] = { { .vendor = PCI_VENDOR_ID_XILINX, .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index cb82b593473a..52d86af3ef2d 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1077,7 +1077,7 @@ struct hdspm { }; -static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = { +static const struct pci_device_id snd_hdspm_ids[] = { { .vendor = PCI_VENDOR_ID_XILINX, .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI, diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 1d9be90f7748..fa9a2a8dce5a 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -307,7 +307,7 @@ static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_d } -static DEFINE_PCI_DEVICE_TABLE(snd_rme9652_ids) = { +static const struct pci_device_id snd_rme9652_ids[] = { { .vendor = 0x10ee, .device = 0x3fc4, diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 6b26b93e001d..7f6a0a0d115a 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); module_param(codecs, int, 0444); MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)"); -static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { +static const struct pci_device_id snd_sis7019_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, { 0, } }; diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 2044dc742071..5b0d317cc9a6 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -242,7 +242,7 @@ struct sonicvibes { #endif }; -static DEFINE_PCI_DEVICE_TABLE(snd_sonic_ids) = { +static const struct pci_device_id snd_sonic_ids[] = { { PCI_VDEVICE(S3, 0xca00), 0, }, { 0, } }; diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index d852458caf38..a54cd6879b31 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -62,7 +62,7 @@ MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM."); module_param_array(wavetable_size, int, NULL, 0444); MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth."); -static DEFINE_PCI_DEVICE_TABLE(snd_trident_ids) = { +static const struct pci_device_id snd_trident_ids[] = { {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 95b98f537b67..ecedf4dbfa2a 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -404,7 +404,7 @@ struct via82xx { #endif }; -static DEFINE_PCI_DEVICE_TABLE(snd_via82xx_ids) = { +static const struct pci_device_id snd_via82xx_ids[] = { /* 0x1106, 0x3058 */ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686_5), TYPE_CARD_VIA686, }, /* 686A */ /* 0x1106, 0x3059 */ diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 46a0526b1d79..fd46ffe12e4f 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -260,7 +260,7 @@ struct via82xx_modem { struct snd_info_entry *proc_entry; }; -static DEFINE_PCI_DEVICE_TABLE(snd_via82xx_modem_ids) = { +static const struct pci_device_id snd_via82xx_modem_ids[] = { { PCI_VDEVICE(VIA, 0x3068), TYPE_CARD_VIA82XX_MODEM, }, { 0, } }; diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index ff9074d22607..3dc4732142ee 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -60,7 +60,7 @@ enum { VX_PCI_VX222_NEW }; -static DEFINE_PCI_DEVICE_TABLE(snd_vx222_ids) = { +static const struct pci_device_id snd_vx222_ids[] = { { 0x10b5, 0x9050, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_OLD, }, /* PLX */ { 0x10b5, 0x9030, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_NEW, }, /* PLX */ { 0, } diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 82eed164b275..47a192369e8f 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -66,7 +66,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address"); module_param_array(rear_switch, bool, NULL, 0444); MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); -static DEFINE_PCI_DEVICE_TABLE(snd_ymfpci_ids) = { +static const struct pci_device_id snd_ymfpci_ids[] = { { PCI_VDEVICE(YAMAHA, 0x0004), 0, }, /* YMF724 */ { PCI_VDEVICE(YAMAHA, 0x000d), 0, }, /* YMF724F */ { PCI_VDEVICE(YAMAHA, 0x000a), 0, }, /* YMF740 */ diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index f652b10ce905..223c47b33ba3 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -1581,6 +1581,35 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* BOSS ME-25 */ + USB_DEVICE(0x0582, 0x0113), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } +}, +{ /* only 44.1 kHz works at the moment */ USB_DEVICE(0x0582, 0x0120), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index d0396af99fa0..5b1b807265a1 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -267,90 +267,90 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) /* * Example Format w/ field column widths: * - * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz SMI %Busy CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt - * 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 + * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz SMI %Busy CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt + * 123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678 */ void print_header(void) { if (show_pkg) - outp += sprintf(outp, "Package "); + outp += sprintf(outp, " Package"); if (show_core) - outp += sprintf(outp, " Core "); + outp += sprintf(outp, " Core"); if (show_cpu) - outp += sprintf(outp, " CPU "); + outp += sprintf(outp, " CPU"); if (has_aperf) - outp += sprintf(outp, "Avg_MHz "); + outp += sprintf(outp, " Avg_MHz"); if (do_nhm_cstates) - outp += sprintf(outp, " %%Busy "); + outp += sprintf(outp, " %%Busy"); if (has_aperf) - outp += sprintf(outp, "Bzy_MHz "); - outp += sprintf(outp, "TSC_MHz "); + outp += sprintf(outp, " Bzy_MHz"); + outp += sprintf(outp, " TSC_MHz"); if (do_smi) - outp += sprintf(outp, " SMI "); + outp += sprintf(outp, " SMI"); if (extra_delta_offset32) - outp += sprintf(outp, " count 0x%03X ", extra_delta_offset32); + outp += sprintf(outp, " count 0x%03X", extra_delta_offset32); if (extra_delta_offset64) - outp += sprintf(outp, " COUNT 0x%03X ", extra_delta_offset64); + outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64); if (extra_msr_offset32) - outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset32); + outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32); if (extra_msr_offset64) - outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset64); + outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64); if (do_nhm_cstates) - outp += sprintf(outp, " CPU%%c1 "); + outp += sprintf(outp, " CPU%%c1"); if (do_nhm_cstates && !do_slm_cstates) - outp += sprintf(outp, " CPU%%c3 "); + outp += sprintf(outp, " CPU%%c3"); if (do_nhm_cstates) - outp += sprintf(outp, " CPU%%c6 "); + outp += sprintf(outp, " CPU%%c6"); if (do_snb_cstates) - outp += sprintf(outp, " CPU%%c7 "); + outp += sprintf(outp, " CPU%%c7"); if (do_dts) - outp += sprintf(outp, "CoreTmp "); + outp += sprintf(outp, " CoreTmp"); if (do_ptm) - outp += sprintf(outp, " PkgTmp "); + outp += sprintf(outp, " PkgTmp"); if (do_snb_cstates) - outp += sprintf(outp, "Pkg%%pc2 "); + outp += sprintf(outp, " Pkg%%pc2"); if (do_nhm_cstates && !do_slm_cstates) - outp += sprintf(outp, "Pkg%%pc3 "); + outp += sprintf(outp, " Pkg%%pc3"); if (do_nhm_cstates && !do_slm_cstates) - outp += sprintf(outp, "Pkg%%pc6 "); + outp += sprintf(outp, " Pkg%%pc6"); if (do_snb_cstates) - outp += sprintf(outp, "Pkg%%pc7 "); + outp += sprintf(outp, " Pkg%%pc7"); if (do_c8_c9_c10) { - outp += sprintf(outp, "Pkg%%pc8 "); - outp += sprintf(outp, "Pkg%%pc9 "); - outp += sprintf(outp, "Pk%%pc10 "); + outp += sprintf(outp, " Pkg%%pc8"); + outp += sprintf(outp, " Pkg%%pc9"); + outp += sprintf(outp, " Pk%%pc10"); } if (do_rapl && !rapl_joules) { if (do_rapl & RAPL_PKG) - outp += sprintf(outp, "PkgWatt "); + outp += sprintf(outp, " PkgWatt"); if (do_rapl & RAPL_CORES) - outp += sprintf(outp, "CorWatt "); + outp += sprintf(outp, " CorWatt"); if (do_rapl & RAPL_GFX) - outp += sprintf(outp, "GFXWatt "); + outp += sprintf(outp, " GFXWatt"); if (do_rapl & RAPL_DRAM) - outp += sprintf(outp, "RAMWatt "); + outp += sprintf(outp, " RAMWatt"); if (do_rapl & RAPL_PKG_PERF_STATUS) - outp += sprintf(outp, " PKG_%% "); + outp += sprintf(outp, " PKG_%%"); if (do_rapl & RAPL_DRAM_PERF_STATUS) - outp += sprintf(outp, " RAM_%% "); + outp += sprintf(outp, " RAM_%%"); } else { if (do_rapl & RAPL_PKG) - outp += sprintf(outp, " Pkg_J "); + outp += sprintf(outp, " Pkg_J"); if (do_rapl & RAPL_CORES) - outp += sprintf(outp, " Cor_J "); + outp += sprintf(outp, " Cor_J"); if (do_rapl & RAPL_GFX) - outp += sprintf(outp, " GFX_J "); + outp += sprintf(outp, " GFX_J"); if (do_rapl & RAPL_DRAM) - outp += sprintf(outp, " RAM_W "); + outp += sprintf(outp, " RAM_W"); if (do_rapl & RAPL_PKG_PERF_STATUS) - outp += sprintf(outp, " PKG_%% "); + outp += sprintf(outp, " PKG_%%"); if (do_rapl & RAPL_DRAM_PERF_STATUS) - outp += sprintf(outp, " RAM_%% "); - outp += sprintf(outp, " time "); + outp += sprintf(outp, " RAM_%%"); + outp += sprintf(outp, " time"); } outp += sprintf(outp, "\n"); |