Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Nov 2018 16:31:19 +0000 (09:31 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Nov 2018 16:31:19 +0000 (09:31 -0700)
Pull i2c fixes from Wolfram Sang:
 "I2C has a core bugfix & cleanup as well as an ID addition and
  MAINTAINERS update for you"

* 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  MAINTAINERS: add maintainer for IMX LPI2C driver
  dt-bindings: i2c: i2c-imx-lpi2c: add imx8qxp compatible string
  i2c: Clear client->irq in i2c_device_remove
  i2c: Remove unnecessary call to irq_find_mapping

132 files changed:
Documentation/ABI/testing/sysfs-platform-lg-laptop [new file with mode: 0644]
Documentation/laptops/lg-laptop.rst [new file with mode: 0644]
Documentation/networking/ip-sysctl.txt
MAINTAINERS
arch/arm64/include/asm/percpu.h
arch/csky/Kconfig.debug
arch/csky/Makefile
arch/csky/boot/dts/Makefile
arch/riscv/Kconfig
arch/riscv/include/asm/elf.h
arch/riscv/kernel/cpufeature.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/systbls_64.S
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/dcdbas.c [deleted file]
drivers/firmware/dcdbas.h [deleted file]
drivers/firmware/dell_rbu.c [deleted file]
drivers/hid/Kconfig
drivers/hid/hid-asus.c
drivers/mfd/cros_ec_dev.h
drivers/net/bonding/bond_netlink.c
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/fm10k/fm10k_iov.c
drivers/net/ethernet/intel/fm10k/fm10k_main.c
drivers/net/ethernet/intel/fm10k/fm10k_pci.c
drivers/net/ethernet/intel/fm10k/fm10k_type.h
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/igb/igb_ptp.c
drivers/net/ethernet/intel/ixgbe/Makefile
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/intel/ixgbevf/Makefile
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/marvell/mvpp2/mvpp2.h
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
drivers/platform/chrome/chromeos_tbmc.c
drivers/platform/chrome/cros_ec_lpc.c
drivers/platform/chrome/cros_ec_lpc_mec.c
drivers/platform/chrome/cros_ec_lpc_mec.h [new file with mode: 0644]
drivers/platform/chrome/cros_ec_lpc_reg.c
drivers/platform/chrome/cros_ec_lpc_reg.h [new file with mode: 0644]
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acerhdf.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/dcdbas.c [new file with mode: 0644]
drivers/platform/x86/dcdbas.h [new file with mode: 0644]
drivers/platform/x86/dell-smbios-smm.c
drivers/platform/x86/dell_rbu.c [new file with mode: 0644]
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel-hid.c
drivers/platform/x86/intel-rst.c
drivers/platform/x86/intel-smartconnect.c
drivers/platform/x86/intel-wmi-thunderbolt.c
drivers/platform/x86/intel_atomisp2_pm.c [new file with mode: 0644]
drivers/platform/x86/intel_bxtwc_tmu.c
drivers/platform/x86/intel_cht_int33fe.c
drivers/platform/x86/intel_chtdc_ti_pwrbtn.c
drivers/platform/x86/intel_int0002_vgpio.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_ips.h
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/intel_mid_powerbtn.c
drivers/platform/x86/intel_mid_thermal.c
drivers/platform/x86/intel_oaktrail.c
drivers/platform/x86/intel_pmc_core.c
drivers/platform/x86/intel_pmc_core.h
drivers/platform/x86/intel_pmc_ipc.c
drivers/platform/x86/intel_punit_ipc.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/intel_scu_ipcutil.c
drivers/platform/x86/intel_telemetry_core.c
drivers/platform/x86/intel_telemetry_debugfs.c
drivers/platform/x86/intel_telemetry_pltdrv.c
drivers/platform/x86/intel_turbo_max_3.c
drivers/platform/x86/lg-laptop.c [new file with mode: 0644]
drivers/platform/x86/mlx-platform.c
drivers/platform/x86/touchscreen_dmi.c
drivers/platform/x86/wmi.c
drivers/vhost/vhost.c
include/linux/avf/virtchnl.h
include/linux/bpf_verifier.h
include/linux/inetdevice.h
include/linux/mfd/cros_ec.h
include/linux/mfd/cros_ec_commands.h
include/linux/mfd/cros_ec_lpc_mec.h [deleted file]
include/linux/mfd/cros_ec_lpc_reg.h [deleted file]
include/linux/platform_data/x86/asus-wmi.h [new file with mode: 0644]
include/net/af_unix.h
include/uapi/linux/elf-em.h
kernel/bpf/verifier.c
kernel/trace/trace_printk.c
lib/Kconfig
lib/Makefile
lib/udivmoddi4.c [deleted file]
lib/umoddi3.c [deleted file]
mm/percpu.c
net/core/rtnetlink.c
net/ipv4/igmp.c
net/ipv4/tcp_bpf.c
net/openvswitch/flow_netlink.c
net/sctp/associola.c
net/sctp/socket.c
net/xfrm/Kconfig
tools/lib/bpf/libbpf.c
tools/testing/selftests/bpf/flow_dissector_load.c
tools/testing/selftests/bpf/test_skb_cgroup_id.sh
tools/testing/selftests/bpf/test_sock_addr.sh
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh

diff --git a/Documentation/ABI/testing/sysfs-platform-lg-laptop b/Documentation/ABI/testing/sysfs-platform-lg-laptop
new file mode 100644 (file)
index 0000000..cf47749
--- /dev/null
@@ -0,0 +1,35 @@
+What:          /sys/devices/platform/lg-laptop/reader_mode
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Control reader mode. 1 means on, 0 means off.
+
+What:          /sys/devices/platform/lg-laptop/fn_lock
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Control FN lock mode. 1 means on, 0 means off.
+
+What:          /sys/devices/platform/lg-laptop/battery_care_limit
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Maximal battery charge level. Accepted values are 80 or 100.
+
+What:          /sys/devices/platform/lg-laptop/fan_mode
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Control fan mode. 1 for performance mode, 0 for silent mode.
+
+What:          /sys/devices/platform/lg-laptop/usb_charge
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Control USB port charging when device is turned off.
+        1 means on, 0 means off.
diff --git a/Documentation/laptops/lg-laptop.rst b/Documentation/laptops/lg-laptop.rst
new file mode 100644 (file)
index 0000000..e486fe7
--- /dev/null
@@ -0,0 +1,81 @@
+.. SPDX-License-Identifier: GPL-2.0+
+LG Gram laptop extra features
+=============================
+
+By Matan Ziv-Av <matan@svgalib.org>
+
+
+Hotkeys
+-------
+
+The following FN keys are ignored by the kernel without this driver:
+- FN-F1 (LG control panel)   - Generates F15
+- FN-F5 (Touchpad toggle)    - Generates F13
+- FN-F6 (Airplane mode)      - Generates RFKILL
+- FN-F8 (Keyboard backlight) - Generates F16.
+  This key also changes keyboard backlight mode.
+- FN-F9 (Reader mode)        - Generates F14
+
+The rest of the FN key work without a need for a special driver.
+
+
+Reader mode
+-----------
+
+Writing 0/1 to /sys/devices/platform/lg-laptop/reader_mode disables/enables
+reader mode. In this mode the screen colors change (blue color reduced),
+and the reader mode indicator LED (on F9 key) turns on.
+
+
+FN Lock
+-------
+
+Writing 0/1 to /sys/devices/platform/lg-laptop/fn_lock disables/enables
+FN lock.
+
+
+Battery care limit
+------------------
+
+Writing 80/100 to /sys/devices/platform/lg-laptop/battery_care_limit
+sets the maximum capacity to charge the battery. Limiting the charge
+reduces battery capacity loss over time.
+
+This value is reset to 100 when the kernel boots.
+
+
+Fan mode
+--------
+
+Writing 1/0 to /sys/devices/platform/lg-laptop/fan_mode disables/enables
+the fan silent mode.
+
+
+USB charge
+----------
+
+Writing 0/1 to /sys/devices/platform/lg-laptop/usb_charge disables/enables
+charging another device from the USB port while the device is turned off.
+
+This value is reset to 0 when the kernel boots.
+
+
+LEDs
+~~~~
+
+The are two LED devices supported by the driver:
+
+Keyboard backlight
+------------------
+
+A led device named kbd_led controls the keyboard backlight. There are three
+lighting level: off (0), low (127) and high (255).
+
+The keyboard backlight is also controlled by the key combination FN-F8
+which cycles through those levels.
+
+
+Touchpad indicator LED
+----------------------
+
+On the F5 key. Controlled by led device names tpad_led.
index 163b5ff1073cd0a852d9ed32e06c599cefcfdd75..32b21571adfeb5bc4b5aec9b25ec14ecebc8e0e5 100644 (file)
@@ -316,6 +316,17 @@ tcp_frto - INTEGER
 
        By default it's enabled with a non-zero value. 0 disables F-RTO.
 
+tcp_fwmark_accept - BOOLEAN
+       If set, incoming connections to listening sockets that do not have a
+       socket mark will set the mark of the accepting socket to the fwmark of
+       the incoming SYN packet. This will cause all packets on that connection
+       (starting from the first SYNACK) to be sent with that fwmark. The
+       listening socket's mark is unchanged. Listening sockets that already
+       have a fwmark set via setsockopt(SOL_SOCKET, SO_MARK, ...) are
+       unaffected.
+
+       Default: 0
+
 tcp_invalid_ratelimit - INTEGER
        Limit the maximal rate for sending duplicate acknowledgments
        in response to incoming TCP packets that are for an existing
index 5d581e0dd01780720e88d347284248552a61e3bf..690c2f68a401fd9e7eab286be7f733b25b551965 100644 (file)
@@ -376,7 +376,7 @@ F:  drivers/platform/x86/i2c-multi-instantiate.c
 ACPI PMIC DRIVERS
 M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 M:     Len Brown <lenb@kernel.org>
-R:     Andy Shevchenko <andy@infradead.org>
+R:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 R:     Mika Westerberg <mika.westerberg@linux.intel.com>
 L:     linux-acpi@vger.kernel.org
 Q:     https://patchwork.kernel.org/project/linux-acpi/list/
@@ -4207,6 +4207,12 @@ M:       Pali Rohár <pali.rohar@gmail.com>
 S:     Maintained
 F:     drivers/platform/x86/dell-rbtn.*
 
+DELL REMOTE BIOS UPDATE DRIVER
+M:     Stuart Hayes <stuart.w.hayes@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/dell_rbu.c
+
 DELL LAPTOP SMM DRIVER
 M:     Pali Rohár <pali.rohar@gmail.com>
 S:     Maintained
@@ -4214,10 +4220,11 @@ F:      drivers/hwmon/dell-smm-hwmon.c
 F:     include/uapi/linux/i8k.h
 
 DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
-M:     Doug Warzecha <Douglas_Warzecha@dell.com>
+M:     Stuart Hayes <stuart.w.hayes@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     Documentation/dcdbas.txt
-F:     drivers/firmware/dcdbas.*
+F:     drivers/platform/x86/dcdbas.*
 
 DELL WMI NOTIFICATIONS DRIVER
 M:     Matthew Garrett <mjg59@srcf.ucam.org>
@@ -7355,6 +7362,12 @@ L:       alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 F:     sound/soc/intel/
 
+INTEL ATOMISP2 DUMMY / POWER-MANAGEMENT DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/intel_atomisp2_pm.c
+
 INTEL C600 SERIES SAS CONTROLLER DRIVER
 M:     Intel SCU Linux support <intel-linux-scu@intel.com>
 M:     Artur Paszkiewicz <artur.paszkiewicz@intel.com>
@@ -7541,7 +7554,6 @@ M:        Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>
 M:     Vishwanath Somayaji <vishwanath.somayaji@intel.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
-F:     arch/x86/include/asm/pmc_core.h
 F:     drivers/platform/x86/intel_pmc_core*
 
 INTEL PMC/P-Unit IPC DRIVER
@@ -7585,7 +7597,8 @@ F:        drivers/infiniband/hw/i40iw/
 F:     include/uapi/rdma/i40iw-abi.h
 
 INTEL TELEMETRY DRIVER
-M:     Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>
+M:     Rajneesh Bhardwaj <rajneesh.bhardwaj@linux.intel.com>
+M:     "David E. Box" <david.e.box@linux.intel.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     arch/x86/include/asm/intel_telemetry.h
@@ -8318,6 +8331,14 @@ W:       http://legousb.sourceforge.net/
 S:     Maintained
 F:     drivers/usb/misc/legousbtower.c
 
+LG LAPTOP EXTRAS
+M:     Matan Ziv-Av <matan@svgalib.org>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     Documentation/ABI/testing/sysfs-platform-lg-laptop
+F:     Documentation/laptops/lg-laptop.rst
+F:     drivers/platform/x86/lg-laptop.c
+
 LG2160 MEDIA DRIVER
 M:     Michael Krufky <mkrufky@linuxtv.org>
 L:     linux-media@vger.kernel.org
index 9234013e759e56a9ebd5c326cab49bd7c66df323..21a81b59a0ccd5419be92ec6e661a3e05e5820ff 100644 (file)
@@ -96,6 +96,7 @@ static inline unsigned long __percpu_##op(void *ptr,                  \
                : [val] "Ir" (val));                                    \
                break;                                                  \
        default:                                                        \
+               ret = 0;                                                \
                BUILD_BUG();                                            \
        }                                                               \
                                                                        \
@@ -125,6 +126,7 @@ static inline unsigned long __percpu_read(void *ptr, int size)
                ret = READ_ONCE(*(u64 *)ptr);
                break;
        default:
+               ret = 0;
                BUILD_BUG();
        }
 
@@ -194,6 +196,7 @@ static inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
                : [val] "r" (val));
                break;
        default:
+               ret = 0;
                BUILD_BUG();
        }
 
index 48cf6ff9df4a36885db042048ce2aa8761c58a58..22a162cd99e8112b37681afd8934c3c3eb490f99 100644 (file)
@@ -1,9 +1 @@
-menu "C-SKY Debug Options"
-config CSKY_BUILTIN_DTB
-       string "Use kernel builtin dtb"
-       help
-         User could define the dtb instead of the one which is passed from
-         bootloader.
-         Sometimes for debug, we want to use a built-in dtb and then we needn't
-         modify bootloader at all.
-endmenu
+# dummy file, do not delete
index 67a4ae1fba2ba4601f689404e52d5ec3dd901ce1..c639fc167895d7a2f00909bf079e5ea2e6b0558c 100644 (file)
@@ -65,26 +65,15 @@ libs-y += arch/csky/lib/ \
        $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
 
 boot := arch/csky/boot
-ifneq '$(CONFIG_CSKY_BUILTIN_DTB)' '""'
 core-y += $(boot)/dts/
-endif
 
 all: zImage
 
-
-dtbs: scripts
-       $(Q)$(MAKE) $(build)=$(boot)/dts
-
-%.dtb %.dtb.S %.dtb.o: scripts
-       $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
-
-zImage Image uImage: vmlinux dtbs
+zImage Image uImage: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
-       $(Q)$(MAKE) $(clean)=$(boot)/dts
-       rm -rf arch/csky/include/generated
 
 define archhelp
   echo  '* zImage       - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
index 305e81a5e91e1e5a0d622f2f399e3511fe61ca07..c57ad3c880bfb933c227fa32141b57b938be3706 100644 (file)
@@ -1,13 +1,3 @@
 dtstree        := $(srctree)/$(src)
 
-ifneq '$(CONFIG_CSKY_BUILTIN_DTB)' '""'
-builtindtb-y := $(patsubst "%",%,$(CONFIG_CSKY_BUILTIN_DTB))
-dtb-y += $(builtindtb-y).dtb
-obj-y += $(builtindtb-y).dtb.o
-.SECONDARY: $(obj)/$(builtindtb-y).dtb.S
-else
 dtb-y := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
-endif
-
-always += $(dtb-y)
-clean-files += *.dtb *.dtb.S
index d86842c217103fff945d34a11a14b0f0513eaf90..55da93f4e818e22ff1918aa625a56dde5bc56019 100644 (file)
@@ -107,7 +107,6 @@ config ARCH_RV32I
        select GENERIC_LIB_ASHRDI3
        select GENERIC_LIB_LSHRDI3
        select GENERIC_LIB_UCMPDI2
-       select GENERIC_LIB_UMODDI3
 
 config ARCH_RV64I
        bool "RV64I"
index a1ef503d616ed05760fcb324e579bb71e842d6bc..697fc23b0d5ae4f6d6cd508e8d0a2804c277e0ee 100644 (file)
@@ -16,9 +16,6 @@
 #include <asm/auxvec.h>
 #include <asm/byteorder.h>
 
-/* TODO: Move definition into include/uapi/linux/elf-em.h */
-#define EM_RISCV       0xF3
-
 /*
  * These are used to set parameters in the core dumps.
  */
index 5493f3228704740e913e0d5883d1cca99ba7f645..0339087aa6520dba2790e6d31caa5d4f089c75b6 100644 (file)
@@ -28,7 +28,7 @@ bool has_fpu __read_mostly;
 
 void riscv_fill_hwcap(void)
 {
-       struct device_node *node;
+       struct device_node *node = NULL;
        const char *isa;
        size_t i;
        static unsigned long isa2hwcap[256] = {0};
@@ -44,9 +44,11 @@ void riscv_fill_hwcap(void)
 
        /*
         * We don't support running Linux on hertergenous ISA systems.  For
-        * now, we just check the ISA of the first processor.
+        * now, we just check the ISA of the first "okay" processor.
         */
-       node = of_find_node_by_type(NULL, "cpu");
+       while ((node = of_find_node_by_type(node, "cpu")))
+               if (riscv_of_processor_hartid(node) >= 0)
+                       break;
        if (!node) {
                pr_warning("Unable to find \"cpu\" devicetree entry");
                return;
index 67b3e6b3ce5d7cf8b417d361c5bbaadce92cc1e0..47c871394ccb1602d59bca5a3459a7e088df98e0 100644 (file)
@@ -1849,16 +1849,12 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
 {
        u64 saved_fault_address = current_thread_info()->fault_address;
        u8 saved_fault_code = get_thread_fault_code();
-       mm_segment_t old_fs;
 
        perf_callchain_store(entry, regs->tpc);
 
        if (!current->mm)
                return;
 
-       old_fs = get_fs();
-       set_fs(USER_DS);
-
        flushw_user();
 
        pagefault_disable();
@@ -1870,7 +1866,6 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
 
        pagefault_enable();
 
-       set_fs(old_fs);
        set_thread_fault_code(saved_fault_code);
        current_thread_info()->fault_address = saved_fault_address;
 }
index bb68c805b891855e18af6397ce534f74d5550a4d..ff9389a1c9f3f68c5acaa32123d65c5fedbf9846 100644 (file)
@@ -47,9 +47,9 @@ sys_call_table32:
        .word sys_recvfrom, sys_setreuid16, sys_setregid16, sys_rename, compat_sys_truncate
 /*130*/        .word compat_sys_ftruncate, sys_flock, compat_sys_lstat64, sys_sendto, sys_shutdown
        .word sys_socketpair, sys_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
-/*140*/        .word sys_sendfile64, sys_nis_syscall, compat_sys_futex, sys_gettid, compat_sys_getrlimit
+/*140*/        .word sys_sendfile64, sys_getpeername, compat_sys_futex, sys_gettid, compat_sys_getrlimit
        .word compat_sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
-/*150*/        .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
+/*150*/        .word sys_getsockname, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
        .word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount
 /*160*/        .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
        .word sys_quotactl, sys_set_tid_address, compat_sys_mount, compat_sys_ustat, sys_setxattr
index 7670e8dda82951312feee7eca53f7499129c911a..7273e5082b4175be3601e28775506ce8b5ee89d9 100644 (file)
@@ -145,34 +145,6 @@ config EFI_PCDP
          See DIG64_HCDPv20_042804.pdf available from
          <http://www.dig64.org/specifications/> 
 
-config DELL_RBU
-       tristate "BIOS update support for DELL systems via sysfs"
-       depends on X86
-       select FW_LOADER
-       select FW_LOADER_USER_HELPER
-       help
-        Say m if you want to have the option of updating the BIOS for your
-        DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
-        supporting application to communicate with the BIOS regarding the new
-        image for the image update to take effect.
-        See <file:Documentation/dell_rbu.txt> for more details on the driver.
-
-config DCDBAS
-       tristate "Dell Systems Management Base Driver"
-       depends on X86
-       help
-         The Dell Systems Management Base Driver provides a sysfs interface
-         for systems management software to perform System Management
-         Interrupts (SMIs) and Host Control Actions (system power cycle or
-         power off after OS shutdown) on certain Dell systems.
-
-         See <file:Documentation/dcdbas.txt> for more details on the driver
-         and the Dell systems on which Dell systems management software makes
-         use of this driver.
-
-         Say Y or M here to enable the driver for use by Dell systems
-         management software such as Dell OpenManage.
-
 config DMIID
     bool "Export DMI identification via sysfs to userspace"
     depends on DMI
index 13660a9514379e7534af0f56c6e084f68b2ef02c..3158dffd9914e6afd44a51caf7acfd688c8984b3 100644 (file)
@@ -11,8 +11,6 @@ obj-$(CONFIG_DMI)             += dmi_scan.o
 obj-$(CONFIG_DMI_SYSFS)                += dmi-sysfs.o
 obj-$(CONFIG_EDD)              += edd.o
 obj-$(CONFIG_EFI_PCDP)         += pcdp.o
-obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
-obj-$(CONFIG_DCDBAS)           += dcdbas.o
 obj-$(CONFIG_DMIID)            += dmi-id.o
 obj-$(CONFIG_ISCSI_IBFT_FIND)  += iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)       += iscsi_ibft.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
deleted file mode 100644 (file)
index 0bdea60..0000000
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- *  dcdbas.c: Dell Systems Management Base Driver
- *
- *  The Dell Systems Management Base Driver provides a sysfs interface for
- *  systems management software to perform System Management Interrupts (SMIs)
- *  and Host Control Actions (power cycle or power off after OS shutdown) on
- *  Dell systems.
- *
- *  See Documentation/dcdbas.txt for more information.
- *
- *  Copyright (C) 1995-2006 Dell Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License v2.0 as published by
- *  the Free Software Foundation.
- *
- *  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.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/cpu.h>
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/mc146818rtc.h>
-#include <linux/module.h>
-#include <linux/reboot.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/mutex.h>
-#include <asm/io.h>
-
-#include "dcdbas.h"
-
-#define DRIVER_NAME            "dcdbas"
-#define DRIVER_VERSION         "5.6.0-3.2"
-#define DRIVER_DESCRIPTION     "Dell Systems Management Base Driver"
-
-static struct platform_device *dcdbas_pdev;
-
-static u8 *smi_data_buf;
-static dma_addr_t smi_data_buf_handle;
-static unsigned long smi_data_buf_size;
-static u32 smi_data_buf_phys_addr;
-static DEFINE_MUTEX(smi_data_lock);
-
-static unsigned int host_control_action;
-static unsigned int host_control_smi_type;
-static unsigned int host_control_on_shutdown;
-
-/**
- * smi_data_buf_free: free SMI data buffer
- */
-static void smi_data_buf_free(void)
-{
-       if (!smi_data_buf)
-               return;
-
-       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
-               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
-
-       dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
-                         smi_data_buf_handle);
-       smi_data_buf = NULL;
-       smi_data_buf_handle = 0;
-       smi_data_buf_phys_addr = 0;
-       smi_data_buf_size = 0;
-}
-
-/**
- * smi_data_buf_realloc: grow SMI data buffer if needed
- */
-static int smi_data_buf_realloc(unsigned long size)
-{
-       void *buf;
-       dma_addr_t handle;
-
-       if (smi_data_buf_size >= size)
-               return 0;
-
-       if (size > MAX_SMI_DATA_BUF_SIZE)
-               return -EINVAL;
-
-       /* new buffer is needed */
-       buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL);
-       if (!buf) {
-               dev_dbg(&dcdbas_pdev->dev,
-                       "%s: failed to allocate memory size %lu\n",
-                       __func__, size);
-               return -ENOMEM;
-       }
-       /* memory zeroed by dma_alloc_coherent */
-
-       if (smi_data_buf)
-               memcpy(buf, smi_data_buf, smi_data_buf_size);
-
-       /* free any existing buffer */
-       smi_data_buf_free();
-
-       /* set up new buffer for use */
-       smi_data_buf = buf;
-       smi_data_buf_handle = handle;
-       smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
-       smi_data_buf_size = size;
-
-       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
-               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
-
-       return 0;
-}
-
-static ssize_t smi_data_buf_phys_addr_show(struct device *dev,
-                                          struct device_attribute *attr,
-                                          char *buf)
-{
-       return sprintf(buf, "%x\n", smi_data_buf_phys_addr);
-}
-
-static ssize_t smi_data_buf_size_show(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
-{
-       return sprintf(buf, "%lu\n", smi_data_buf_size);
-}
-
-static ssize_t smi_data_buf_size_store(struct device *dev,
-                                      struct device_attribute *attr,
-                                      const char *buf, size_t count)
-{
-       unsigned long buf_size;
-       ssize_t ret;
-
-       buf_size = simple_strtoul(buf, NULL, 10);
-
-       /* make sure SMI data buffer is at least buf_size */
-       mutex_lock(&smi_data_lock);
-       ret = smi_data_buf_realloc(buf_size);
-       mutex_unlock(&smi_data_lock);
-       if (ret)
-               return ret;
-
-       return count;
-}
-
-static ssize_t smi_data_read(struct file *filp, struct kobject *kobj,
-                            struct bin_attribute *bin_attr,
-                            char *buf, loff_t pos, size_t count)
-{
-       ssize_t ret;
-
-       mutex_lock(&smi_data_lock);
-       ret = memory_read_from_buffer(buf, count, &pos, smi_data_buf,
-                                       smi_data_buf_size);
-       mutex_unlock(&smi_data_lock);
-       return ret;
-}
-
-static ssize_t smi_data_write(struct file *filp, struct kobject *kobj,
-                             struct bin_attribute *bin_attr,
-                             char *buf, loff_t pos, size_t count)
-{
-       ssize_t ret;
-
-       if ((pos + count) > MAX_SMI_DATA_BUF_SIZE)
-               return -EINVAL;
-
-       mutex_lock(&smi_data_lock);
-
-       ret = smi_data_buf_realloc(pos + count);
-       if (ret)
-               goto out;
-
-       memcpy(smi_data_buf + pos, buf, count);
-       ret = count;
-out:
-       mutex_unlock(&smi_data_lock);
-       return ret;
-}
-
-static ssize_t host_control_action_show(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
-{
-       return sprintf(buf, "%u\n", host_control_action);
-}
-
-static ssize_t host_control_action_store(struct device *dev,
-                                        struct device_attribute *attr,
-                                        const char *buf, size_t count)
-{
-       ssize_t ret;
-
-       /* make sure buffer is available for host control command */
-       mutex_lock(&smi_data_lock);
-       ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
-       mutex_unlock(&smi_data_lock);
-       if (ret)
-               return ret;
-
-       host_control_action = simple_strtoul(buf, NULL, 10);
-       return count;
-}
-
-static ssize_t host_control_smi_type_show(struct device *dev,
-                                         struct device_attribute *attr,
-                                         char *buf)
-{
-       return sprintf(buf, "%u\n", host_control_smi_type);
-}
-
-static ssize_t host_control_smi_type_store(struct device *dev,
-                                          struct device_attribute *attr,
-                                          const char *buf, size_t count)
-{
-       host_control_smi_type = simple_strtoul(buf, NULL, 10);
-       return count;
-}
-
-static ssize_t host_control_on_shutdown_show(struct device *dev,
-                                            struct device_attribute *attr,
-                                            char *buf)
-{
-       return sprintf(buf, "%u\n", host_control_on_shutdown);
-}
-
-static ssize_t host_control_on_shutdown_store(struct device *dev,
-                                             struct device_attribute *attr,
-                                             const char *buf, size_t count)
-{
-       host_control_on_shutdown = simple_strtoul(buf, NULL, 10);
-       return count;
-}
-
-static int raise_smi(void *par)
-{
-       struct smi_cmd *smi_cmd = par;
-
-       if (smp_processor_id() != 0) {
-               dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
-                       __func__);
-               return -EBUSY;
-       }
-
-       /* generate SMI */
-       /* inb to force posted write through and make SMI happen now */
-       asm volatile (
-               "outb %b0,%w1\n"
-               "inb %w1"
-               : /* no output args */
-               : "a" (smi_cmd->command_code),
-                 "d" (smi_cmd->command_address),
-                 "b" (smi_cmd->ebx),
-                 "c" (smi_cmd->ecx)
-               : "memory"
-       );
-
-       return 0;
-}
-/**
- * dcdbas_smi_request: generate SMI request
- *
- * Called with smi_data_lock.
- */
-int dcdbas_smi_request(struct smi_cmd *smi_cmd)
-{
-       int ret;
-
-       if (smi_cmd->magic != SMI_CMD_MAGIC) {
-               dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
-                        __func__);
-               return -EBADR;
-       }
-
-       /* SMI requires CPU 0 */
-       get_online_cpus();
-       ret = smp_call_on_cpu(0, raise_smi, smi_cmd, true);
-       put_online_cpus();
-
-       return ret;
-}
-
-/**
- * smi_request_store:
- *
- * The valid values are:
- * 0: zero SMI data buffer
- * 1: generate calling interface SMI
- * 2: generate raw SMI
- *
- * User application writes smi_cmd to smi_data before telling driver
- * to generate SMI.
- */
-static ssize_t smi_request_store(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct smi_cmd *smi_cmd;
-       unsigned long val = simple_strtoul(buf, NULL, 10);
-       ssize_t ret;
-
-       mutex_lock(&smi_data_lock);
-
-       if (smi_data_buf_size < sizeof(struct smi_cmd)) {
-               ret = -ENODEV;
-               goto out;
-       }
-       smi_cmd = (struct smi_cmd *)smi_data_buf;
-
-       switch (val) {
-       case 2:
-               /* Raw SMI */
-               ret = dcdbas_smi_request(smi_cmd);
-               if (!ret)
-                       ret = count;
-               break;
-       case 1:
-               /* Calling Interface SMI */
-               smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer);
-               ret = dcdbas_smi_request(smi_cmd);
-               if (!ret)
-                       ret = count;
-               break;
-       case 0:
-               memset(smi_data_buf, 0, smi_data_buf_size);
-               ret = count;
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-
-out:
-       mutex_unlock(&smi_data_lock);
-       return ret;
-}
-EXPORT_SYMBOL(dcdbas_smi_request);
-
-/**
- * host_control_smi: generate host control SMI
- *
- * Caller must set up the host control command in smi_data_buf.
- */
-static int host_control_smi(void)
-{
-       struct apm_cmd *apm_cmd;
-       u8 *data;
-       unsigned long flags;
-       u32 num_ticks;
-       s8 cmd_status;
-       u8 index;
-
-       apm_cmd = (struct apm_cmd *)smi_data_buf;
-       apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;
-
-       switch (host_control_smi_type) {
-       case HC_SMITYPE_TYPE1:
-               spin_lock_irqsave(&rtc_lock, flags);
-               /* write SMI data buffer physical address */
-               data = (u8 *)&smi_data_buf_phys_addr;
-               for (index = PE1300_CMOS_CMD_STRUCT_PTR;
-                    index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
-                    index++, data++) {
-                       outb(index,
-                            (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
-                       outb(*data,
-                            (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
-               }
-
-               /* first set status to -1 as called by spec */
-               cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
-               outb((u8) cmd_status, PCAT_APM_STATUS_PORT);
-
-               /* generate SMM call */
-               outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
-               spin_unlock_irqrestore(&rtc_lock, flags);
-
-               /* wait a few to see if it executed */
-               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
-               while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
-                      == ESM_STATUS_CMD_UNSUCCESSFUL) {
-                       num_ticks--;
-                       if (num_ticks == EXPIRED_TIMER)
-                               return -ETIME;
-               }
-               break;
-
-       case HC_SMITYPE_TYPE2:
-       case HC_SMITYPE_TYPE3:
-               spin_lock_irqsave(&rtc_lock, flags);
-               /* write SMI data buffer physical address */
-               data = (u8 *)&smi_data_buf_phys_addr;
-               for (index = PE1400_CMOS_CMD_STRUCT_PTR;
-                    index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
-                    index++, data++) {
-                       outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
-                       outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
-               }
-
-               /* generate SMM call */
-               if (host_control_smi_type == HC_SMITYPE_TYPE3)
-                       outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
-               else
-                       outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);
-
-               /* restore RTC index pointer since it was written to above */
-               CMOS_READ(RTC_REG_C);
-               spin_unlock_irqrestore(&rtc_lock, flags);
-
-               /* read control port back to serialize write */
-               cmd_status = inb(PE1400_APM_CONTROL_PORT);
-
-               /* wait a few to see if it executed */
-               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
-               while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
-                       num_ticks--;
-                       if (num_ticks == EXPIRED_TIMER)
-                               return -ETIME;
-               }
-               break;
-
-       default:
-               dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
-                       __func__, host_control_smi_type);
-               return -ENOSYS;
-       }
-
-       return 0;
-}
-
-/**
- * dcdbas_host_control: initiate host control
- *
- * This function is called by the driver after the system has
- * finished shutting down if the user application specified a
- * host control action to perform on shutdown.  It is safe to
- * use smi_data_buf at this point because the system has finished
- * shutting down and no userspace apps are running.
- */
-static void dcdbas_host_control(void)
-{
-       struct apm_cmd *apm_cmd;
-       u8 action;
-
-       if (host_control_action == HC_ACTION_NONE)
-               return;
-
-       action = host_control_action;
-       host_control_action = HC_ACTION_NONE;
-
-       if (!smi_data_buf) {
-               dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __func__);
-               return;
-       }
-
-       if (smi_data_buf_size < sizeof(struct apm_cmd)) {
-               dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
-                       __func__);
-               return;
-       }
-
-       apm_cmd = (struct apm_cmd *)smi_data_buf;
-
-       /* power off takes precedence */
-       if (action & HC_ACTION_HOST_CONTROL_POWEROFF) {
-               apm_cmd->command = ESM_APM_POWER_CYCLE;
-               apm_cmd->reserved = 0;
-               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 0;
-               host_control_smi();
-       } else if (action & HC_ACTION_HOST_CONTROL_POWERCYCLE) {
-               apm_cmd->command = ESM_APM_POWER_CYCLE;
-               apm_cmd->reserved = 0;
-               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 20;
-               host_control_smi();
-       }
-}
-
-/**
- * dcdbas_reboot_notify: handle reboot notification for host control
- */
-static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
-                               void *unused)
-{
-       switch (code) {
-       case SYS_DOWN:
-       case SYS_HALT:
-       case SYS_POWER_OFF:
-               if (host_control_on_shutdown) {
-                       /* firmware is going to perform host control action */
-                       printk(KERN_WARNING "Please wait for shutdown "
-                              "action to complete...\n");
-                       dcdbas_host_control();
-               }
-               break;
-       }
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block dcdbas_reboot_nb = {
-       .notifier_call = dcdbas_reboot_notify,
-       .next = NULL,
-       .priority = INT_MIN
-};
-
-static DCDBAS_BIN_ATTR_RW(smi_data);
-
-static struct bin_attribute *dcdbas_bin_attrs[] = {
-       &bin_attr_smi_data,
-       NULL
-};
-
-static DCDBAS_DEV_ATTR_RW(smi_data_buf_size);
-static DCDBAS_DEV_ATTR_RO(smi_data_buf_phys_addr);
-static DCDBAS_DEV_ATTR_WO(smi_request);
-static DCDBAS_DEV_ATTR_RW(host_control_action);
-static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
-static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
-
-static struct attribute *dcdbas_dev_attrs[] = {
-       &dev_attr_smi_data_buf_size.attr,
-       &dev_attr_smi_data_buf_phys_addr.attr,
-       &dev_attr_smi_request.attr,
-       &dev_attr_host_control_action.attr,
-       &dev_attr_host_control_smi_type.attr,
-       &dev_attr_host_control_on_shutdown.attr,
-       NULL
-};
-
-static const struct attribute_group dcdbas_attr_group = {
-       .attrs = dcdbas_dev_attrs,
-       .bin_attrs = dcdbas_bin_attrs,
-};
-
-static int dcdbas_probe(struct platform_device *dev)
-{
-       int error;
-
-       host_control_action = HC_ACTION_NONE;
-       host_control_smi_type = HC_SMITYPE_NONE;
-
-       dcdbas_pdev = dev;
-
-       /*
-        * BIOS SMI calls require buffer addresses be in 32-bit address space.
-        * This is done by setting the DMA mask below.
-        */
-       error = dma_set_coherent_mask(&dcdbas_pdev->dev, DMA_BIT_MASK(32));
-       if (error)
-               return error;
-
-       error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
-       if (error)
-               return error;
-
-       register_reboot_notifier(&dcdbas_reboot_nb);
-
-       dev_info(&dev->dev, "%s (version %s)\n",
-                DRIVER_DESCRIPTION, DRIVER_VERSION);
-
-       return 0;
-}
-
-static int dcdbas_remove(struct platform_device *dev)
-{
-       unregister_reboot_notifier(&dcdbas_reboot_nb);
-       sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
-
-       return 0;
-}
-
-static struct platform_driver dcdbas_driver = {
-       .driver         = {
-               .name   = DRIVER_NAME,
-       },
-       .probe          = dcdbas_probe,
-       .remove         = dcdbas_remove,
-};
-
-static const struct platform_device_info dcdbas_dev_info __initconst = {
-       .name           = DRIVER_NAME,
-       .id             = -1,
-       .dma_mask       = DMA_BIT_MASK(32),
-};
-
-static struct platform_device *dcdbas_pdev_reg;
-
-/**
- * dcdbas_init: initialize driver
- */
-static int __init dcdbas_init(void)
-{
-       int error;
-
-       error = platform_driver_register(&dcdbas_driver);
-       if (error)
-               return error;
-
-       dcdbas_pdev_reg = platform_device_register_full(&dcdbas_dev_info);
-       if (IS_ERR(dcdbas_pdev_reg)) {
-               error = PTR_ERR(dcdbas_pdev_reg);
-               goto err_unregister_driver;
-       }
-
-       return 0;
-
- err_unregister_driver:
-       platform_driver_unregister(&dcdbas_driver);
-       return error;
-}
-
-/**
- * dcdbas_exit: perform driver cleanup
- */
-static void __exit dcdbas_exit(void)
-{
-       /*
-        * make sure functions that use dcdbas_pdev are called
-        * before platform_device_unregister
-        */
-       unregister_reboot_notifier(&dcdbas_reboot_nb);
-
-       /*
-        * We have to free the buffer here instead of dcdbas_remove
-        * because only in module exit function we can be sure that
-        * all sysfs attributes belonging to this module have been
-        * released.
-        */
-       if (dcdbas_pdev)
-               smi_data_buf_free();
-       platform_device_unregister(dcdbas_pdev_reg);
-       platform_driver_unregister(&dcdbas_driver);
-}
-
-subsys_initcall_sync(dcdbas_init);
-module_exit(dcdbas_exit);
-
-MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_AUTHOR("Dell Inc.");
-MODULE_LICENSE("GPL");
-/* Any System or BIOS claiming to be by Dell */
-MODULE_ALIAS("dmi:*:[bs]vnD[Ee][Ll][Ll]*:*");
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
deleted file mode 100644 (file)
index ca3cb0a..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *  dcdbas.h: Definitions for Dell Systems Management Base driver
- *
- *  Copyright (C) 1995-2005 Dell Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License v2.0 as published by
- *  the Free Software Foundation.
- *
- *  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.
- */
-
-#ifndef _DCDBAS_H_
-#define _DCDBAS_H_
-
-#include <linux/device.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-
-#define MAX_SMI_DATA_BUF_SIZE                  (256 * 1024)
-
-#define HC_ACTION_NONE                         (0)
-#define HC_ACTION_HOST_CONTROL_POWEROFF                BIT(1)
-#define HC_ACTION_HOST_CONTROL_POWERCYCLE      BIT(2)
-
-#define HC_SMITYPE_NONE                                (0)
-#define HC_SMITYPE_TYPE1                       (1)
-#define HC_SMITYPE_TYPE2                       (2)
-#define HC_SMITYPE_TYPE3                       (3)
-
-#define ESM_APM_CMD                            (0x0A0)
-#define ESM_APM_POWER_CYCLE                    (0x10)
-#define ESM_STATUS_CMD_UNSUCCESSFUL            (-1)
-
-#define CMOS_BASE_PORT                         (0x070)
-#define CMOS_PAGE1_INDEX_PORT                  (0)
-#define CMOS_PAGE1_DATA_PORT                   (1)
-#define CMOS_PAGE2_INDEX_PORT_PIIX4            (2)
-#define CMOS_PAGE2_DATA_PORT_PIIX4             (3)
-#define PE1400_APM_CONTROL_PORT                        (0x0B0)
-#define PCAT_APM_CONTROL_PORT                  (0x0B2)
-#define PCAT_APM_STATUS_PORT                   (0x0B3)
-#define PE1300_CMOS_CMD_STRUCT_PTR             (0x38)
-#define PE1400_CMOS_CMD_STRUCT_PTR             (0x70)
-
-#define MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN       (14)
-#define MAX_SYSMGMT_LONGCMD_SGENTRY_NUM                (16)
-
-#define TIMEOUT_USEC_SHORT_SEMA_BLOCKING       (10000)
-#define EXPIRED_TIMER                          (0)
-
-#define SMI_CMD_MAGIC                          (0x534D4931)
-
-#define DCDBAS_DEV_ATTR_RW(_name) \
-       DEVICE_ATTR(_name,0600,_name##_show,_name##_store);
-
-#define DCDBAS_DEV_ATTR_RO(_name) \
-       DEVICE_ATTR(_name,0400,_name##_show,NULL);
-
-#define DCDBAS_DEV_ATTR_WO(_name) \
-       DEVICE_ATTR(_name,0200,NULL,_name##_store);
-
-#define DCDBAS_BIN_ATTR_RW(_name) \
-struct bin_attribute bin_attr_##_name = { \
-       .attr =  { .name = __stringify(_name), \
-                  .mode = 0600 }, \
-       .read =  _name##_read, \
-       .write = _name##_write, \
-}
-
-struct smi_cmd {
-       __u32 magic;
-       __u32 ebx;
-       __u32 ecx;
-       __u16 command_address;
-       __u8 command_code;
-       __u8 reserved;
-       __u8 command_buffer[1];
-} __attribute__ ((packed));
-
-struct apm_cmd {
-       __u8 command;
-       __s8 status;
-       __u16 reserved;
-       union {
-               struct {
-                       __u8 parm[MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN];
-               } __attribute__ ((packed)) shortreq;
-
-               struct {
-                       __u16 num_sg_entries;
-                       struct {
-                               __u32 size;
-                               __u64 addr;
-                       } __attribute__ ((packed))
-                           sglist[MAX_SYSMGMT_LONGCMD_SGENTRY_NUM];
-               } __attribute__ ((packed)) longreq;
-       } __attribute__ ((packed)) parameters;
-} __attribute__ ((packed));
-
-int dcdbas_smi_request(struct smi_cmd *smi_cmd);
-
-#endif /* _DCDBAS_H_ */
-
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
deleted file mode 100644 (file)
index fb8af5c..0000000
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- * dell_rbu.c
- * Bios Update driver for Dell systems
- * Author: Dell Inc
- *         Abhay Salunke <abhay_salunke@dell.com>
- *
- * Copyright (C) 2005 Dell Inc.
- *
- * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
- * creating entries in the /sys file systems on Linux 2.6 and higher
- * kernels. The driver supports two mechanism to update the BIOS namely
- * contiguous and packetized. Both these methods still require having some
- * application to set the CMOS bit indicating the BIOS to update itself
- * after a reboot.
- *
- * Contiguous method:
- * This driver writes the incoming data in a monolithic image by allocating
- * contiguous physical pages large enough to accommodate the incoming BIOS
- * image size.
- *
- * Packetized method:
- * The driver writes the incoming packet image by allocating a new packet
- * on every time the packet data is written. This driver requires an
- * application to break the BIOS image in to fixed sized packet chunks.
- *
- * See Documentation/dell_rbu.txt for more info.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License v2.0 as published by
- * the Free Software Foundation
- *
- * 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.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/blkdev.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/moduleparam.h>
-#include <linux/firmware.h>
-#include <linux/dma-mapping.h>
-
-MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
-MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("3.2");
-
-#define BIOS_SCAN_LIMIT 0xffffffff
-#define MAX_IMAGE_LENGTH 16
-static struct _rbu_data {
-       void *image_update_buffer;
-       unsigned long image_update_buffer_size;
-       unsigned long bios_image_size;
-       int image_update_ordernum;
-       int dma_alloc;
-       spinlock_t lock;
-       unsigned long packet_read_count;
-       unsigned long num_packets;
-       unsigned long packetsize;
-       unsigned long imagesize;
-       int entry_created;
-} rbu_data;
-
-static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
-module_param_string(image_type, image_type, sizeof (image_type), 0);
-MODULE_PARM_DESC(image_type,
-       "BIOS image type. choose- mono or packet or init");
-
-static unsigned long allocation_floor = 0x100000;
-module_param(allocation_floor, ulong, 0644);
-MODULE_PARM_DESC(allocation_floor,
-    "Minimum address for allocations when using Packet mode");
-
-struct packet_data {
-       struct list_head list;
-       size_t length;
-       void *data;
-       int ordernum;
-};
-
-static struct packet_data packet_data_head;
-
-static struct platform_device *rbu_device;
-static int context;
-static dma_addr_t dell_rbu_dmaaddr;
-
-static void init_packet_head(void)
-{
-       INIT_LIST_HEAD(&packet_data_head.list);
-       rbu_data.packet_read_count = 0;
-       rbu_data.num_packets = 0;
-       rbu_data.packetsize = 0;
-       rbu_data.imagesize = 0;
-}
-
-static int create_packet(void *data, size_t length)
-{
-       struct packet_data *newpacket;
-       int ordernum = 0;
-       int retval = 0;
-       unsigned int packet_array_size = 0;
-       void **invalid_addr_packet_array = NULL;
-       void *packet_data_temp_buf = NULL;
-       unsigned int idx = 0;
-
-       pr_debug("create_packet: entry \n");
-
-       if (!rbu_data.packetsize) {
-               pr_debug("create_packet: packetsize not specified\n");
-               retval = -EINVAL;
-               goto out_noalloc;
-       }
-
-       spin_unlock(&rbu_data.lock);
-
-       newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);
-
-       if (!newpacket) {
-               printk(KERN_WARNING
-                       "dell_rbu:%s: failed to allocate new "
-                       "packet\n", __func__);
-               retval = -ENOMEM;
-               spin_lock(&rbu_data.lock);
-               goto out_noalloc;
-       }
-
-       ordernum = get_order(length);
-
-       /*
-        * BIOS errata mean we cannot allocate packets below 1MB or they will
-        * be overwritten by BIOS.
-        *
-        * array to temporarily hold packets
-        * that are below the allocation floor
-        *
-        * NOTE: very simplistic because we only need the floor to be at 1MB
-        *       due to BIOS errata. This shouldn't be used for higher floors
-        *       or you will run out of mem trying to allocate the array.
-        */
-       packet_array_size = max(
-                       (unsigned int)(allocation_floor / rbu_data.packetsize),
-                       (unsigned int)1);
-       invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *),
-                                               GFP_KERNEL);
-
-       if (!invalid_addr_packet_array) {
-               printk(KERN_WARNING
-                       "dell_rbu:%s: failed to allocate "
-                       "invalid_addr_packet_array \n",
-                       __func__);
-               retval = -ENOMEM;
-               spin_lock(&rbu_data.lock);
-               goto out_alloc_packet;
-       }
-
-       while (!packet_data_temp_buf) {
-               packet_data_temp_buf = (unsigned char *)
-                       __get_free_pages(GFP_KERNEL, ordernum);
-               if (!packet_data_temp_buf) {
-                       printk(KERN_WARNING
-                               "dell_rbu:%s: failed to allocate new "
-                               "packet\n", __func__);
-                       retval = -ENOMEM;
-                       spin_lock(&rbu_data.lock);
-                       goto out_alloc_packet_array;
-               }
-
-               if ((unsigned long)virt_to_phys(packet_data_temp_buf)
-                               < allocation_floor) {
-                       pr_debug("packet 0x%lx below floor at 0x%lx.\n",
-                                       (unsigned long)virt_to_phys(
-                                               packet_data_temp_buf),
-                                       allocation_floor);
-                       invalid_addr_packet_array[idx++] = packet_data_temp_buf;
-                       packet_data_temp_buf = NULL;
-               }
-       }
-       spin_lock(&rbu_data.lock);
-
-       newpacket->data = packet_data_temp_buf;
-
-       pr_debug("create_packet: newpacket at physical addr %lx\n",
-               (unsigned long)virt_to_phys(newpacket->data));
-
-       /* packets may not have fixed size */
-       newpacket->length = length;
-       newpacket->ordernum = ordernum;
-       ++rbu_data.num_packets;
-
-       /* initialize the newly created packet headers */
-       INIT_LIST_HEAD(&newpacket->list);
-       list_add_tail(&newpacket->list, &packet_data_head.list);
-
-       memcpy(newpacket->data, data, length);
-
-       pr_debug("create_packet: exit \n");
-
-out_alloc_packet_array:
-       /* always free packet array */
-       for (;idx>0;idx--) {
-               pr_debug("freeing unused packet below floor 0x%lx.\n",
-                       (unsigned long)virt_to_phys(
-                               invalid_addr_packet_array[idx-1]));
-               free_pages((unsigned long)invalid_addr_packet_array[idx-1],
-                       ordernum);
-       }
-       kfree(invalid_addr_packet_array);
-
-out_alloc_packet:
-       /* if error, free data */
-       if (retval)
-               kfree(newpacket);
-
-out_noalloc:
-       return retval;
-}
-
-static int packetize_data(const u8 *data, size_t length)
-{
-       int rc = 0;
-       int done = 0;
-       int packet_length;
-       u8 *temp;
-       u8 *end = (u8 *) data + length;
-       pr_debug("packetize_data: data length %zd\n", length);
-       if (!rbu_data.packetsize) {
-               printk(KERN_WARNING
-                       "dell_rbu: packetsize not specified\n");
-               return -EIO;
-       }
-
-       temp = (u8 *) data;
-
-       /* packetize the hunk */
-       while (!done) {
-               if ((temp + rbu_data.packetsize) < end)
-                       packet_length = rbu_data.packetsize;
-               else {
-                       /* this is the last packet */
-                       packet_length = end - temp;
-                       done = 1;
-               }
-
-               if ((rc = create_packet(temp, packet_length)))
-                       return rc;
-
-               pr_debug("%p:%td\n", temp, (end - temp));
-               temp += packet_length;
-       }
-
-       rbu_data.imagesize = length;
-
-       return rc;
-}
-
-static int do_packet_read(char *data, struct list_head *ptemp_list,
-       int length, int bytes_read, int *list_read_count)
-{
-       void *ptemp_buf;
-       struct packet_data *newpacket = NULL;
-       int bytes_copied = 0;
-       int j = 0;
-
-       newpacket = list_entry(ptemp_list, struct packet_data, list);
-       *list_read_count += newpacket->length;
-
-       if (*list_read_count > bytes_read) {
-               /* point to the start of unread data */
-               j = newpacket->length - (*list_read_count - bytes_read);
-               /* point to the offset in the packet buffer */
-               ptemp_buf = (u8 *) newpacket->data + j;
-               /*
-                * check if there is enough room in
-                * * the incoming buffer
-                */
-               if (length > (*list_read_count - bytes_read))
-                       /*
-                        * copy what ever is there in this
-                        * packet and move on
-                        */
-                       bytes_copied = (*list_read_count - bytes_read);
-               else
-                       /* copy the remaining */
-                       bytes_copied = length;
-               memcpy(data, ptemp_buf, bytes_copied);
-       }
-       return bytes_copied;
-}
-
-static int packet_read_list(char *data, size_t * pread_length)
-{
-       struct list_head *ptemp_list;
-       int temp_count = 0;
-       int bytes_copied = 0;
-       int bytes_read = 0;
-       int remaining_bytes = 0;
-       char *pdest = data;
-
-       /* check if we have any packets */
-       if (0 == rbu_data.num_packets)
-               return -ENOMEM;
-
-       remaining_bytes = *pread_length;
-       bytes_read = rbu_data.packet_read_count;
-
-       ptemp_list = (&packet_data_head.list)->next;
-       while (!list_empty(ptemp_list)) {
-               bytes_copied = do_packet_read(pdest, ptemp_list,
-                       remaining_bytes, bytes_read, &temp_count);
-               remaining_bytes -= bytes_copied;
-               bytes_read += bytes_copied;
-               pdest += bytes_copied;
-               /*
-                * check if we reached end of buffer before reaching the
-                * last packet
-                */
-               if (remaining_bytes == 0)
-                       break;
-
-               ptemp_list = ptemp_list->next;
-       }
-       /*finally set the bytes read */
-       *pread_length = bytes_read - rbu_data.packet_read_count;
-       rbu_data.packet_read_count = bytes_read;
-       return 0;
-}
-
-static void packet_empty_list(void)
-{
-       struct list_head *ptemp_list;
-       struct list_head *pnext_list;
-       struct packet_data *newpacket;
-
-       ptemp_list = (&packet_data_head.list)->next;
-       while (!list_empty(ptemp_list)) {
-               newpacket =
-                       list_entry(ptemp_list, struct packet_data, list);
-               pnext_list = ptemp_list->next;
-               list_del(ptemp_list);
-               ptemp_list = pnext_list;
-               /*
-                * zero out the RBU packet memory before freeing
-                * to make sure there are no stale RBU packets left in memory
-                */
-               memset(newpacket->data, 0, rbu_data.packetsize);
-               free_pages((unsigned long) newpacket->data,
-                       newpacket->ordernum);
-               kfree(newpacket);
-       }
-       rbu_data.packet_read_count = 0;
-       rbu_data.num_packets = 0;
-       rbu_data.imagesize = 0;
-}
-
-/*
- * img_update_free: Frees the buffer allocated for storing BIOS image
- * Always called with lock held and returned with lock held
- */
-static void img_update_free(void)
-{
-       if (!rbu_data.image_update_buffer)
-               return;
-       /*
-        * zero out this buffer before freeing it to get rid of any stale
-        * BIOS image copied in memory.
-        */
-       memset(rbu_data.image_update_buffer, 0,
-               rbu_data.image_update_buffer_size);
-       if (rbu_data.dma_alloc == 1)
-               dma_free_coherent(NULL, rbu_data.bios_image_size,
-                       rbu_data.image_update_buffer, dell_rbu_dmaaddr);
-       else
-               free_pages((unsigned long) rbu_data.image_update_buffer,
-                       rbu_data.image_update_ordernum);
-
-       /*
-        * Re-initialize the rbu_data variables after a free
-        */
-       rbu_data.image_update_ordernum = -1;
-       rbu_data.image_update_buffer = NULL;
-       rbu_data.image_update_buffer_size = 0;
-       rbu_data.bios_image_size = 0;
-       rbu_data.dma_alloc = 0;
-}
-
-/*
- * img_update_realloc: This function allocates the contiguous pages to
- * accommodate the requested size of data. The memory address and size
- * values are stored globally and on every call to this function the new
- * size is checked to see if more data is required than the existing size.
- * If true the previous memory is freed and new allocation is done to
- * accommodate the new size. If the incoming size is less then than the
- * already allocated size, then that memory is reused. This function is
- * called with lock held and returns with lock held.
- */
-static int img_update_realloc(unsigned long size)
-{
-       unsigned char *image_update_buffer = NULL;
-       unsigned long rc;
-       unsigned long img_buf_phys_addr;
-       int ordernum;
-       int dma_alloc = 0;
-
-       /*
-        * check if the buffer of sufficient size has been
-        * already allocated
-        */
-       if (rbu_data.image_update_buffer_size >= size) {
-               /*
-                * check for corruption
-                */
-               if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
-                       printk(KERN_ERR "dell_rbu:%s: corruption "
-                               "check failed\n", __func__);
-                       return -EINVAL;
-               }
-               /*
-                * we have a valid pre-allocated buffer with
-                * sufficient size
-                */
-               return 0;
-       }
-
-       /*
-        * free any previously allocated buffer
-        */
-       img_update_free();
-
-       spin_unlock(&rbu_data.lock);
-
-       ordernum = get_order(size);
-       image_update_buffer =
-               (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
-
-       img_buf_phys_addr =
-               (unsigned long) virt_to_phys(image_update_buffer);
-
-       if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
-               free_pages((unsigned long) image_update_buffer, ordernum);
-               ordernum = -1;
-               image_update_buffer = dma_alloc_coherent(NULL, size,
-                       &dell_rbu_dmaaddr, GFP_KERNEL);
-               dma_alloc = 1;
-       }
-
-       spin_lock(&rbu_data.lock);
-
-       if (image_update_buffer != NULL) {
-               rbu_data.image_update_buffer = image_update_buffer;
-               rbu_data.image_update_buffer_size = size;
-               rbu_data.bios_image_size =
-                       rbu_data.image_update_buffer_size;
-               rbu_data.image_update_ordernum = ordernum;
-               rbu_data.dma_alloc = dma_alloc;
-               rc = 0;
-       } else {
-               pr_debug("Not enough memory for image update:"
-                       "size = %ld\n", size);
-               rc = -ENOMEM;
-       }
-
-       return rc;
-}
-
-static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
-{
-       int retval;
-       size_t bytes_left;
-       size_t data_length;
-       char *ptempBuf = buffer;
-
-       /* check to see if we have something to return */
-       if (rbu_data.num_packets == 0) {
-               pr_debug("read_packet_data: no packets written\n");
-               retval = -ENOMEM;
-               goto read_rbu_data_exit;
-       }
-
-       if (pos > rbu_data.imagesize) {
-               retval = 0;
-               printk(KERN_WARNING "dell_rbu:read_packet_data: "
-                       "data underrun\n");
-               goto read_rbu_data_exit;
-       }
-
-       bytes_left = rbu_data.imagesize - pos;
-       data_length = min(bytes_left, count);
-
-       if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
-               goto read_rbu_data_exit;
-
-       if ((pos + count) > rbu_data.imagesize) {
-               rbu_data.packet_read_count = 0;
-               /* this was the last copy */
-               retval = bytes_left;
-       } else
-               retval = count;
-
-      read_rbu_data_exit:
-       return retval;
-}
-
-static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
-{
-       /* check to see if we have something to return */
-       if ((rbu_data.image_update_buffer == NULL) ||
-               (rbu_data.bios_image_size == 0)) {
-               pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
-                       "bios_image_size %lu\n",
-                       rbu_data.image_update_buffer,
-                       rbu_data.bios_image_size);
-               return -ENOMEM;
-       }
-
-       return memory_read_from_buffer(buffer, count, &pos,
-                       rbu_data.image_update_buffer, rbu_data.bios_image_size);
-}
-
-static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj,
-                            struct bin_attribute *bin_attr,
-                            char *buffer, loff_t pos, size_t count)
-{
-       ssize_t ret_count = 0;
-
-       spin_lock(&rbu_data.lock);
-
-       if (!strcmp(image_type, "mono"))
-               ret_count = read_rbu_mono_data(buffer, pos, count);
-       else if (!strcmp(image_type, "packet"))
-               ret_count = read_packet_data(buffer, pos, count);
-       else
-               pr_debug("read_rbu_data: invalid image type specified\n");
-
-       spin_unlock(&rbu_data.lock);
-       return ret_count;
-}
-
-static void callbackfn_rbu(const struct firmware *fw, void *context)
-{
-       rbu_data.entry_created = 0;
-
-       if (!fw)
-               return;
-
-       if (!fw->size)
-               goto out;
-
-       spin_lock(&rbu_data.lock);
-       if (!strcmp(image_type, "mono")) {
-               if (!img_update_realloc(fw->size))
-                       memcpy(rbu_data.image_update_buffer,
-                               fw->data, fw->size);
-       } else if (!strcmp(image_type, "packet")) {
-               /*
-                * we need to free previous packets if a
-                * new hunk of packets needs to be downloaded
-                */
-               packet_empty_list();
-               if (packetize_data(fw->data, fw->size))
-                       /* Incase something goes wrong when we are
-                        * in middle of packetizing the data, we
-                        * need to free up whatever packets might
-                        * have been created before we quit.
-                        */
-                       packet_empty_list();
-       } else
-               pr_debug("invalid image type specified.\n");
-       spin_unlock(&rbu_data.lock);
- out:
-       release_firmware(fw);
-}
-
-static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj,
-                                  struct bin_attribute *bin_attr,
-                                  char *buffer, loff_t pos, size_t count)
-{
-       int size = 0;
-       if (!pos)
-               size = scnprintf(buffer, count, "%s\n", image_type);
-       return size;
-}
-
-static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj,
-                                   struct bin_attribute *bin_attr,
-                                   char *buffer, loff_t pos, size_t count)
-{
-       int rc = count;
-       int req_firm_rc = 0;
-       int i;
-       spin_lock(&rbu_data.lock);
-       /*
-        * Find the first newline or space
-        */
-       for (i = 0; i < count; ++i)
-               if (buffer[i] == '\n' || buffer[i] == ' ') {
-                       buffer[i] = '\0';
-                       break;
-               }
-       if (i == count)
-               buffer[count] = '\0';
-
-       if (strstr(buffer, "mono"))
-               strcpy(image_type, "mono");
-       else if (strstr(buffer, "packet"))
-               strcpy(image_type, "packet");
-       else if (strstr(buffer, "init")) {
-               /*
-                * If due to the user error the driver gets in a bad
-                * state where even though it is loaded , the
-                * /sys/class/firmware/dell_rbu entries are missing.
-                * to cover this situation the user can recreate entries
-                * by writing init to image_type.
-                */
-               if (!rbu_data.entry_created) {
-                       spin_unlock(&rbu_data.lock);
-                       req_firm_rc = request_firmware_nowait(THIS_MODULE,
-                               FW_ACTION_NOHOTPLUG, "dell_rbu",
-                               &rbu_device->dev, GFP_KERNEL, &context,
-                               callbackfn_rbu);
-                       if (req_firm_rc) {
-                               printk(KERN_ERR
-                                       "dell_rbu:%s request_firmware_nowait"
-                                       " failed %d\n", __func__, rc);
-                               rc = -EIO;
-                       } else
-                               rbu_data.entry_created = 1;
-
-                       spin_lock(&rbu_data.lock);
-               }
-       } else {
-               printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
-               spin_unlock(&rbu_data.lock);
-               return -EINVAL;
-       }
-
-       /* we must free all previous allocations */
-       packet_empty_list();
-       img_update_free();
-       spin_unlock(&rbu_data.lock);
-
-       return rc;
-}
-
-static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj,
-                                   struct bin_attribute *bin_attr,
-                                   char *buffer, loff_t pos, size_t count)
-{
-       int size = 0;
-       if (!pos) {
-               spin_lock(&rbu_data.lock);
-               size = scnprintf(buffer, count, "%lu\n", rbu_data.packetsize);
-               spin_unlock(&rbu_data.lock);
-       }
-       return size;
-}
-
-static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj,
-                                    struct bin_attribute *bin_attr,
-                                    char *buffer, loff_t pos, size_t count)
-{
-       unsigned long temp;
-       spin_lock(&rbu_data.lock);
-       packet_empty_list();
-       sscanf(buffer, "%lu", &temp);
-       if (temp < 0xffffffff)
-               rbu_data.packetsize = temp;
-
-       spin_unlock(&rbu_data.lock);
-       return count;
-}
-
-static struct bin_attribute rbu_data_attr = {
-       .attr = {.name = "data", .mode = 0444},
-       .read = read_rbu_data,
-};
-
-static struct bin_attribute rbu_image_type_attr = {
-       .attr = {.name = "image_type", .mode = 0644},
-       .read = read_rbu_image_type,
-       .write = write_rbu_image_type,
-};
-
-static struct bin_attribute rbu_packet_size_attr = {
-       .attr = {.name = "packet_size", .mode = 0644},
-       .read = read_rbu_packet_size,
-       .write = write_rbu_packet_size,
-};
-
-static int __init dcdrbu_init(void)
-{
-       int rc;
-       spin_lock_init(&rbu_data.lock);
-
-       init_packet_head();
-       rbu_device = platform_device_register_simple("dell_rbu", -1, NULL, 0);
-       if (IS_ERR(rbu_device)) {
-               printk(KERN_ERR
-                       "dell_rbu:%s:platform_device_register_simple "
-                       "failed\n", __func__);
-               return PTR_ERR(rbu_device);
-       }
-
-       rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
-       if (rc)
-               goto out_devreg;
-       rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
-       if (rc)
-               goto out_data;
-       rc = sysfs_create_bin_file(&rbu_device->dev.kobj,
-               &rbu_packet_size_attr);
-       if (rc)
-               goto out_imtype;
-
-       rbu_data.entry_created = 0;
-       return 0;
-
-out_imtype:
-       sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
-out_data:
-       sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
-out_devreg:
-       platform_device_unregister(rbu_device);
-       return rc;
-}
-
-static __exit void dcdrbu_exit(void)
-{
-       spin_lock(&rbu_data.lock);
-       packet_empty_list();
-       img_update_free();
-       spin_unlock(&rbu_data.lock);
-       platform_device_unregister(rbu_device);
-}
-
-module_exit(dcdrbu_exit);
-module_init(dcdrbu_init);
-
-/* vim:noet:ts=8:sw=8
-*/
index 5ed319e3b084d920cddf6adc5a665c5732c8c77c..41e9935fc5849e0992e3103912fbe01a5af2a555 100644 (file)
@@ -149,6 +149,7 @@ config HID_APPLEIR
 config HID_ASUS
        tristate "Asus"
        depends on LEDS_CLASS
+       depends on ASUS_WMI || ASUS_WMI=n
        ---help---
        Support for Asus notebook built-in keyboard and touchpad via i2c, and
        the Asus Republic of Gamers laptop keyboard special keys.
index 88a5672f42cd814187ede87e8783414023824bf2..dc6d6477e9611eb2ba93a8d687bfaf9d4e634ef8 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/dmi.h>
 #include <linux/hid.h>
 #include <linux/module.h>
+#include <linux/platform_data/x86/asus-wmi.h>
 #include <linux/input/mt.h>
 #include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
 
@@ -349,6 +350,24 @@ static void asus_kbd_backlight_work(struct work_struct *work)
                hid_err(led->hdev, "Asus failed to set keyboard backlight: %d\n", ret);
 }
 
+/* WMI-based keyboard backlight LED control (via asus-wmi driver) takes
+ * precedence. We only activate HID-based backlight control when the
+ * WMI control is not available.
+ */
+static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev)
+{
+       u32 value;
+       int ret;
+
+       ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2,
+                                      ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value);
+       hid_dbg(hdev, "WMI backlight check: rc %d value %x", ret, value);
+       if (ret)
+               return false;
+
+       return !!(value & ASUS_WMI_DSTS_PRESENCE_BIT);
+}
+
 static int asus_kbd_register_leds(struct hid_device *hdev)
 {
        struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
@@ -436,7 +455,9 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
 
        drvdata->input = input;
 
-       if (drvdata->enable_backlight && asus_kbd_register_leds(hdev))
+       if (drvdata->enable_backlight &&
+           !asus_kbd_wmi_led_control_present(hdev) &&
+           asus_kbd_register_leds(hdev))
                hid_warn(hdev, "Failed to initialize backlight.\n");
 
        return 0;
index 45e9453608c58dcf311dde45c55491f23d1e6c7d..978d836a02481fc12f8644a28f1067fca046b99c 100644 (file)
 
 #define CROS_EC_DEV_VERSION "1.0.0"
 
-/*
- * @offset: within EC_LPC_ADDR_MEMMAP region
- * @bytes: number of bytes to read. zero means "read a string" (including '\0')
- *         (at most only EC_MEMMAP_SIZE bytes can be read)
- * @buffer: where to store the result
- * ioctl returns the number of bytes read, negative on error
+/**
+ * struct cros_ec_readmem - Struct used to read mapped memory.
+ * @offset: Within EC_LPC_ADDR_MEMMAP region.
+ * @bytes: Number of bytes to read. Zero means "read a string" (including '\0')
+ *         At most only EC_MEMMAP_SIZE bytes can be read.
+ * @buffer: Where to store the result. The ioctl returns the number of bytes
+ *         read or negative on error.
  */
 struct cros_ec_readmem {
        uint32_t offset;
index 9697977b80f040c3fde59037e2caabe0cdfaa79f..6b9ad86732188c19c87f26a6639d63f95893f139 100644 (file)
@@ -638,8 +638,7 @@ static int bond_fill_info(struct sk_buff *skb,
                                goto nla_put_failure;
 
                        if (nla_put(skb, IFLA_BOND_AD_ACTOR_SYSTEM,
-                                   sizeof(bond->params.ad_actor_system),
-                                   &bond->params.ad_actor_system))
+                                   ETH_ALEN, &bond->params.ad_actor_system))
                                goto nla_put_failure;
                }
                if (!bond_3ad_get_active_agg_info(bond, &info)) {
index e82e4ca206205da6562fa3449802869a975a86d3..055b40606dbc20f358f6445067b33f226d79554e 100644 (file)
@@ -316,8 +316,8 @@ struct hnae3_ae_ops {
        int (*set_loopback)(struct hnae3_handle *handle,
                            enum hnae3_loop loop_mode, bool en);
 
-       void (*set_promisc_mode)(struct hnae3_handle *handle, bool en_uc_pmc,
-                                bool en_mc_pmc);
+       int (*set_promisc_mode)(struct hnae3_handle *handle, bool en_uc_pmc,
+                               bool en_mc_pmc);
        int (*set_mtu)(struct hnae3_handle *handle, int new_mtu);
 
        void (*get_pauseparam)(struct hnae3_handle *handle,
@@ -391,7 +391,7 @@ struct hnae3_ae_ops {
                                      int vector_num,
                                      struct hnae3_ring_chain_node *vr_chain);
 
-       void (*reset_queue)(struct hnae3_handle *handle, u16 queue_id);
+       int (*reset_queue)(struct hnae3_handle *handle, u16 queue_id);
        u32 (*get_fw_version)(struct hnae3_handle *handle);
        void (*get_mdix_mode)(struct hnae3_handle *handle,
                              u8 *tp_mdix_ctrl, u8 *tp_mdix);
index 32f3aca814e78b530495956d7cafcb9017139176..3f96aa30068ec3dcf991bec4ed022b3e68d013e7 100644 (file)
@@ -509,16 +509,18 @@ static void hns3_nic_set_rx_mode(struct net_device *netdev)
        h->netdev_flags = new_flags;
 }
 
-void hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags)
+int hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags)
 {
        struct hns3_nic_priv *priv = netdev_priv(netdev);
        struct hnae3_handle *h = priv->ae_handle;
 
        if (h->ae_algo->ops->set_promisc_mode) {
-               h->ae_algo->ops->set_promisc_mode(h,
-                                                 promisc_flags & HNAE3_UPE,
-                                                 promisc_flags & HNAE3_MPE);
+               return h->ae_algo->ops->set_promisc_mode(h,
+                                               promisc_flags & HNAE3_UPE,
+                                               promisc_flags & HNAE3_MPE);
        }
+
+       return 0;
 }
 
 void hns3_enable_vlan_filter(struct net_device *netdev, bool enable)
@@ -1494,18 +1496,22 @@ static int hns3_vlan_rx_kill_vid(struct net_device *netdev,
        return ret;
 }
 
-static void hns3_restore_vlan(struct net_device *netdev)
+static int hns3_restore_vlan(struct net_device *netdev)
 {
        struct hns3_nic_priv *priv = netdev_priv(netdev);
+       int ret = 0;
        u16 vid;
-       int ret;
 
        for_each_set_bit(vid, priv->active_vlans, VLAN_N_VID) {
                ret = hns3_vlan_rx_add_vid(netdev, htons(ETH_P_8021Q), vid);
-               if (ret)
-                       netdev_warn(netdev, "Restore vlan: %d filter, ret:%d\n",
-                                   vid, ret);
+               if (ret) {
+                       netdev_err(netdev, "Restore vlan: %d filter, ret:%d\n",
+                                  vid, ret);
+                       return ret;
+               }
        }
+
+       return ret;
 }
 
 static int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
@@ -2727,7 +2733,7 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
                        chain = devm_kzalloc(&pdev->dev, sizeof(*chain),
                                             GFP_KERNEL);
                        if (!chain)
-                               return -ENOMEM;
+                               goto err_free_chain;
 
                        cur_chain->next = chain;
                        chain->tqp_index = tx_ring->tqp->tqp_index;
@@ -2757,7 +2763,7 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
        while (rx_ring) {
                chain = devm_kzalloc(&pdev->dev, sizeof(*chain), GFP_KERNEL);
                if (!chain)
-                       return -ENOMEM;
+                       goto err_free_chain;
 
                cur_chain->next = chain;
                chain->tqp_index = rx_ring->tqp->tqp_index;
@@ -2772,6 +2778,16 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
        }
 
        return 0;
+
+err_free_chain:
+       cur_chain = head->next;
+       while (cur_chain) {
+               chain = cur_chain->next;
+               devm_kfree(&pdev->dev, chain);
+               cur_chain = chain;
+       }
+
+       return -ENOMEM;
 }
 
 static void hns3_free_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
@@ -2821,7 +2837,7 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
        struct hnae3_handle *h = priv->ae_handle;
        struct hns3_enet_tqp_vector *tqp_vector;
        int ret = 0;
-       u16 i;
+       int i;
 
        hns3_nic_set_cpumask(priv);
 
@@ -2868,13 +2884,19 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
                hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain);
 
                if (ret)
-                       return ret;
+                       goto map_ring_fail;
 
                netif_napi_add(priv->netdev, &tqp_vector->napi,
                               hns3_nic_common_poll, NAPI_POLL_WEIGHT);
        }
 
        return 0;
+
+map_ring_fail:
+       while (i--)
+               netif_napi_del(&priv->tqp_vector[i].napi);
+
+       return ret;
 }
 
 static int hns3_nic_alloc_vector_data(struct hns3_nic_priv *priv)
@@ -3031,8 +3053,10 @@ static int hns3_queue_to_ring(struct hnae3_queue *tqp,
                return ret;
 
        ret = hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_RX);
-       if (ret)
+       if (ret) {
+               devm_kfree(priv->dev, priv->ring_data[tqp->tqp_index].ring);
                return ret;
+       }
 
        return 0;
 }
@@ -3059,6 +3083,12 @@ static int hns3_get_ring_config(struct hns3_nic_priv *priv)
 
        return 0;
 err:
+       while (i--) {
+               devm_kfree(priv->dev, priv->ring_data[i].ring);
+               devm_kfree(priv->dev,
+                          priv->ring_data[i + h->kinfo.num_tqps].ring);
+       }
+
        devm_kfree(&pdev->dev, priv->ring_data);
        return ret;
 }
@@ -3226,9 +3256,6 @@ int hns3_uninit_all_ring(struct hns3_nic_priv *priv)
        int i;
 
        for (i = 0; i < h->kinfo.num_tqps; i++) {
-               if (h->ae_algo->ops->reset_queue)
-                       h->ae_algo->ops->reset_queue(h, i);
-
                hns3_fini_ring(priv->ring_data[i].ring);
                hns3_fini_ring(priv->ring_data[i + h->kinfo.num_tqps].ring);
        }
@@ -3236,11 +3263,12 @@ int hns3_uninit_all_ring(struct hns3_nic_priv *priv)
 }
 
 /* Set mac addr if it is configured. or leave it to the AE driver */
-static void hns3_init_mac_addr(struct net_device *netdev, bool init)
+static int hns3_init_mac_addr(struct net_device *netdev, bool init)
 {
        struct hns3_nic_priv *priv = netdev_priv(netdev);
        struct hnae3_handle *h = priv->ae_handle;
        u8 mac_addr_temp[ETH_ALEN];
+       int ret = 0;
 
        if (h->ae_algo->ops->get_mac_addr && init) {
                h->ae_algo->ops->get_mac_addr(h, mac_addr_temp);
@@ -3255,8 +3283,9 @@ static void hns3_init_mac_addr(struct net_device *netdev, bool init)
        }
 
        if (h->ae_algo->ops->set_mac_addr)
-               h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr, true);
+               ret = h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr, true);
 
+       return ret;
 }
 
 static int hns3_restore_fd_rules(struct net_device *netdev)
@@ -3469,20 +3498,29 @@ err_out:
        return ret;
 }
 
-static void hns3_recover_hw_addr(struct net_device *ndev)
+static int hns3_recover_hw_addr(struct net_device *ndev)
 {
        struct netdev_hw_addr_list *list;
        struct netdev_hw_addr *ha, *tmp;
+       int ret = 0;
 
        /* go through and sync uc_addr entries to the device */
        list = &ndev->uc;
-       list_for_each_entry_safe(ha, tmp, &list->list, list)
-               hns3_nic_uc_sync(ndev, ha->addr);
+       list_for_each_entry_safe(ha, tmp, &list->list, list) {
+               ret = hns3_nic_uc_sync(ndev, ha->addr);
+               if (ret)
+                       return ret;
+       }
 
        /* go through and sync mc_addr entries to the device */
        list = &ndev->mc;
-       list_for_each_entry_safe(ha, tmp, &list->list, list)
-               hns3_nic_mc_sync(ndev, ha->addr);
+       list_for_each_entry_safe(ha, tmp, &list->list, list) {
+               ret = hns3_nic_mc_sync(ndev, ha->addr);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
 }
 
 static void hns3_remove_hw_addr(struct net_device *netdev)
@@ -3609,7 +3647,10 @@ int hns3_nic_reset_all_ring(struct hnae3_handle *h)
        int ret;
 
        for (i = 0; i < h->kinfo.num_tqps; i++) {
-               h->ae_algo->ops->reset_queue(h, i);
+               ret = h->ae_algo->ops->reset_queue(h, i);
+               if (ret)
+                       return ret;
+
                hns3_init_ring_hw(priv->ring_data[i].ring);
 
                /* We need to clear tx ring here because self test will
@@ -3701,18 +3742,30 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
        bool vlan_filter_enable;
        int ret;
 
-       hns3_init_mac_addr(netdev, false);
-       hns3_recover_hw_addr(netdev);
-       hns3_update_promisc_mode(netdev, handle->netdev_flags);
+       ret = hns3_init_mac_addr(netdev, false);
+       if (ret)
+               return ret;
+
+       ret = hns3_recover_hw_addr(netdev);
+       if (ret)
+               return ret;
+
+       ret = hns3_update_promisc_mode(netdev, handle->netdev_flags);
+       if (ret)
+               return ret;
+
        vlan_filter_enable = netdev->flags & IFF_PROMISC ? false : true;
        hns3_enable_vlan_filter(netdev, vlan_filter_enable);
 
-
        /* Hardware table is only clear when pf resets */
-       if (!(handle->flags & HNAE3_SUPPORT_VF))
-               hns3_restore_vlan(netdev);
+       if (!(handle->flags & HNAE3_SUPPORT_VF)) {
+               ret = hns3_restore_vlan(netdev);
+               return ret;
+       }
 
-       hns3_restore_fd_rules(netdev);
+       ret = hns3_restore_fd_rules(netdev);
+       if (ret)
+               return ret;
 
        /* Carrier off reporting is important to ethtool even BEFORE open */
        netif_carrier_off(netdev);
index 71cfca132d0bd044006f3a8e1a599973dbceb500..d3636d088aa3d960ae3bc2721d1257018286ae89 100644 (file)
@@ -640,7 +640,7 @@ void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector,
                                 u32 rl_value);
 
 void hns3_enable_vlan_filter(struct net_device *netdev, bool enable);
-void hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags);
+int hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags);
 
 #ifdef CONFIG_HNS3_DCB
 void hns3_dcbnl_setup(struct hnae3_handle *handle);
index ac13cb2b168e5a6e67517837dd470e092a0db8f8..690f62ed87dcaa3b1997df510f0c06784e7c1eb6 100644 (file)
@@ -24,15 +24,15 @@ static int hclge_ring_space(struct hclge_cmq_ring *ring)
        return ring->desc_num - used - 1;
 }
 
-static int is_valid_csq_clean_head(struct hclge_cmq_ring *ring, int h)
+static int is_valid_csq_clean_head(struct hclge_cmq_ring *ring, int head)
 {
-       int u = ring->next_to_use;
-       int c = ring->next_to_clean;
+       int ntu = ring->next_to_use;
+       int ntc = ring->next_to_clean;
 
-       if (unlikely(h >= ring->desc_num))
-               return 0;
+       if (ntu > ntc)
+               return head >= ntc && head <= ntu;
 
-       return u > c ? (h > c && h <= u) : (h > c || h <= u);
+       return head >= ntc || head <= ntu;
 }
 
 static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
@@ -304,6 +304,10 @@ int hclge_cmd_queue_init(struct hclge_dev *hdev)
 {
        int ret;
 
+       /* Setup the lock for command queue */
+       spin_lock_init(&hdev->hw.cmq.csq.lock);
+       spin_lock_init(&hdev->hw.cmq.crq.lock);
+
        /* Setup the queue entries for use cmd queue */
        hdev->hw.cmq.csq.desc_num = HCLGE_NIC_CMQ_DESC_NUM;
        hdev->hw.cmq.crq.desc_num = HCLGE_NIC_CMQ_DESC_NUM;
@@ -337,18 +341,20 @@ int hclge_cmd_init(struct hclge_dev *hdev)
        u32 version;
        int ret;
 
+       spin_lock_bh(&hdev->hw.cmq.csq.lock);
+       spin_lock_bh(&hdev->hw.cmq.crq.lock);
+
        hdev->hw.cmq.csq.next_to_clean = 0;
        hdev->hw.cmq.csq.next_to_use = 0;
        hdev->hw.cmq.crq.next_to_clean = 0;
        hdev->hw.cmq.crq.next_to_use = 0;
 
-       /* Setup the lock for command queue */
-       spin_lock_init(&hdev->hw.cmq.csq.lock);
-       spin_lock_init(&hdev->hw.cmq.crq.lock);
-
        hclge_cmd_init_regs(&hdev->hw);
        clear_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
 
+       spin_unlock_bh(&hdev->hw.cmq.crq.lock);
+       spin_unlock_bh(&hdev->hw.cmq.csq.lock);
+
        ret = hclge_cmd_query_firmware_version(&hdev->hw, &version);
        if (ret) {
                dev_err(&hdev->pdev->dev,
index dca6f2326c2672bf75f46613c2ed3389003090de..123c37e653f3eda4ad120970aa4cd19b094557f8 100644 (file)
@@ -751,7 +751,7 @@ static void hclge_process_ncsi_error(struct hclge_dev *hdev,
        ret = hclge_cmd_clear_error(hdev, &desc_wr, &desc_rd,
                                    HCLGE_NCSI_INT_CLR, 0);
        if (ret)
-               dev_err(dev, "failed(=%d) to clear NCSI intrerrupt status\n",
+               dev_err(dev, "failed(=%d) to clear NCSI interrupt status\n",
                        ret);
 }
 
index 5234b5373ed3b9257aad7ad3f480040694623721..ffdd96020860db0153d467814984d63efb01995e 100644 (file)
@@ -2236,7 +2236,7 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data)
        }
 
        /* clear the source of interrupt if it is not cause by reset */
-       if (event_cause != HCLGE_VECTOR0_EVENT_RST) {
+       if (event_cause == HCLGE_VECTOR0_EVENT_MBX) {
                hclge_clear_event_cause(hdev, event_cause, clearval);
                hclge_enable_vector(&hdev->misc_vector, true);
        }
@@ -2470,14 +2470,17 @@ static void hclge_reset(struct hclge_dev *hdev)
        handle = &hdev->vport[0].nic;
        rtnl_lock();
        hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
+       rtnl_unlock();
 
        if (!hclge_reset_wait(hdev)) {
+               rtnl_lock();
                hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT);
                hclge_reset_ae_dev(hdev->ae_dev);
                hclge_notify_client(hdev, HNAE3_INIT_CLIENT);
 
                hclge_clear_reset_cause(hdev);
        } else {
+               rtnl_lock();
                /* schedule again to check pending resets later */
                set_bit(hdev->reset_type, &hdev->reset_pending);
                hclge_reset_task_schedule(hdev);
@@ -3314,8 +3317,8 @@ void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc,
        param->vf_id = vport_id;
 }
 
-static void hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
-                                  bool en_mc_pmc)
+static int hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
+                                 bool en_mc_pmc)
 {
        struct hclge_vport *vport = hclge_get_vport(handle);
        struct hclge_dev *hdev = vport->back;
@@ -3323,7 +3326,7 @@ static void hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
 
        hclge_promisc_param_init(&param, en_uc_pmc, en_mc_pmc, true,
                                 vport->vport_id);
-       hclge_cmd_set_promisc_mode(hdev, &param);
+       return hclge_cmd_set_promisc_mode(hdev, &param);
 }
 
 static int hclge_get_fd_mode(struct hclge_dev *hdev, u8 *fd_mode)
@@ -6107,31 +6110,28 @@ static u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle,
        return tqp->index;
 }
 
-void hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
+int hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
 {
        struct hclge_vport *vport = hclge_get_vport(handle);
        struct hclge_dev *hdev = vport->back;
        int reset_try_times = 0;
        int reset_status;
        u16 queue_gid;
-       int ret;
-
-       if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
-               return;
+       int ret = 0;
 
        queue_gid = hclge_covert_handle_qid_global(handle, queue_id);
 
        ret = hclge_tqp_enable(hdev, queue_id, 0, false);
        if (ret) {
-               dev_warn(&hdev->pdev->dev, "Disable tqp fail, ret = %d\n", ret);
-               return;
+               dev_err(&hdev->pdev->dev, "Disable tqp fail, ret = %d\n", ret);
+               return ret;
        }
 
        ret = hclge_send_reset_tqp_cmd(hdev, queue_gid, true);
        if (ret) {
-               dev_warn(&hdev->pdev->dev,
-                        "Send reset tqp cmd fail, ret = %d\n", ret);
-               return;
+               dev_err(&hdev->pdev->dev,
+                       "Send reset tqp cmd fail, ret = %d\n", ret);
+               return ret;
        }
 
        reset_try_times = 0;
@@ -6144,16 +6144,16 @@ void hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
        }
 
        if (reset_try_times >= HCLGE_TQP_RESET_TRY_TIMES) {
-               dev_warn(&hdev->pdev->dev, "Reset TQP fail\n");
-               return;
+               dev_err(&hdev->pdev->dev, "Reset TQP fail\n");
+               return ret;
        }
 
        ret = hclge_send_reset_tqp_cmd(hdev, queue_gid, false);
-       if (ret) {
-               dev_warn(&hdev->pdev->dev,
-                        "Deassert the soft reset fail, ret = %d\n", ret);
-               return;
-       }
+       if (ret)
+               dev_err(&hdev->pdev->dev,
+                       "Deassert the soft reset fail, ret = %d\n", ret);
+
+       return ret;
 }
 
 void hclge_reset_vf_queue(struct hclge_vport *vport, u16 queue_id)
index e3dfd654eca9a1c4b1f0af7a90b29d91c725ca1b..0d92154042699c94a41410ab6dc3aa38437c9b3a 100644 (file)
@@ -778,7 +778,7 @@ int hclge_rss_init_hw(struct hclge_dev *hdev);
 void hclge_rss_indir_init_cfg(struct hclge_dev *hdev);
 
 void hclge_mbx_handler(struct hclge_dev *hdev);
-void hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id);
+int hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id);
 void hclge_reset_vf_queue(struct hclge_vport *vport, u16 queue_id);
 int hclge_cfg_flowctrl(struct hclge_dev *hdev);
 int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id);
index 04462a347a94075bd28453b6db9088d77ef586c9..f890022938d9a15a96e98ab2c48cea04fc0dc784 100644 (file)
@@ -400,6 +400,12 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
 
        /* handle all the mailbox requests in the queue */
        while (!hclge_cmd_crq_empty(&hdev->hw)) {
+               if (test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state)) {
+                       dev_warn(&hdev->pdev->dev,
+                                "command queue needs re-initializing\n");
+                       return;
+               }
+
                desc = &crq->desc[crq->next_to_use];
                req = (struct hclge_mbx_vf_to_pf_cmd *)desc->data;
 
index 24b1f2a0c32afc328cbdc82b67d5adb5fae916cc..03018638f701b3f2824bb153864e13cf929bd06c 100644 (file)
@@ -52,7 +52,7 @@ static int hclge_mdio_write(struct mii_bus *bus, int phyid, int regnum,
        struct hclge_desc desc;
        int ret;
 
-       if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
+       if (test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state))
                return 0;
 
        hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, false);
@@ -90,7 +90,7 @@ static int hclge_mdio_read(struct mii_bus *bus, int phyid, int regnum)
        struct hclge_desc desc;
        int ret;
 
-       if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
+       if (test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state))
                return 0;
 
        hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, true);
index e0a86a58342c28dab0a6e044895f9c4635f46207..085edb945389c5fc8aba0d94f8ffe2c74f070f24 100644 (file)
@@ -925,12 +925,12 @@ static int hclgevf_cmd_set_promisc_mode(struct hclgevf_dev *hdev,
        return status;
 }
 
-static void hclgevf_set_promisc_mode(struct hnae3_handle *handle,
-                                    bool en_uc_pmc, bool en_mc_pmc)
+static int hclgevf_set_promisc_mode(struct hnae3_handle *handle,
+                                   bool en_uc_pmc, bool en_mc_pmc)
 {
        struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
 
-       hclgevf_cmd_set_promisc_mode(hdev, en_uc_pmc, en_mc_pmc);
+       return hclgevf_cmd_set_promisc_mode(hdev, en_uc_pmc, en_mc_pmc);
 }
 
 static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, int tqp_id,
@@ -1080,7 +1080,7 @@ static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
                                    1, false, NULL, 0);
 }
 
-static void hclgevf_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
+static int hclgevf_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
 {
        struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
        u8 msg_data[2];
@@ -1091,10 +1091,10 @@ static void hclgevf_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
        /* disable vf queue before send queue reset msg to PF */
        ret = hclgevf_tqp_enable(hdev, queue_id, 0, false);
        if (ret)
-               return;
+               return ret;
 
-       hclgevf_send_mbx_msg(hdev, HCLGE_MBX_QUEUE_RESET, 0, msg_data,
-                            2, true, NULL, 0);
+       return hclgevf_send_mbx_msg(hdev, HCLGE_MBX_QUEUE_RESET, 0, msg_data,
+                                   2, true, NULL, 0);
 }
 
 static int hclgevf_notify_client(struct hclgevf_dev *hdev,
@@ -1170,6 +1170,8 @@ static int hclgevf_reset(struct hclgevf_dev *hdev)
        /* bring down the nic to stop any ongoing TX/RX */
        hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
 
+       rtnl_unlock();
+
        /* check if VF could successfully fetch the hardware reset completion
         * status from the hardware
         */
@@ -1181,12 +1183,15 @@ static int hclgevf_reset(struct hclgevf_dev *hdev)
                        ret);
 
                dev_warn(&hdev->pdev->dev, "VF reset failed, disabling VF!\n");
+               rtnl_lock();
                hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT);
 
                rtnl_unlock();
                return ret;
        }
 
+       rtnl_lock();
+
        /* now, re-initialize the nic client and ae device*/
        ret = hclgevf_reset_stack(hdev);
        if (ret)
index 967c993d5303ab87420c691abd1af11f4411560a..bbf9bdd0ee3e74246d558b4caa3cb3cfeb453e58 100644 (file)
@@ -532,7 +532,7 @@ void hinic_task_set_inner_l3(struct hinic_sq_task *task,
 }
 
 void hinic_task_set_tunnel_l4(struct hinic_sq_task *task,
-                             enum hinic_l4_offload_type l4_type,
+                             enum hinic_l4_tunnel_type l4_type,
                              u32 tunnel_len)
 {
        task->pkt_info2 |= HINIC_SQ_TASK_INFO2_SET(l4_type, TUNNEL_L4TYPE) |
index a0dc63a4bfc7ab9bd724fda8899650b37b4785e5..038522e202b6f616db097fbc4f0ef6d05755e682 100644 (file)
@@ -160,7 +160,7 @@ void hinic_task_set_inner_l3(struct hinic_sq_task *task,
                             u32 network_len);
 
 void hinic_task_set_tunnel_l4(struct hinic_sq_task *task,
-                             enum hinic_l4_offload_type l4_type,
+                             enum hinic_l4_tunnel_type l4_type,
                              u32 tunnel_len);
 
 void hinic_set_cs_inner_l4(struct hinic_sq_task *task,
index fd3373d82a9e94c7850631b88c6b4c7c8940f1a1..59e1bc0f609ee3399130eec23e330111b2dc64e6 100644 (file)
@@ -200,6 +200,15 @@ config IXGBE_DCB
 
          If unsure, say N.
 
+config IXGBE_IPSEC
+       bool "IPSec XFRM cryptography-offload acceleration"
+       depends on IXGBE
+       depends on XFRM_OFFLOAD
+       default y
+       select XFRM_ALGO
+       ---help---
+         Enable support for IPSec offload in ixgbe.ko
+
 config IXGBEVF
        tristate "Intel(R) 10GbE PCI Express Virtual Function Ethernet support"
        depends on PCI_MSI
@@ -217,6 +226,15 @@ config IXGBEVF
          will be called ixgbevf.  MSI-X interrupt support is required
          for this driver to work correctly.
 
+config IXGBEVF_IPSEC
+       bool "IPSec XFRM cryptography-offload acceleration"
+       depends on IXGBEVF
+       depends on XFRM_OFFLOAD
+       default y
+       select XFRM_ALGO
+       ---help---
+         Enable support for IPSec offload in ixgbevf.ko
+
 config I40E
        tristate "Intel(R) Ethernet Controller XL710 Family support"
        imply PTP_1588_CLOCK
index e707d717012faa997a127687ce45d54b27b9e3eb..5d4f1761dc0c2ef0613757ff5bfedb214f9ca79f 100644 (file)
@@ -244,7 +244,8 @@ process_mbx:
                }
 
                /* guarantee we have free space in the SM mailbox */
-               if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) {
+               if (hw->mbx.state == FM10K_STATE_OPEN &&
+                   !hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) {
                        /* keep track of how many times this occurs */
                        interface->hw_sm_mbx_full++;
 
@@ -302,6 +303,28 @@ void fm10k_iov_suspend(struct pci_dev *pdev)
        }
 }
 
+static void fm10k_mask_aer_comp_abort(struct pci_dev *pdev)
+{
+       u32 err_mask;
+       int pos;
+
+       pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
+       if (!pos)
+               return;
+
+       /* Mask the completion abort bit in the ERR_UNCOR_MASK register,
+        * preventing the device from reporting these errors to the upstream
+        * PCIe root device. This avoids bringing down platforms which upgrade
+        * non-fatal completer aborts into machine check exceptions. Completer
+        * aborts can occur whenever a VF reads a queue it doesn't own.
+        */
+       pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_MASK, &err_mask);
+       err_mask |= PCI_ERR_UNC_COMP_ABORT;
+       pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_MASK, err_mask);
+
+       mmiowb();
+}
+
 int fm10k_iov_resume(struct pci_dev *pdev)
 {
        struct fm10k_intfc *interface = pci_get_drvdata(pdev);
@@ -317,6 +340,12 @@ int fm10k_iov_resume(struct pci_dev *pdev)
        if (!iov_data)
                return -ENOMEM;
 
+       /* Lower severity of completer abort error reporting as
+        * the VFs can trigger this any time they read a queue
+        * that they don't own.
+        */
+       fm10k_mask_aer_comp_abort(pdev);
+
        /* allocate hardware resources for the VFs */
        hw->iov.ops.assign_resources(hw, num_vfs, num_vfs);
 
@@ -460,20 +489,6 @@ void fm10k_iov_disable(struct pci_dev *pdev)
        fm10k_iov_free_data(pdev);
 }
 
-static void fm10k_disable_aer_comp_abort(struct pci_dev *pdev)
-{
-       u32 err_sev;
-       int pos;
-
-       pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
-       if (!pos)
-               return;
-
-       pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &err_sev);
-       err_sev &= ~PCI_ERR_UNC_COMP_ABORT;
-       pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, err_sev);
-}
-
 int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs)
 {
        int current_vfs = pci_num_vf(pdev);
@@ -495,12 +510,6 @@ int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs)
 
        /* allocate VFs if not already allocated */
        if (num_vfs && num_vfs != current_vfs) {
-               /* Disable completer abort error reporting as
-                * the VFs can trigger this any time they read a queue
-                * that they don't own.
-                */
-               fm10k_disable_aer_comp_abort(pdev);
-
                err = pci_enable_sriov(pdev, num_vfs);
                if (err) {
                        dev_err(&pdev->dev,
index 503bbc0177922c45804bce8280452c7942663bf9..5b2a50e5798f755c4e360d5fec2d13c65f1ea2a1 100644 (file)
@@ -11,7 +11,7 @@
 
 #include "fm10k.h"
 
-#define DRV_VERSION    "0.23.4-k"
+#define DRV_VERSION    "0.26.1-k"
 #define DRV_SUMMARY    "Intel(R) Ethernet Switch Host Interface Driver"
 const char fm10k_driver_version[] = DRV_VERSION;
 char fm10k_driver_name[] = "fm10k";
index 02345d3813036cac695d675ae24b9a02aea8510c..e49fb51d36133ff49c6b11646f895b1b7dc8ee61 100644 (file)
@@ -23,6 +23,8 @@ static const struct fm10k_info *fm10k_info_tbl[] = {
  */
 static const struct pci_device_id fm10k_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, FM10K_DEV_ID_PF), fm10k_device_pf },
+       { PCI_VDEVICE(INTEL, FM10K_DEV_ID_SDI_FM10420_QDA2), fm10k_device_pf },
+       { PCI_VDEVICE(INTEL, FM10K_DEV_ID_SDI_FM10420_DA2), fm10k_device_pf },
        { PCI_VDEVICE(INTEL, FM10K_DEV_ID_VF), fm10k_device_vf },
        /* required last entry */
        { 0, }
index 3e608e493f9df6bf921383f65be2139ad38cb288..9fb9fca375e3f69282c757fb3ae665a18982e8f3 100644 (file)
@@ -15,6 +15,8 @@ struct fm10k_hw;
 
 #define FM10K_DEV_ID_PF                        0x15A4
 #define FM10K_DEV_ID_VF                        0x15A5
+#define FM10K_DEV_ID_SDI_FM10420_QDA2  0x15D0
+#define FM10K_DEV_ID_SDI_FM10420_DA2   0x15D5
 
 #define FM10K_MAX_QUEUES               256
 #define FM10K_MAX_QUEUES_PF            128
index 81b0e1f8d14b6d041e4a8668b0f20955b9633e55..ac5698ed0b11194a30496b4bb4f11cafb26938c5 100644 (file)
@@ -3674,7 +3674,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
                dev_err(&pf->pdev->dev, "Invalid message from VF %d, opcode %d, len %d\n",
                        local_vf_id, v_opcode, msglen);
                switch (ret) {
-               case VIRTCHNL_ERR_PARAM:
+               case VIRTCHNL_STATUS_ERR_PARAM:
                        return -EPERM;
                default:
                        return -EINVAL;
index 9f4d700e09df33cb5d3e17576859a563f9c6c52c..29ced6b74d364632113e9674f8d005257e548411 100644 (file)
  *
  * The 40 bit 82580 SYSTIM overflows every
  *   2^40 * 10^-9 /  60  = 18.3 minutes.
+ *
+ * SYSTIM is converted to real time using a timecounter. As
+ * timecounter_cyc2time() allows old timestamps, the timecounter
+ * needs to be updated at least once per half of the SYSTIM interval.
+ * Scheduling of delayed work is not very accurate, so we aim for 8
+ * minutes to be sure the actual interval is shorter than 9.16 minutes.
  */
 
-#define IGB_SYSTIM_OVERFLOW_PERIOD     (HZ * 60 * 9)
+#define IGB_SYSTIM_OVERFLOW_PERIOD     (HZ * 60 * 8)
 #define IGB_PTP_TX_TIMEOUT             (HZ * 15)
 #define INCPERIOD_82576                        BIT(E1000_TIMINCA_16NS_SHIFT)
 #define INCVALUE_82576_MASK            GENMASK(E1000_TIMINCA_16NS_SHIFT - 1, 0)
index ca6b0c458e4a50eca96aea8ace64806cbf66aa45..4fb0d9e3f2da21db5acf17dbf5b9c091502db442 100644 (file)
@@ -17,4 +17,4 @@ ixgbe-$(CONFIG_IXGBE_DCB) +=  ixgbe_dcb.o ixgbe_dcb_82598.o \
 ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o
 ixgbe-$(CONFIG_DEBUG_FS) += ixgbe_debugfs.o
 ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o
-ixgbe-$(CONFIG_XFRM_OFFLOAD) += ixgbe_ipsec.o
+ixgbe-$(CONFIG_IXGBE_IPSEC) += ixgbe_ipsec.o
index ec1b87cc44100904bf7b486692bc1d06b256fc80..143bdd5ee2a088a738a5fb381e33c141d774e633 100644 (file)
@@ -769,9 +769,9 @@ struct ixgbe_adapter {
 #define IXGBE_RSS_KEY_SIZE     40  /* size of RSS Hash Key in bytes */
        u32 *rss_key;
 
-#ifdef CONFIG_XFRM_OFFLOAD
+#ifdef CONFIG_IXGBE_IPSEC
        struct ixgbe_ipsec *ipsec;
-#endif /* CONFIG_XFRM_OFFLOAD */
+#endif /* CONFIG_IXGBE_IPSEC */
 
        /* AF_XDP zero-copy */
        struct xdp_umem **xsk_umems;
@@ -1008,7 +1008,7 @@ void ixgbe_store_key(struct ixgbe_adapter *adapter);
 void ixgbe_store_reta(struct ixgbe_adapter *adapter);
 s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
                       u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
-#ifdef CONFIG_XFRM_OFFLOAD
+#ifdef CONFIG_IXGBE_IPSEC
 void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter);
 void ixgbe_stop_ipsec_offload(struct ixgbe_adapter *adapter);
 void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter);
@@ -1036,5 +1036,5 @@ static inline int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter,
                                        u32 *mbuf, u32 vf) { return -EACCES; }
 static inline int ixgbe_ipsec_vf_del_sa(struct ixgbe_adapter *adapter,
                                        u32 *mbuf, u32 vf) { return -EACCES; }
-#endif /* CONFIG_XFRM_OFFLOAD */
+#endif /* CONFIG_IXGBE_IPSEC */
 #endif /* _IXGBE_H_ */
index 0049a2becd7e7349db1cc6d7acf653489882277c..113b38e0defbf547920a5f2fadb63428e50e6dc1 100644 (file)
@@ -8694,7 +8694,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 
 #endif /* IXGBE_FCOE */
 
-#ifdef CONFIG_XFRM_OFFLOAD
+#ifdef CONFIG_IXGBE_IPSEC
        if (skb->sp && !ixgbe_ipsec_tx(tx_ring, first, &ipsec_tx))
                goto out_drop;
 #endif
@@ -10190,7 +10190,7 @@ ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
         * the TSO, so it's the exception.
         */
        if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID)) {
-#ifdef CONFIG_XFRM_OFFLOAD
+#ifdef CONFIG_IXGBE_IPSEC
                if (!skb->sp)
 #endif
                        features &= ~NETIF_F_TSO;
@@ -10883,7 +10883,7 @@ skip_sriov:
        if (hw->mac.type >= ixgbe_mac_82599EB)
                netdev->features |= NETIF_F_SCTP_CRC;
 
-#ifdef CONFIG_XFRM_OFFLOAD
+#ifdef CONFIG_IXGBE_IPSEC
 #define IXGBE_ESP_FEATURES     (NETIF_F_HW_ESP | \
                                 NETIF_F_HW_ESP_TX_CSUM | \
                                 NETIF_F_GSO_ESP)
index af25a8fffeb8ba4f19a79f11f6d96f3d7f252047..5dacfc870259881f8746a72546f5c410f4bf06f6 100644 (file)
@@ -722,8 +722,10 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
                        ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
                                        adapter->default_up, vf);
 
-               if (vfinfo->spoofchk_enabled)
+               if (vfinfo->spoofchk_enabled) {
                        hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
+                       hw->mac.ops.set_mac_anti_spoofing(hw, true, vf);
+               }
        }
 
        /* reset multicast table array for vf */
index 297d0f0858b59eba441397d0f6924558e7836768..186a4bb24fdea58a483f161858333313c34373ae 100644 (file)
@@ -10,5 +10,5 @@ ixgbevf-objs := vf.o \
                 mbx.o \
                 ethtool.o \
                 ixgbevf_main.o
-ixgbevf-$(CONFIG_XFRM_OFFLOAD) += ipsec.o
+ixgbevf-$(CONFIG_IXGBEVF_IPSEC) += ipsec.o
 
index e399e1c0c54ab178648632cbe187e50d7bd5f0f3..ecab686574b65d23dd7840d840b26c2c002338f9 100644 (file)
@@ -459,7 +459,7 @@ int ethtool_ioctl(struct ifreq *ifr);
 
 extern void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector);
 
-#ifdef CONFIG_XFRM_OFFLOAD
+#ifdef CONFIG_IXGBEVF_IPSEC
 void ixgbevf_init_ipsec_offload(struct ixgbevf_adapter *adapter);
 void ixgbevf_stop_ipsec_offload(struct ixgbevf_adapter *adapter);
 void ixgbevf_ipsec_restore(struct ixgbevf_adapter *adapter);
@@ -482,7 +482,7 @@ static inline int ixgbevf_ipsec_tx(struct ixgbevf_ring *tx_ring,
                                   struct ixgbevf_tx_buffer *first,
                                   struct ixgbevf_ipsec_tx_data *itd)
 { return 0; }
-#endif /* CONFIG_XFRM_OFFLOAD */
+#endif /* CONFIG_IXGBEVF_IPSEC */
 
 void ixgbe_napi_add_all(struct ixgbevf_adapter *adapter);
 void ixgbe_napi_del_all(struct ixgbevf_adapter *adapter);
index 98707ee11d72667a3ba83212ea301eeb27ba09d7..5e47ede7e832001a17575616fc0ab337d4d2f7fe 100644 (file)
@@ -4150,7 +4150,7 @@ static int ixgbevf_xmit_frame_ring(struct sk_buff *skb,
        first->tx_flags = tx_flags;
        first->protocol = vlan_get_protocol(skb);
 
-#ifdef CONFIG_XFRM_OFFLOAD
+#ifdef CONFIG_IXGBEVF_IPSEC
        if (skb->sp && !ixgbevf_ipsec_tx(tx_ring, first, &ipsec_tx))
                goto out_drop;
 #endif
index 176c6b56fdccda6bc65f9c78f2b29fa88c6ed867..398328f107437e2f7c17e5fe54d0d8f36d83f058 100644 (file)
@@ -796,6 +796,7 @@ struct mvpp2_queue_vector {
        int nrxqs;
        u32 pending_cause_rx;
        struct mvpp2_port *port;
+       struct cpumask *mask;
 };
 
 struct mvpp2_port {
index 14f9679c957c6afd04929ea23ccd80afd19650ab..7a37a37e3fb347d90679db2ca16231597ba9afad 100644 (file)
@@ -3298,24 +3298,30 @@ static int mvpp2_irqs_init(struct mvpp2_port *port)
        for (i = 0; i < port->nqvecs; i++) {
                struct mvpp2_queue_vector *qv = port->qvecs + i;
 
-               if (qv->type == MVPP2_QUEUE_VECTOR_PRIVATE)
+               if (qv->type == MVPP2_QUEUE_VECTOR_PRIVATE) {
+                       qv->mask = kzalloc(cpumask_size(), GFP_KERNEL);
+                       if (!qv->mask) {
+                               err = -ENOMEM;
+                               goto err;
+                       }
+
                        irq_set_status_flags(qv->irq, IRQ_NO_BALANCING);
+               }
 
                err = request_irq(qv->irq, mvpp2_isr, 0, port->dev->name, qv);
                if (err)
                        goto err;
 
                if (qv->type == MVPP2_QUEUE_VECTOR_PRIVATE) {
-                       unsigned long mask = 0;
                        unsigned int cpu;
 
                        for_each_present_cpu(cpu) {
                                if (mvpp2_cpu_to_thread(port->priv, cpu) ==
                                    qv->sw_thread_id)
-                                       mask |= BIT(cpu);
+                                       cpumask_set_cpu(cpu, qv->mask);
                        }
 
-                       irq_set_affinity_hint(qv->irq, to_cpumask(&mask));
+                       irq_set_affinity_hint(qv->irq, qv->mask);
                }
        }
 
@@ -3325,6 +3331,8 @@ err:
                struct mvpp2_queue_vector *qv = port->qvecs + i;
 
                irq_set_affinity_hint(qv->irq, NULL);
+               kfree(qv->mask);
+               qv->mask = NULL;
                free_irq(qv->irq, qv);
        }
 
@@ -3339,6 +3347,8 @@ static void mvpp2_irqs_deinit(struct mvpp2_port *port)
                struct mvpp2_queue_vector *qv = port->qvecs + i;
 
                irq_set_affinity_hint(qv->irq, NULL);
+               kfree(qv->mask);
+               qv->mask = NULL;
                irq_clear_status_flags(qv->irq, IRQ_NO_BALANCING);
                free_irq(qv->irq, qv);
        }
index 5a6d0919533d6e0e619927abd753c5d07ed95dac..db00bf1c23f5ad31d64652ddc8bee32e2e7534c8 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/vmalloc.h>
 #include <linux/irq.h>
 
+#include <net/ip.h>
 #if IS_ENABLED(CONFIG_IPV6)
 #include <net/ip6_checksum.h>
 #endif
index 94224c22ecc310a87b6715051e335446f29bec03..79638dcbae78395fb723c9bf3fa877e7a42d91cd 100644 (file)
@@ -713,43 +713,15 @@ static inline void mlx5e_enable_ecn(struct mlx5e_rq *rq, struct sk_buff *skb)
        rq->stats->ecn_mark += !!rc;
 }
 
-static __be32 mlx5e_get_fcs(struct sk_buff *skb)
+static u32 mlx5e_get_fcs(const struct sk_buff *skb)
 {
-       int last_frag_sz, bytes_in_prev, nr_frags;
-       u8 *fcs_p1, *fcs_p2;
-       skb_frag_t *last_frag;
-       __be32 fcs_bytes;
+       const void *fcs_bytes;
+       u32 _fcs_bytes;
 
-       if (!skb_is_nonlinear(skb))
-               return *(__be32 *)(skb->data + skb->len - ETH_FCS_LEN);
+       fcs_bytes = skb_header_pointer(skb, skb->len - ETH_FCS_LEN,
+                                      ETH_FCS_LEN, &_fcs_bytes);
 
-       nr_frags = skb_shinfo(skb)->nr_frags;
-       last_frag = &skb_shinfo(skb)->frags[nr_frags - 1];
-       last_frag_sz = skb_frag_size(last_frag);
-
-       /* If all FCS data is in last frag */
-       if (last_frag_sz >= ETH_FCS_LEN)
-               return *(__be32 *)(skb_frag_address(last_frag) +
-                                  last_frag_sz - ETH_FCS_LEN);
-
-       fcs_p2 = (u8 *)skb_frag_address(last_frag);
-       bytes_in_prev = ETH_FCS_LEN - last_frag_sz;
-
-       /* Find where the other part of the FCS is - Linear or another frag */
-       if (nr_frags == 1) {
-               fcs_p1 = skb_tail_pointer(skb);
-       } else {
-               skb_frag_t *prev_frag = &skb_shinfo(skb)->frags[nr_frags - 2];
-
-               fcs_p1 = skb_frag_address(prev_frag) +
-                           skb_frag_size(prev_frag);
-       }
-       fcs_p1 -= bytes_in_prev;
-
-       memcpy(&fcs_bytes, fcs_p1, bytes_in_prev);
-       memcpy(((u8 *)&fcs_bytes) + bytes_in_prev, fcs_p2, last_frag_sz);
-
-       return fcs_bytes;
+       return __get_unaligned_cpu32(fcs_bytes);
 }
 
 static u8 get_ip_proto(struct sk_buff *skb, __be16 proto)
@@ -797,8 +769,9 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
                                                 network_depth - ETH_HLEN,
                                                 skb->csum);
                if (unlikely(netdev->features & NETIF_F_RXFCS))
-                       skb->csum = csum_add(skb->csum,
-                                            (__force __wsum)mlx5e_get_fcs(skb));
+                       skb->csum = csum_block_add(skb->csum,
+                                                  (__force __wsum)mlx5e_get_fcs(skb),
+                                                  skb->len - ETH_FCS_LEN);
                stats->csum_complete++;
                return;
        }
index 937d0ace699a7eeb4e04af3bf54eebde5dd5d459..30f751e696980d727a86200e1748adda13bb8a22 100644 (file)
@@ -943,8 +943,8 @@ static int mlxsw_devlink_core_bus_device_reload(struct devlink *devlink,
                                             mlxsw_core->bus,
                                             mlxsw_core->bus_priv, true,
                                             devlink);
-       if (err)
-               mlxsw_core->reload_fail = true;
+       mlxsw_core->reload_fail = !!err;
+
        return err;
 }
 
@@ -1083,8 +1083,15 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
 {
        struct devlink *devlink = priv_to_devlink(mlxsw_core);
 
-       if (mlxsw_core->reload_fail)
-               goto reload_fail;
+       if (mlxsw_core->reload_fail) {
+               if (!reload)
+                       /* Only the parts that were not de-initialized in the
+                        * failed reload attempt need to be de-initialized.
+                        */
+                       goto reload_fail_deinit;
+               else
+                       return;
+       }
 
        if (mlxsw_core->driver->fini)
                mlxsw_core->driver->fini(mlxsw_core);
@@ -1098,9 +1105,12 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
        if (!reload)
                devlink_resources_unregister(devlink, NULL);
        mlxsw_core->bus->fini(mlxsw_core->bus_priv);
-       if (reload)
-               return;
-reload_fail:
+
+       return;
+
+reload_fail_deinit:
+       devlink_unregister(devlink);
+       devlink_resources_unregister(devlink, NULL);
        devlink_free(devlink);
 }
 EXPORT_SYMBOL(mlxsw_core_bus_device_unregister);
index 32cb6718bb173ff966639a2ffc63374e457b586a..db3d2790aeecf9c3b93fe4c66df7856d637dfc70 100644 (file)
@@ -3284,7 +3284,7 @@ static inline void mlxsw_reg_qtct_pack(char *payload, u8 local_port,
  * Configures the ETS elements.
  */
 #define MLXSW_REG_QEEC_ID 0x400D
-#define MLXSW_REG_QEEC_LEN 0x1C
+#define MLXSW_REG_QEEC_LEN 0x20
 
 MLXSW_REG_DEFINE(qeec, MLXSW_REG_QEEC_ID, MLXSW_REG_QEEC_LEN);
 
@@ -3326,6 +3326,15 @@ MLXSW_ITEM32(reg, qeec, element_index, 0x04, 0, 8);
  */
 MLXSW_ITEM32(reg, qeec, next_element_index, 0x08, 0, 8);
 
+/* reg_qeec_mise
+ * Min shaper configuration enable. Enables configuration of the min
+ * shaper on this ETS element
+ * 0 - Disable
+ * 1 - Enable
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, qeec, mise, 0x0C, 31, 1);
+
 enum {
        MLXSW_REG_QEEC_BYTES_MODE,
        MLXSW_REG_QEEC_PACKETS_MODE,
@@ -3342,6 +3351,17 @@ enum {
  */
 MLXSW_ITEM32(reg, qeec, pb, 0x0C, 28, 1);
 
+/* The smallest permitted min shaper rate. */
+#define MLXSW_REG_QEEC_MIS_MIN 200000          /* Kbps */
+
+/* reg_qeec_min_shaper_rate
+ * Min shaper information rate.
+ * For CPU port, can only be configured for port hierarchy.
+ * When in bytes mode, value is specified in units of 1000bps.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, qeec, min_shaper_rate, 0x0C, 0, 28);
+
 /* reg_qeec_mase
  * Max shaper configuration enable. Enables configuration of the max
  * shaper on this ETS element.
index 8a4983adae940a08b4d4d5ec39637522fb1bea46..a2df12b79f8e915702323f9258972260135c094c 100644 (file)
@@ -2740,6 +2740,21 @@ int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port,
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl);
 }
 
+static int mlxsw_sp_port_min_bw_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                   enum mlxsw_reg_qeec_hr hr, u8 index,
+                                   u8 next_index, u32 minrate)
+{
+       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+       char qeec_pl[MLXSW_REG_QEEC_LEN];
+
+       mlxsw_reg_qeec_pack(qeec_pl, mlxsw_sp_port->local_port, hr, index,
+                           next_index);
+       mlxsw_reg_qeec_mise_set(qeec_pl, true);
+       mlxsw_reg_qeec_min_shaper_rate_set(qeec_pl, minrate);
+
+       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qeec), qeec_pl);
+}
+
 int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port,
                              u8 switch_prio, u8 tclass)
 {
@@ -2817,6 +2832,16 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port)
                        return err;
        }
 
+       /* Configure the min shaper for multicast TCs. */
+       for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+               err = mlxsw_sp_port_min_bw_set(mlxsw_sp_port,
+                                              MLXSW_REG_QEEC_HIERARCY_TC,
+                                              i + 8, i,
+                                              MLXSW_REG_QEEC_MIS_MIN);
+               if (err)
+                       return err;
+       }
+
        /* Map all priorities to traffic class 0. */
        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
                err = mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i, 0);
index bc60d7a8b49d764b4066c50bc808963c52c27950..739a51f0a366f421074a5ac31a6ec887898fb76a 100644 (file)
@@ -2661,8 +2661,6 @@ static void mlxsw_sp_switchdev_bridge_fdb_event_work(struct work_struct *work)
                break;
        case SWITCHDEV_FDB_DEL_TO_DEVICE:
                fdb_info = &switchdev_work->fdb_info;
-               if (!fdb_info->added_by_user)
-                       break;
                mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
                break;
        case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
index b72ef171477e0ec6dfba85c09815226a584ec30b..bdd351597b55251b35e17daf43aeff643912e33b 100644 (file)
@@ -243,7 +243,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
  */
 int stmmac_mdio_reset(struct mii_bus *bus)
 {
-#if defined(CONFIG_STMMAC_PLATFORM)
+#if IS_ENABLED(CONFIG_STMMAC_PLATFORM)
        struct net_device *ndev = bus->priv;
        struct stmmac_priv *priv = netdev_priv(ndev);
        unsigned int mii_address = priv->hw->mii.addr;
index 1e81f8144c0d6f2e36027863df7e3dab2ec0d2f6..ce259ec9f990078302041523f654c4f638c754bf 100644 (file)
@@ -99,7 +99,7 @@ static const struct acpi_device_id chromeos_tbmc_acpi_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, chromeos_tbmc_acpi_device_ids);
 
-static const SIMPLE_DEV_PM_OPS(chromeos_tbmc_pm_ops, NULL,
+static SIMPLE_DEV_PM_OPS(chromeos_tbmc_pm_ops, NULL,
                chromeos_tbmc_resume);
 
 static struct acpi_driver chromeos_tbmc_driver = {
index 31c8b8c49e458f5be62b9aec0dbedd436785f84c..e1b75775cd4a12867b1b3b4566140605564c7085 100644 (file)
 #include <linux/dmi.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/mfd/cros_ec.h>
 #include <linux/mfd/cros_ec_commands.h>
-#include <linux/mfd/cros_ec_lpc_reg.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/printk.h>
 #include <linux/suspend.h>
 
+#include "cros_ec_lpc_reg.h"
+
 #define DRV_NAME "cros_ec_lpcs"
 #define ACPI_DRV_NAME "GOOG0004"
 
@@ -248,7 +250,7 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
        acpi_status status;
        struct cros_ec_device *ec_dev;
        u8 buf[2];
-       int ret;
+       int irq, ret;
 
        if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
                                 dev_name(dev))) {
@@ -287,6 +289,18 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
                           sizeof(struct ec_response_get_protocol_info);
        ec_dev->dout_size = sizeof(struct ec_host_request);
 
+       /*
+        * Some boards do not have an IRQ allotted for cros_ec_lpc,
+        * which makes ENXIO an expected (and safe) scenario.
+        */
+       irq = platform_get_irq(pdev, 0);
+       if (irq > 0)
+               ec_dev->irq = irq;
+       else if (irq != -ENXIO) {
+               dev_err(dev, "couldn't retrieve IRQ number (%d)\n", irq);
+               return irq;
+       }
+
        ret = cros_ec_register(ec_dev);
        if (ret) {
                dev_err(dev, "couldn't register ec_dev (%d)\n", ret);
index 2eda2c2fc210fb3dc95d147b75012fb7a013b4bf..c4edfa83e493062fcd65363e4733387562211ef5 100644 (file)
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/mfd/cros_ec_commands.h>
-#include <linux/mfd/cros_ec_lpc_mec.h>
 #include <linux/mutex.h>
 #include <linux/types.h>
 
+#include "cros_ec_lpc_mec.h"
+
 /*
  * This mutex must be held while accessing the EMI unit. We can't rely on the
  * EC mutex because memmap data may be accessed without it being held.
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.h b/drivers/platform/chrome/cros_ec_lpc_mec.h
new file mode 100644 (file)
index 0000000..105068c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2016 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#ifndef __CROS_EC_LPC_MEC_H
+#define __CROS_EC_LPC_MEC_H
+
+#include <linux/mfd/cros_ec_commands.h>
+
+enum cros_ec_lpc_mec_emi_access_mode {
+       /* 8-bit access */
+       ACCESS_TYPE_BYTE = 0x0,
+       /* 16-bit access */
+       ACCESS_TYPE_WORD = 0x1,
+       /* 32-bit access */
+       ACCESS_TYPE_LONG = 0x2,
+       /*
+        * 32-bit access, read or write of MEC_EMI_EC_DATA_B3 causes the
+        * EC data register to be incremented.
+        */
+       ACCESS_TYPE_LONG_AUTO_INCREMENT = 0x3,
+};
+
+enum cros_ec_lpc_mec_io_type {
+       MEC_IO_READ,
+       MEC_IO_WRITE,
+};
+
+/* Access IO ranges 0x800 thru 0x9ff using EMI interface instead of LPC */
+#define MEC_EMI_RANGE_START EC_HOST_CMD_REGION0
+#define MEC_EMI_RANGE_END   (EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE)
+
+/* EMI registers are relative to base */
+#define MEC_EMI_BASE 0x800
+#define MEC_EMI_HOST_TO_EC (MEC_EMI_BASE + 0)
+#define MEC_EMI_EC_TO_HOST (MEC_EMI_BASE + 1)
+#define MEC_EMI_EC_ADDRESS_B0 (MEC_EMI_BASE + 2)
+#define MEC_EMI_EC_ADDRESS_B1 (MEC_EMI_BASE + 3)
+#define MEC_EMI_EC_DATA_B0 (MEC_EMI_BASE + 4)
+#define MEC_EMI_EC_DATA_B1 (MEC_EMI_BASE + 5)
+#define MEC_EMI_EC_DATA_B2 (MEC_EMI_BASE + 6)
+#define MEC_EMI_EC_DATA_B3 (MEC_EMI_BASE + 7)
+
+/*
+ * cros_ec_lpc_mec_init
+ *
+ * Initialize MEC I/O.
+ */
+void cros_ec_lpc_mec_init(void);
+
+/*
+ * cros_ec_lpc_mec_destroy
+ *
+ * Cleanup MEC I/O.
+ */
+void cros_ec_lpc_mec_destroy(void);
+
+/**
+ * cros_ec_lpc_io_bytes_mec - Read / write bytes to MEC EMI port
+ *
+ * @io_type: MEC_IO_READ or MEC_IO_WRITE, depending on request
+ * @offset:  Base read / write address
+ * @length:  Number of bytes to read / write
+ * @buf:     Destination / source buffer
+ *
+ * @return 8-bit checksum of all bytes read / written
+ */
+u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
+                           unsigned int offset, unsigned int length, u8 *buf);
+
+#endif /* __CROS_EC_LPC_MEC_H */
index dcc7a3e30604bb60ffc3a550efa7877e01998921..fc23d535c404e32c773faf0e61a854d0fa4eeaaa 100644 (file)
@@ -24,7 +24,8 @@
 #include <linux/io.h>
 #include <linux/mfd/cros_ec.h>
 #include <linux/mfd/cros_ec_commands.h>
-#include <linux/mfd/cros_ec_lpc_mec.h>
+
+#include "cros_ec_lpc_mec.h"
 
 static u8 lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest)
 {
diff --git a/drivers/platform/chrome/cros_ec_lpc_reg.h b/drivers/platform/chrome/cros_ec_lpc_reg.h
new file mode 100644 (file)
index 0000000..1c12c38
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller
+ *
+ * Copyright (C) 2016 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#ifndef __CROS_EC_LPC_REG_H
+#define __CROS_EC_LPC_REG_H
+
+/**
+ * cros_ec_lpc_read_bytes - Read bytes from a given LPC-mapped address.
+ * Returns 8-bit checksum of all bytes read.
+ *
+ * @offset: Base read address
+ * @length: Number of bytes to read
+ * @dest: Destination buffer
+ */
+u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest);
+
+/**
+ * cros_ec_lpc_write_bytes - Write bytes to a given LPC-mapped address.
+ * Returns 8-bit checksum of all bytes written.
+ *
+ * @offset: Base write address
+ * @length: Number of bytes to write
+ * @msg: Write data buffer
+ */
+u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg);
+
+/**
+ * cros_ec_lpc_reg_init
+ *
+ * Initialize register I/O.
+ */
+void cros_ec_lpc_reg_init(void);
+
+/**
+ * cros_ec_lpc_reg_destroy
+ *
+ * Cleanup reg I/O.
+ */
+void cros_ec_lpc_reg_destroy(void);
+
+#endif /* __CROS_EC_LPC_REG_H */
index bdac939de223c9242385bfd77c23a343258fc687..54f6a40c75c69c667ac3d4591dde89fd99bac3be 100644 (file)
@@ -60,7 +60,10 @@ config ACERHDF
 
          After loading this driver the BIOS is still in control of the fan.
          To let the kernel handle the fan, do:
-         echo -n enabled > /sys/class/thermal/thermal_zone0/mode
+         echo -n enabled > /sys/class/thermal/thermal_zoneN/mode
+         where N=0,1,2... depending on the number of thermal nodes and the
+         detection order of your particular system.  The "type" parameter
+         in the same node directory will tell you if it is "acerhdf".
 
          For more information about this driver see
          <http://piie.net/files/acerhdf_README.txt>
@@ -105,6 +108,22 @@ config ASUS_LAPTOP
 
          If you have an ACPI-compatible ASUS laptop, say Y or M here.
 
+config DCDBAS
+       tristate "Dell Systems Management Base Driver"
+       depends on X86
+       help
+         The Dell Systems Management Base Driver provides a sysfs interface
+         for systems management software to perform System Management
+         Interrupts (SMIs) and Host Control Actions (system power cycle or
+         power off after OS shutdown) on certain Dell systems.
+
+         See <file:Documentation/dcdbas.txt> for more details on the driver
+         and the Dell systems on which Dell systems management software makes
+         use of this driver.
+
+         Say Y or M here to enable the driver for use by Dell systems
+         management software such as Dell OpenManage.
+
 #
 # The DELL_SMBIOS driver depends on ACPI_WMI and/or DCDBAS if those
 # backends are selected. The "depends" line prevents a configuration
@@ -227,6 +246,18 @@ config DELL_RBTN
          To compile this driver as a module, choose M here: the module will
          be called dell-rbtn.
 
+config DELL_RBU
+       tristate "BIOS update support for DELL systems via sysfs"
+       depends on X86
+       select FW_LOADER
+       select FW_LOADER_USER_HELPER
+       help
+        Say m if you want to have the option of updating the BIOS for your
+        DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
+        supporting application to communicate with the BIOS regarding the new
+        image for the image update to take effect.
+        See <file:Documentation/dell_rbu.txt> for more details on the driver.
+
 
 config FUJITSU_LAPTOP
        tristate "Fujitsu Laptop Extras"
@@ -336,6 +367,20 @@ config HP_WMI
         To compile this driver as a module, choose M here: the module will
         be called hp-wmi.
 
+config LG_LAPTOP
+       tristate "LG Laptop Extras"
+       depends on ACPI
+       depends on ACPI_WMI
+       depends on INPUT
+       select INPUT_SPARSEKMAP
+       select LEDS_CLASS
+       help
+        This driver adds support for hotkeys as well as control of keyboard
+        backlight, battery maximum charge level and various other ACPI
+        features.
+
+        If you have an LG Gram laptop, say Y or M here.
+
 config MSI_LAPTOP
        tristate "MSI Laptop Extras"
        depends on ACPI
@@ -1231,6 +1276,18 @@ config I2C_MULTI_INSTANTIATE
          To compile this driver as a module, choose M here: the module
          will be called i2c-multi-instantiate.
 
+config INTEL_ATOMISP2_PM
+       tristate "Intel AtomISP2 dummy / power-management driver"
+       depends on PCI && IOSF_MBI && PM
+       help
+         Power-management driver for Intel's Image Signal Processor found on
+         Bay and Cherry Trail devices. This dummy driver's sole purpose is to
+         turn the ISP off (put it in D3) to save power and to allow entering
+         of S0ix modes.
+
+         To compile this driver as a module, choose M here: the module
+         will be called intel_atomisp2_pm.
+
 endif # X86_PLATFORM_DEVICES
 
 config PMC_ATOM
index e6d1becf81ce8c6bd526e196b8c167576d0f5c6f..39ae94135406b69bb7cef9bcb8d24242382afe35 100644 (file)
@@ -9,9 +9,11 @@ obj-$(CONFIG_ASUS_NB_WMI)      += asus-nb-wmi.o
 obj-$(CONFIG_ASUS_WIRELESS)    += asus-wireless.o
 obj-$(CONFIG_EEEPC_LAPTOP)     += eeepc-laptop.o
 obj-$(CONFIG_EEEPC_WMI)                += eeepc-wmi.o
+obj-$(CONFIG_LG_LAPTOP)                += lg-laptop.o
 obj-$(CONFIG_MSI_LAPTOP)       += msi-laptop.o
 obj-$(CONFIG_ACPI_CMPC)                += classmate-laptop.o
 obj-$(CONFIG_COMPAL_LAPTOP)    += compal-laptop.o
+obj-$(CONFIG_DCDBAS)           += dcdbas.o
 obj-$(CONFIG_DELL_SMBIOS)      += dell-smbios.o
 dell-smbios-objs               := dell-smbios-base.o
 dell-smbios-$(CONFIG_DELL_SMBIOS_WMI)  += dell-smbios-wmi.o
@@ -23,6 +25,7 @@ obj-$(CONFIG_DELL_WMI_AIO)    += dell-wmi-aio.o
 obj-$(CONFIG_DELL_WMI_LED)     += dell-wmi-led.o
 obj-$(CONFIG_DELL_SMO8800)     += dell-smo8800.o
 obj-$(CONFIG_DELL_RBTN)                += dell-rbtn.o
+obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
 obj-$(CONFIG_ACER_WMI)         += acer-wmi.o
 obj-$(CONFIG_ACER_WIRELESS)    += acer-wireless.o
 obj-$(CONFIG_ACERHDF)          += acerhdf.o
@@ -92,3 +95,4 @@ obj-$(CONFIG_MLX_PLATFORM)    += mlx-platform.o
 obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
 obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN)    += intel_chtdc_ti_pwrbtn.o
 obj-$(CONFIG_I2C_MULTI_INSTANTIATE)    += i2c-multi-instantiate.o
+obj-$(CONFIG_INTEL_ATOMISP2_PM)        += intel_atomisp2_pm.o
index ea22591ee66feb9c08d8a831cbb822d8b9ab7591..50522422537886c26c849af01b18694be049387b 100644 (file)
@@ -86,6 +86,7 @@ static unsigned int interval = 10;
 static unsigned int fanon = 60000;
 static unsigned int fanoff = 53000;
 static unsigned int verbose;
+static unsigned int list_supported;
 static unsigned int fanstate = ACERHDF_FAN_AUTO;
 static char force_bios[16];
 static char force_product[16];
@@ -104,10 +105,12 @@ module_param(fanoff, uint, 0600);
 MODULE_PARM_DESC(fanoff, "Turn the fan off below this temperature");
 module_param(verbose, uint, 0600);
 MODULE_PARM_DESC(verbose, "Enable verbose dmesg output");
+module_param(list_supported, uint, 0600);
+MODULE_PARM_DESC(list_supported, "List supported models and BIOS versions");
 module_param_string(force_bios, force_bios, 16, 0);
-MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check");
+MODULE_PARM_DESC(force_bios, "Pretend system has this known supported BIOS version");
 module_param_string(force_product, force_product, 16, 0);
-MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check");
+MODULE_PARM_DESC(force_product, "Pretend system is this known supported model");
 
 /*
  * cmd_off: to switch the fan completely off and check if the fan is off
@@ -130,7 +133,7 @@ static const struct manualcmd mcmd = {
        .moff = 0xff,
 };
 
-/* BIOS settings */
+/* BIOS settings - only used during probe */
 struct bios_settings {
        const char *vendor;
        const char *product;
@@ -141,8 +144,18 @@ struct bios_settings {
        int mcmd_enable;
 };
 
+/* This could be a daughter struct in the above, but not worth the redirect */
+struct ctrl_settings {
+       u8 fanreg;
+       u8 tempreg;
+       struct fancmd cmd;
+       int mcmd_enable;
+};
+
+static struct ctrl_settings ctrl_cfg __read_mostly;
+
 /* Register addresses and values for different BIOS versions */
-static const struct bios_settings bios_tbl[] = {
+static const struct bios_settings bios_tbl[] __initconst = {
        /* AOA110 */
        {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00}, 0},
        {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00}, 0},
@@ -233,6 +246,7 @@ static const struct bios_settings bios_tbl[] = {
        {"Gateway", "LT31",   "v1.3201",  0x55, 0x58, {0x9e, 0x00}, 0},
        {"Gateway", "LT31",   "v1.3302",  0x55, 0x58, {0x9e, 0x00}, 0},
        {"Gateway", "LT31",   "v1.3303t", 0x55, 0x58, {0x9e, 0x00}, 0},
+       {"Gateway", "LT31",   "v1.3307",  0x55, 0x58, {0x9e, 0x00}, 0},
        /* Packard Bell */
        {"Packard Bell", "DOA150",  "v0.3104",  0x55, 0x58, {0x21, 0x00}, 0},
        {"Packard Bell", "DOA150",  "v0.3105",  0x55, 0x58, {0x20, 0x00}, 0},
@@ -256,8 +270,6 @@ static const struct bios_settings bios_tbl[] = {
        {"", "", "", 0, 0, {0, 0}, 0}
 };
 
-static const struct bios_settings *bios_cfg __read_mostly;
-
 /*
  * this struct is used to instruct thermal layer to use bang_bang instead of
  * default governor for acerhdf
@@ -270,7 +282,7 @@ static int acerhdf_get_temp(int *temp)
 {
        u8 read_temp;
 
-       if (ec_read(bios_cfg->tempreg, &read_temp))
+       if (ec_read(ctrl_cfg.tempreg, &read_temp))
                return -EINVAL;
 
        *temp = read_temp * 1000;
@@ -282,10 +294,10 @@ static int acerhdf_get_fanstate(int *state)
 {
        u8 fan;
 
-       if (ec_read(bios_cfg->fanreg, &fan))
+       if (ec_read(ctrl_cfg.fanreg, &fan))
                return -EINVAL;
 
-       if (fan != bios_cfg->cmd.cmd_off)
+       if (fan != ctrl_cfg.cmd.cmd_off)
                *state = ACERHDF_FAN_AUTO;
        else
                *state = ACERHDF_FAN_OFF;
@@ -306,13 +318,13 @@ static void acerhdf_change_fanstate(int state)
                state = ACERHDF_FAN_AUTO;
        }
 
-       cmd = (state == ACERHDF_FAN_OFF) ? bios_cfg->cmd.cmd_off
-                                        : bios_cfg->cmd.cmd_auto;
+       cmd = (state == ACERHDF_FAN_OFF) ? ctrl_cfg.cmd.cmd_off
+                                        : ctrl_cfg.cmd.cmd_auto;
        fanstate = state;
 
-       ec_write(bios_cfg->fanreg, cmd);
+       ec_write(ctrl_cfg.fanreg, cmd);
 
-       if (bios_cfg->mcmd_enable && state == ACERHDF_FAN_OFF) {
+       if (ctrl_cfg.mcmd_enable && state == ACERHDF_FAN_OFF) {
                if (verbose)
                        pr_notice("turning off fan manually\n");
                ec_write(mcmd.mreg, mcmd.moff);
@@ -615,10 +627,11 @@ static int str_starts_with(const char *str, const char *start)
 }
 
 /* check hardware */
-static int acerhdf_check_hardware(void)
+static int __init acerhdf_check_hardware(void)
 {
        char const *vendor, *version, *product;
        const struct bios_settings *bt = NULL;
+       int found = 0;
 
        /* get BIOS data */
        vendor  = dmi_get_system_info(DMI_SYS_VENDOR);
@@ -632,6 +645,17 @@ static int acerhdf_check_hardware(void)
 
        pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER);
 
+       if (list_supported) {
+               pr_info("List of supported Manufacturer/Model/BIOS:\n");
+               pr_info("---------------------------------------------------\n");
+               for (bt = bios_tbl; bt->vendor[0]; bt++) {
+                       pr_info("%-13s | %-17s | %-10s\n", bt->vendor,
+                               bt->product, bt->version);
+               }
+               pr_info("---------------------------------------------------\n");
+               return -ECANCELED;
+       }
+
        if (force_bios[0]) {
                version = force_bios;
                pr_info("forcing BIOS version: %s\n", version);
@@ -657,30 +681,36 @@ static int acerhdf_check_hardware(void)
                if (str_starts_with(vendor, bt->vendor) &&
                                str_starts_with(product, bt->product) &&
                                str_starts_with(version, bt->version)) {
-                       bios_cfg = bt;
+                       found = 1;
                        break;
                }
        }
 
-       if (!bios_cfg) {
+       if (!found) {
                pr_err("unknown (unsupported) BIOS version %s/%s/%s, please report, aborting!\n",
                       vendor, product, version);
                return -EINVAL;
        }
 
+       /* Copy control settings from BIOS table before we free it. */
+       ctrl_cfg.fanreg = bt->fanreg;
+       ctrl_cfg.tempreg = bt->tempreg;
+       memcpy(&ctrl_cfg.cmd, &bt->cmd, sizeof(struct fancmd));
+       ctrl_cfg.mcmd_enable = bt->mcmd_enable;
+
        /*
         * if started with kernel mode off, prevent the kernel from switching
         * off the fan
         */
        if (!kernelmode) {
                pr_notice("Fan control off, to enable do:\n");
-               pr_notice("echo -n \"enabled\" > /sys/class/thermal/thermal_zone0/mode\n");
+               pr_notice("echo -n \"enabled\" > /sys/class/thermal/thermal_zoneN/mode # N=0,1,2...\n");
        }
 
        return 0;
 }
 
-static int acerhdf_register_platform(void)
+static int __init acerhdf_register_platform(void)
 {
        int err = 0;
 
@@ -712,7 +742,7 @@ static void acerhdf_unregister_platform(void)
        platform_driver_unregister(&acerhdf_driver);
 }
 
-static int acerhdf_register_thermal(void)
+static int __init acerhdf_register_thermal(void)
 {
        cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL,
                                                 &acerhdf_cooling_ops);
index 93ee2d5466f8092978f57bf74ca84ee9c3cc1cc8..c285a16675ee7d912280028bf5f94c552fad6371 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/platform_data/x86/asus-wmi.h>
 #include <linux/platform_device.h>
 #include <linux/thermal.h>
 #include <linux/acpi.h>
@@ -69,89 +70,6 @@ MODULE_LICENSE("GPL");
 #define NOTIFY_KBD_BRTDWN              0xc5
 #define NOTIFY_KBD_BRTTOGGLE           0xc7
 
-/* WMI Methods */
-#define ASUS_WMI_METHODID_SPEC         0x43455053 /* BIOS SPECification */
-#define ASUS_WMI_METHODID_SFBD         0x44424653 /* Set First Boot Device */
-#define ASUS_WMI_METHODID_GLCD         0x44434C47 /* Get LCD status */
-#define ASUS_WMI_METHODID_GPID         0x44495047 /* Get Panel ID?? (Resol) */
-#define ASUS_WMI_METHODID_QMOD         0x444F4D51 /* Quiet MODe */
-#define ASUS_WMI_METHODID_SPLV         0x4C425053 /* Set Panel Light Value */
-#define ASUS_WMI_METHODID_AGFN         0x4E464741 /* FaN? */
-#define ASUS_WMI_METHODID_SFUN         0x4E554653 /* FUNCtionalities */
-#define ASUS_WMI_METHODID_SDSP         0x50534453 /* Set DiSPlay output */
-#define ASUS_WMI_METHODID_GDSP         0x50534447 /* Get DiSPlay output */
-#define ASUS_WMI_METHODID_DEVP         0x50564544 /* DEVice Policy */
-#define ASUS_WMI_METHODID_OSVR         0x5256534F /* OS VeRsion */
-#define ASUS_WMI_METHODID_DSTS         0x53544344 /* Device STatuS */
-#define ASUS_WMI_METHODID_DSTS2                0x53545344 /* Device STatuS #2*/
-#define ASUS_WMI_METHODID_BSTS         0x53545342 /* Bios STatuS ? */
-#define ASUS_WMI_METHODID_DEVS         0x53564544 /* DEVice Set */
-#define ASUS_WMI_METHODID_CFVS         0x53564643 /* CPU Frequency Volt Set */
-#define ASUS_WMI_METHODID_KBFT         0x5446424B /* KeyBoard FilTer */
-#define ASUS_WMI_METHODID_INIT         0x54494E49 /* INITialize */
-#define ASUS_WMI_METHODID_HKEY         0x59454B48 /* Hot KEY ?? */
-
-#define ASUS_WMI_UNSUPPORTED_METHOD    0xFFFFFFFE
-
-/* Wireless */
-#define ASUS_WMI_DEVID_HW_SWITCH       0x00010001
-#define ASUS_WMI_DEVID_WIRELESS_LED    0x00010002
-#define ASUS_WMI_DEVID_CWAP            0x00010003
-#define ASUS_WMI_DEVID_WLAN            0x00010011
-#define ASUS_WMI_DEVID_WLAN_LED                0x00010012
-#define ASUS_WMI_DEVID_BLUETOOTH       0x00010013
-#define ASUS_WMI_DEVID_GPS             0x00010015
-#define ASUS_WMI_DEVID_WIMAX           0x00010017
-#define ASUS_WMI_DEVID_WWAN3G          0x00010019
-#define ASUS_WMI_DEVID_UWB             0x00010021
-
-/* Leds */
-/* 0x000200XX and 0x000400XX */
-#define ASUS_WMI_DEVID_LED1            0x00020011
-#define ASUS_WMI_DEVID_LED2            0x00020012
-#define ASUS_WMI_DEVID_LED3            0x00020013
-#define ASUS_WMI_DEVID_LED4            0x00020014
-#define ASUS_WMI_DEVID_LED5            0x00020015
-#define ASUS_WMI_DEVID_LED6            0x00020016
-
-/* Backlight and Brightness */
-#define ASUS_WMI_DEVID_ALS_ENABLE      0x00050001 /* Ambient Light Sensor */
-#define ASUS_WMI_DEVID_BACKLIGHT       0x00050011
-#define ASUS_WMI_DEVID_BRIGHTNESS      0x00050012
-#define ASUS_WMI_DEVID_KBD_BACKLIGHT   0x00050021
-#define ASUS_WMI_DEVID_LIGHT_SENSOR    0x00050022 /* ?? */
-#define ASUS_WMI_DEVID_LIGHTBAR                0x00050025
-
-/* Misc */
-#define ASUS_WMI_DEVID_CAMERA          0x00060013
-
-/* Storage */
-#define ASUS_WMI_DEVID_CARDREADER      0x00080013
-
-/* Input */
-#define ASUS_WMI_DEVID_TOUCHPAD                0x00100011
-#define ASUS_WMI_DEVID_TOUCHPAD_LED    0x00100012
-
-/* Fan, Thermal */
-#define ASUS_WMI_DEVID_THERMAL_CTRL    0x00110011
-#define ASUS_WMI_DEVID_FAN_CTRL                0x00110012
-
-/* Power */
-#define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
-
-/* Deep S3 / Resume on LID open */
-#define ASUS_WMI_DEVID_LID_RESUME      0x00120031
-
-/* DSTS masks */
-#define ASUS_WMI_DSTS_STATUS_BIT       0x00000001
-#define ASUS_WMI_DSTS_UNKNOWN_BIT      0x00000002
-#define ASUS_WMI_DSTS_PRESENCE_BIT     0x00010000
-#define ASUS_WMI_DSTS_USER_BIT         0x00020000
-#define ASUS_WMI_DSTS_BIOS_BIT         0x00040000
-#define ASUS_WMI_DSTS_BRIGHTNESS_MASK  0x000000FF
-#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK  0x0000FF00
-#define ASUS_WMI_DSTS_LIGHTBAR_MASK    0x0000000F
-
 #define ASUS_FAN_DESC                  "cpu_fan"
 #define ASUS_FAN_MFUN                  0x13
 #define ASUS_FAN_SFUN_READ             0x06
@@ -239,7 +157,6 @@ struct asus_wmi {
        int lightbar_led_wk;
        struct workqueue_struct *led_workqueue;
        struct work_struct tpd_led_work;
-       struct work_struct kbd_led_work;
        struct work_struct wlan_led_work;
        struct work_struct lightbar_led_work;
 
@@ -302,8 +219,7 @@ static void asus_wmi_input_exit(struct asus_wmi *asus)
        asus->inputdev = NULL;
 }
 
-static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
-                                   u32 *retval)
+int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval)
 {
        struct bios_args args = {
                .arg0 = arg0,
@@ -339,6 +255,7 @@ exit:
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(asus_wmi_evaluate_method);
 
 static int asus_wmi_evaluate_method_agfn(const struct acpi_buffer args)
 {
@@ -456,12 +373,9 @@ static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
        return read_tpd_led_state(asus);
 }
 
-static void kbd_led_update(struct work_struct *work)
+static void kbd_led_update(struct asus_wmi *asus)
 {
        int ctrl_param = 0;
-       struct asus_wmi *asus;
-
-       asus = container_of(work, struct asus_wmi, kbd_led_work);
 
        /*
         * bits 0-2: level
@@ -471,7 +385,6 @@ static void kbd_led_update(struct work_struct *work)
                ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
 
        asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
-       led_classdev_notify_brightness_hw_changed(&asus->kbd_led, asus->kbd_led_wk);
 }
 
 static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
@@ -516,7 +429,7 @@ static void do_kbd_led_set(struct led_classdev *led_cdev, int value)
                value = 0;
 
        asus->kbd_led_wk = value;
-       queue_work(asus->led_workqueue, &asus->kbd_led_work);
+       kbd_led_update(asus);
 }
 
 static void kbd_led_set(struct led_classdev *led_cdev,
@@ -525,6 +438,14 @@ static void kbd_led_set(struct led_classdev *led_cdev,
        do_kbd_led_set(led_cdev, value);
 }
 
+static void kbd_led_set_by_kbd(struct asus_wmi *asus, enum led_brightness value)
+{
+       struct led_classdev *led_cdev = &asus->kbd_led;
+
+       do_kbd_led_set(led_cdev, value);
+       led_classdev_notify_brightness_hw_changed(led_cdev, asus->kbd_led_wk);
+}
+
 static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
 {
        struct asus_wmi *asus;
@@ -671,8 +592,6 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
 
        led_val = kbd_led_read(asus, NULL, NULL);
        if (led_val >= 0) {
-               INIT_WORK(&asus->kbd_led_work, kbd_led_update);
-
                asus->kbd_led_wk = led_val;
                asus->kbd_led.name = "asus::kbd_backlight";
                asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
@@ -1746,18 +1665,18 @@ static void asus_wmi_notify(u32 value, void *context)
        }
 
        if (code == NOTIFY_KBD_BRTUP) {
-               do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1);
+               kbd_led_set_by_kbd(asus, asus->kbd_led_wk + 1);
                goto exit;
        }
        if (code == NOTIFY_KBD_BRTDWN) {
-               do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk - 1);
+               kbd_led_set_by_kbd(asus, asus->kbd_led_wk - 1);
                goto exit;
        }
        if (code == NOTIFY_KBD_BRTTOGGLE) {
                if (asus->kbd_led_wk == asus->kbd_led.max_brightness)
-                       do_kbd_led_set(&asus->kbd_led, 0);
+                       kbd_led_set_by_kbd(asus, 0);
                else
-                       do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1);
+                       kbd_led_set_by_kbd(asus, asus->kbd_led_wk + 1);
                goto exit;
        }
 
@@ -2291,7 +2210,7 @@ static int asus_hotk_resume(struct device *device)
        struct asus_wmi *asus = dev_get_drvdata(device);
 
        if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
-               queue_work(asus->led_workqueue, &asus->kbd_led_work);
+               kbd_led_update(asus);
 
        return 0;
 }
@@ -2327,7 +2246,7 @@ static int asus_hotk_restore(struct device *device)
                rfkill_set_sw_state(asus->uwb.rfkill, bl);
        }
        if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
-               queue_work(asus->led_workqueue, &asus->kbd_led_work);
+               kbd_led_update(asus);
 
        return 0;
 }
diff --git a/drivers/platform/x86/dcdbas.c b/drivers/platform/x86/dcdbas.c
new file mode 100644 (file)
index 0000000..88bd7ef
--- /dev/null
@@ -0,0 +1,761 @@
+/*
+ *  dcdbas.c: Dell Systems Management Base Driver
+ *
+ *  The Dell Systems Management Base Driver provides a sysfs interface for
+ *  systems management software to perform System Management Interrupts (SMIs)
+ *  and Host Control Actions (power cycle or power off after OS shutdown) on
+ *  Dell systems.
+ *
+ *  See Documentation/dcdbas.txt for more information.
+ *
+ *  Copyright (C) 1995-2006 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License v2.0 as published by
+ *  the Free Software Foundation.
+ *
+ *  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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/cpu.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+
+#include "dcdbas.h"
+
+#define DRIVER_NAME            "dcdbas"
+#define DRIVER_VERSION         "5.6.0-3.3"
+#define DRIVER_DESCRIPTION     "Dell Systems Management Base Driver"
+
+static struct platform_device *dcdbas_pdev;
+
+static u8 *smi_data_buf;
+static dma_addr_t smi_data_buf_handle;
+static unsigned long smi_data_buf_size;
+static unsigned long max_smi_data_buf_size = MAX_SMI_DATA_BUF_SIZE;
+static u32 smi_data_buf_phys_addr;
+static DEFINE_MUTEX(smi_data_lock);
+static u8 *eps_buffer;
+
+static unsigned int host_control_action;
+static unsigned int host_control_smi_type;
+static unsigned int host_control_on_shutdown;
+
+static bool wsmt_enabled;
+
+/**
+ * smi_data_buf_free: free SMI data buffer
+ */
+static void smi_data_buf_free(void)
+{
+       if (!smi_data_buf || wsmt_enabled)
+               return;
+
+       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+       dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
+                         smi_data_buf_handle);
+       smi_data_buf = NULL;
+       smi_data_buf_handle = 0;
+       smi_data_buf_phys_addr = 0;
+       smi_data_buf_size = 0;
+}
+
+/**
+ * smi_data_buf_realloc: grow SMI data buffer if needed
+ */
+static int smi_data_buf_realloc(unsigned long size)
+{
+       void *buf;
+       dma_addr_t handle;
+
+       if (smi_data_buf_size >= size)
+               return 0;
+
+       if (size > max_smi_data_buf_size)
+               return -EINVAL;
+
+       /* new buffer is needed */
+       buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL);
+       if (!buf) {
+               dev_dbg(&dcdbas_pdev->dev,
+                       "%s: failed to allocate memory size %lu\n",
+                       __func__, size);
+               return -ENOMEM;
+       }
+       /* memory zeroed by dma_alloc_coherent */
+
+       if (smi_data_buf)
+               memcpy(buf, smi_data_buf, smi_data_buf_size);
+
+       /* free any existing buffer */
+       smi_data_buf_free();
+
+       /* set up new buffer for use */
+       smi_data_buf = buf;
+       smi_data_buf_handle = handle;
+       smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
+       smi_data_buf_size = size;
+
+       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+       return 0;
+}
+
+static ssize_t smi_data_buf_phys_addr_show(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+{
+       return sprintf(buf, "%x\n", smi_data_buf_phys_addr);
+}
+
+static ssize_t smi_data_buf_size_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       return sprintf(buf, "%lu\n", smi_data_buf_size);
+}
+
+static ssize_t smi_data_buf_size_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
+{
+       unsigned long buf_size;
+       ssize_t ret;
+
+       buf_size = simple_strtoul(buf, NULL, 10);
+
+       /* make sure SMI data buffer is at least buf_size */
+       mutex_lock(&smi_data_lock);
+       ret = smi_data_buf_realloc(buf_size);
+       mutex_unlock(&smi_data_lock);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static ssize_t smi_data_read(struct file *filp, struct kobject *kobj,
+                            struct bin_attribute *bin_attr,
+                            char *buf, loff_t pos, size_t count)
+{
+       ssize_t ret;
+
+       mutex_lock(&smi_data_lock);
+       ret = memory_read_from_buffer(buf, count, &pos, smi_data_buf,
+                                       smi_data_buf_size);
+       mutex_unlock(&smi_data_lock);
+       return ret;
+}
+
+static ssize_t smi_data_write(struct file *filp, struct kobject *kobj,
+                             struct bin_attribute *bin_attr,
+                             char *buf, loff_t pos, size_t count)
+{
+       ssize_t ret;
+
+       if ((pos + count) > max_smi_data_buf_size)
+               return -EINVAL;
+
+       mutex_lock(&smi_data_lock);
+
+       ret = smi_data_buf_realloc(pos + count);
+       if (ret)
+               goto out;
+
+       memcpy(smi_data_buf + pos, buf, count);
+       ret = count;
+out:
+       mutex_unlock(&smi_data_lock);
+       return ret;
+}
+
+static ssize_t host_control_action_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       return sprintf(buf, "%u\n", host_control_action);
+}
+
+static ssize_t host_control_action_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       ssize_t ret;
+
+       /* make sure buffer is available for host control command */
+       mutex_lock(&smi_data_lock);
+       ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
+       mutex_unlock(&smi_data_lock);
+       if (ret)
+               return ret;
+
+       host_control_action = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+
+static ssize_t host_control_smi_type_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       return sprintf(buf, "%u\n", host_control_smi_type);
+}
+
+static ssize_t host_control_smi_type_store(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf, size_t count)
+{
+       host_control_smi_type = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+
+static ssize_t host_control_on_shutdown_show(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buf)
+{
+       return sprintf(buf, "%u\n", host_control_on_shutdown);
+}
+
+static ssize_t host_control_on_shutdown_store(struct device *dev,
+                                             struct device_attribute *attr,
+                                             const char *buf, size_t count)
+{
+       host_control_on_shutdown = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+
+static int raise_smi(void *par)
+{
+       struct smi_cmd *smi_cmd = par;
+
+       if (smp_processor_id() != 0) {
+               dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
+                       __func__);
+               return -EBUSY;
+       }
+
+       /* generate SMI */
+       /* inb to force posted write through and make SMI happen now */
+       asm volatile (
+               "outb %b0,%w1\n"
+               "inb %w1"
+               : /* no output args */
+               : "a" (smi_cmd->command_code),
+                 "d" (smi_cmd->command_address),
+                 "b" (smi_cmd->ebx),
+                 "c" (smi_cmd->ecx)
+               : "memory"
+       );
+
+       return 0;
+}
+/**
+ * dcdbas_smi_request: generate SMI request
+ *
+ * Called with smi_data_lock.
+ */
+int dcdbas_smi_request(struct smi_cmd *smi_cmd)
+{
+       int ret;
+
+       if (smi_cmd->magic != SMI_CMD_MAGIC) {
+               dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
+                        __func__);
+               return -EBADR;
+       }
+
+       /* SMI requires CPU 0 */
+       get_online_cpus();
+       ret = smp_call_on_cpu(0, raise_smi, smi_cmd, true);
+       put_online_cpus();
+
+       return ret;
+}
+
+/**
+ * smi_request_store:
+ *
+ * The valid values are:
+ * 0: zero SMI data buffer
+ * 1: generate calling interface SMI
+ * 2: generate raw SMI
+ *
+ * User application writes smi_cmd to smi_data before telling driver
+ * to generate SMI.
+ */
+static ssize_t smi_request_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       struct smi_cmd *smi_cmd;
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+       ssize_t ret;
+
+       mutex_lock(&smi_data_lock);
+
+       if (smi_data_buf_size < sizeof(struct smi_cmd)) {
+               ret = -ENODEV;
+               goto out;
+       }
+       smi_cmd = (struct smi_cmd *)smi_data_buf;
+
+       switch (val) {
+       case 2:
+               /* Raw SMI */
+               ret = dcdbas_smi_request(smi_cmd);
+               if (!ret)
+                       ret = count;
+               break;
+       case 1:
+               /*
+                * Calling Interface SMI
+                *
+                * Provide physical address of command buffer field within
+                * the struct smi_cmd to BIOS.
+                *
+                * Because the address that smi_cmd (smi_data_buf) points to
+                * will be from memremap() of a non-memory address if WSMT
+                * is present, we can't use virt_to_phys() on smi_cmd, so
+                * we have to use the physical address that was saved when
+                * the virtual address for smi_cmd was received.
+                */
+               smi_cmd->ebx = smi_data_buf_phys_addr +
+                               offsetof(struct smi_cmd, command_buffer);
+               ret = dcdbas_smi_request(smi_cmd);
+               if (!ret)
+                       ret = count;
+               break;
+       case 0:
+               memset(smi_data_buf, 0, smi_data_buf_size);
+               ret = count;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+out:
+       mutex_unlock(&smi_data_lock);
+       return ret;
+}
+EXPORT_SYMBOL(dcdbas_smi_request);
+
+/**
+ * host_control_smi: generate host control SMI
+ *
+ * Caller must set up the host control command in smi_data_buf.
+ */
+static int host_control_smi(void)
+{
+       struct apm_cmd *apm_cmd;
+       u8 *data;
+       unsigned long flags;
+       u32 num_ticks;
+       s8 cmd_status;
+       u8 index;
+
+       apm_cmd = (struct apm_cmd *)smi_data_buf;
+       apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;
+
+       switch (host_control_smi_type) {
+       case HC_SMITYPE_TYPE1:
+               spin_lock_irqsave(&rtc_lock, flags);
+               /* write SMI data buffer physical address */
+               data = (u8 *)&smi_data_buf_phys_addr;
+               for (index = PE1300_CMOS_CMD_STRUCT_PTR;
+                    index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
+                    index++, data++) {
+                       outb(index,
+                            (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
+                       outb(*data,
+                            (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
+               }
+
+               /* first set status to -1 as called by spec */
+               cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
+               outb((u8) cmd_status, PCAT_APM_STATUS_PORT);
+
+               /* generate SMM call */
+               outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+               spin_unlock_irqrestore(&rtc_lock, flags);
+
+               /* wait a few to see if it executed */
+               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+               while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
+                      == ESM_STATUS_CMD_UNSUCCESSFUL) {
+                       num_ticks--;
+                       if (num_ticks == EXPIRED_TIMER)
+                               return -ETIME;
+               }
+               break;
+
+       case HC_SMITYPE_TYPE2:
+       case HC_SMITYPE_TYPE3:
+               spin_lock_irqsave(&rtc_lock, flags);
+               /* write SMI data buffer physical address */
+               data = (u8 *)&smi_data_buf_phys_addr;
+               for (index = PE1400_CMOS_CMD_STRUCT_PTR;
+                    index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
+                    index++, data++) {
+                       outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
+                       outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
+               }
+
+               /* generate SMM call */
+               if (host_control_smi_type == HC_SMITYPE_TYPE3)
+                       outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+               else
+                       outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);
+
+               /* restore RTC index pointer since it was written to above */
+               CMOS_READ(RTC_REG_C);
+               spin_unlock_irqrestore(&rtc_lock, flags);
+
+               /* read control port back to serialize write */
+               cmd_status = inb(PE1400_APM_CONTROL_PORT);
+
+               /* wait a few to see if it executed */
+               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+               while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
+                       num_ticks--;
+                       if (num_ticks == EXPIRED_TIMER)
+                               return -ETIME;
+               }
+               break;
+
+       default:
+               dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
+                       __func__, host_control_smi_type);
+               return -ENOSYS;
+       }
+
+       return 0;
+}
+
+/**
+ * dcdbas_host_control: initiate host control
+ *
+ * This function is called by the driver after the system has
+ * finished shutting down if the user application specified a
+ * host control action to perform on shutdown.  It is safe to
+ * use smi_data_buf at this point because the system has finished
+ * shutting down and no userspace apps are running.
+ */
+static void dcdbas_host_control(void)
+{
+       struct apm_cmd *apm_cmd;
+       u8 action;
+
+       if (host_control_action == HC_ACTION_NONE)
+               return;
+
+       action = host_control_action;
+       host_control_action = HC_ACTION_NONE;
+
+       if (!smi_data_buf) {
+               dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __func__);
+               return;
+       }
+
+       if (smi_data_buf_size < sizeof(struct apm_cmd)) {
+               dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
+                       __func__);
+               return;
+       }
+
+       apm_cmd = (struct apm_cmd *)smi_data_buf;
+
+       /* power off takes precedence */
+       if (action & HC_ACTION_HOST_CONTROL_POWEROFF) {
+               apm_cmd->command = ESM_APM_POWER_CYCLE;
+               apm_cmd->reserved = 0;
+               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 0;
+               host_control_smi();
+       } else if (action & HC_ACTION_HOST_CONTROL_POWERCYCLE) {
+               apm_cmd->command = ESM_APM_POWER_CYCLE;
+               apm_cmd->reserved = 0;
+               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 20;
+               host_control_smi();
+       }
+}
+
+/* WSMT */
+
+static u8 checksum(u8 *buffer, u8 length)
+{
+       u8 sum = 0;
+       u8 *end = buffer + length;
+
+       while (buffer < end)
+               sum += *buffer++;
+       return sum;
+}
+
+static inline struct smm_eps_table *check_eps_table(u8 *addr)
+{
+       struct smm_eps_table *eps = (struct smm_eps_table *)addr;
+
+       if (strncmp(eps->smm_comm_buff_anchor, SMM_EPS_SIG, 4) != 0)
+               return NULL;
+
+       if (checksum(addr, eps->length) != 0)
+               return NULL;
+
+       return eps;
+}
+
+static int dcdbas_check_wsmt(void)
+{
+       struct acpi_table_wsmt *wsmt = NULL;
+       struct smm_eps_table *eps = NULL;
+       u64 remap_size;
+       u8 *addr;
+
+       acpi_get_table(ACPI_SIG_WSMT, 0, (struct acpi_table_header **)&wsmt);
+       if (!wsmt)
+               return 0;
+
+       /* Check if WSMT ACPI table shows that protection is enabled */
+       if (!(wsmt->protection_flags & ACPI_WSMT_FIXED_COMM_BUFFERS) ||
+           !(wsmt->protection_flags & ACPI_WSMT_COMM_BUFFER_NESTED_PTR_PROTECTION))
+               return 0;
+
+       /* Scan for EPS (entry point structure) */
+       for (addr = (u8 *)__va(0xf0000);
+            addr < (u8 *)__va(0x100000 - sizeof(struct smm_eps_table));
+            addr += 16) {
+               eps = check_eps_table(addr);
+               if (eps)
+                       break;
+       }
+
+       if (!eps) {
+               dev_dbg(&dcdbas_pdev->dev, "found WSMT, but no EPS found\n");
+               return -ENODEV;
+       }
+
+       /*
+        * Get physical address of buffer and map to virtual address.
+        * Table gives size in 4K pages, regardless of actual system page size.
+        */
+       if (upper_32_bits(eps->smm_comm_buff_addr + 8)) {
+               dev_warn(&dcdbas_pdev->dev, "found WSMT, but EPS buffer address is above 4GB\n");
+               return -EINVAL;
+       }
+       /*
+        * Limit remap size to MAX_SMI_DATA_BUF_SIZE + 8 (since the first 8
+        * bytes are used for a semaphore, not the data buffer itself).
+        */
+       remap_size = eps->num_of_4k_pages * PAGE_SIZE;
+       if (remap_size > MAX_SMI_DATA_BUF_SIZE + 8)
+               remap_size = MAX_SMI_DATA_BUF_SIZE + 8;
+       eps_buffer = memremap(eps->smm_comm_buff_addr, remap_size, MEMREMAP_WB);
+       if (!eps_buffer) {
+               dev_warn(&dcdbas_pdev->dev, "found WSMT, but failed to map EPS buffer\n");
+               return -ENOMEM;
+       }
+
+       /* First 8 bytes is for a semaphore, not part of the smi_data_buf */
+       smi_data_buf_phys_addr = eps->smm_comm_buff_addr + 8;
+       smi_data_buf = eps_buffer + 8;
+       smi_data_buf_size = remap_size - 8;
+       max_smi_data_buf_size = smi_data_buf_size;
+       wsmt_enabled = true;
+       dev_info(&dcdbas_pdev->dev,
+                "WSMT found, using firmware-provided SMI buffer.\n");
+       return 1;
+}
+
+/**
+ * dcdbas_reboot_notify: handle reboot notification for host control
+ */
+static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
+                               void *unused)
+{
+       switch (code) {
+       case SYS_DOWN:
+       case SYS_HALT:
+       case SYS_POWER_OFF:
+               if (host_control_on_shutdown) {
+                       /* firmware is going to perform host control action */
+                       printk(KERN_WARNING "Please wait for shutdown "
+                              "action to complete...\n");
+                       dcdbas_host_control();
+               }
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block dcdbas_reboot_nb = {
+       .notifier_call = dcdbas_reboot_notify,
+       .next = NULL,
+       .priority = INT_MIN
+};
+
+static DCDBAS_BIN_ATTR_RW(smi_data);
+
+static struct bin_attribute *dcdbas_bin_attrs[] = {
+       &bin_attr_smi_data,
+       NULL
+};
+
+static DCDBAS_DEV_ATTR_RW(smi_data_buf_size);
+static DCDBAS_DEV_ATTR_RO(smi_data_buf_phys_addr);
+static DCDBAS_DEV_ATTR_WO(smi_request);
+static DCDBAS_DEV_ATTR_RW(host_control_action);
+static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
+static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
+
+static struct attribute *dcdbas_dev_attrs[] = {
+       &dev_attr_smi_data_buf_size.attr,
+       &dev_attr_smi_data_buf_phys_addr.attr,
+       &dev_attr_smi_request.attr,
+       &dev_attr_host_control_action.attr,
+       &dev_attr_host_control_smi_type.attr,
+       &dev_attr_host_control_on_shutdown.attr,
+       NULL
+};
+
+static const struct attribute_group dcdbas_attr_group = {
+       .attrs = dcdbas_dev_attrs,
+       .bin_attrs = dcdbas_bin_attrs,
+};
+
+static int dcdbas_probe(struct platform_device *dev)
+{
+       int error;
+
+       host_control_action = HC_ACTION_NONE;
+       host_control_smi_type = HC_SMITYPE_NONE;
+
+       dcdbas_pdev = dev;
+
+       /* Check if ACPI WSMT table specifies protected SMI buffer address */
+       error = dcdbas_check_wsmt();
+       if (error < 0)
+               return error;
+
+       /*
+        * BIOS SMI calls require buffer addresses be in 32-bit address space.
+        * This is done by setting the DMA mask below.
+        */
+       error = dma_set_coherent_mask(&dcdbas_pdev->dev, DMA_BIT_MASK(32));
+       if (error)
+               return error;
+
+       error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
+       if (error)
+               return error;
+
+       register_reboot_notifier(&dcdbas_reboot_nb);
+
+       dev_info(&dev->dev, "%s (version %s)\n",
+                DRIVER_DESCRIPTION, DRIVER_VERSION);
+
+       return 0;
+}
+
+static int dcdbas_remove(struct platform_device *dev)
+{
+       unregister_reboot_notifier(&dcdbas_reboot_nb);
+       sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
+
+       return 0;
+}
+
+static struct platform_driver dcdbas_driver = {
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+       .probe          = dcdbas_probe,
+       .remove         = dcdbas_remove,
+};
+
+static const struct platform_device_info dcdbas_dev_info __initconst = {
+       .name           = DRIVER_NAME,
+       .id             = -1,
+       .dma_mask       = DMA_BIT_MASK(32),
+};
+
+static struct platform_device *dcdbas_pdev_reg;
+
+/**
+ * dcdbas_init: initialize driver
+ */
+static int __init dcdbas_init(void)
+{
+       int error;
+
+       error = platform_driver_register(&dcdbas_driver);
+       if (error)
+               return error;
+
+       dcdbas_pdev_reg = platform_device_register_full(&dcdbas_dev_info);
+       if (IS_ERR(dcdbas_pdev_reg)) {
+               error = PTR_ERR(dcdbas_pdev_reg);
+               goto err_unregister_driver;
+       }
+
+       return 0;
+
+ err_unregister_driver:
+       platform_driver_unregister(&dcdbas_driver);
+       return error;
+}
+
+/**
+ * dcdbas_exit: perform driver cleanup
+ */
+static void __exit dcdbas_exit(void)
+{
+       /*
+        * make sure functions that use dcdbas_pdev are called
+        * before platform_device_unregister
+        */
+       unregister_reboot_notifier(&dcdbas_reboot_nb);
+
+       /*
+        * We have to free the buffer here instead of dcdbas_remove
+        * because only in module exit function we can be sure that
+        * all sysfs attributes belonging to this module have been
+        * released.
+        */
+       if (dcdbas_pdev)
+               smi_data_buf_free();
+       if (eps_buffer)
+               memunmap(eps_buffer);
+       platform_device_unregister(dcdbas_pdev_reg);
+       platform_driver_unregister(&dcdbas_driver);
+}
+
+subsys_initcall_sync(dcdbas_init);
+module_exit(dcdbas_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR("Dell Inc.");
+MODULE_LICENSE("GPL");
+/* Any System or BIOS claiming to be by Dell */
+MODULE_ALIAS("dmi:*:[bs]vnD[Ee][Ll][Ll]*:*");
diff --git a/drivers/platform/x86/dcdbas.h b/drivers/platform/x86/dcdbas.h
new file mode 100644 (file)
index 0000000..52729a4
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  dcdbas.h: Definitions for Dell Systems Management Base driver
+ *
+ *  Copyright (C) 1995-2005 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License v2.0 as published by
+ *  the Free Software Foundation.
+ *
+ *  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.
+ */
+
+#ifndef _DCDBAS_H_
+#define _DCDBAS_H_
+
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#define MAX_SMI_DATA_BUF_SIZE                  (256 * 1024)
+
+#define HC_ACTION_NONE                         (0)
+#define HC_ACTION_HOST_CONTROL_POWEROFF                BIT(1)
+#define HC_ACTION_HOST_CONTROL_POWERCYCLE      BIT(2)
+
+#define HC_SMITYPE_NONE                                (0)
+#define HC_SMITYPE_TYPE1                       (1)
+#define HC_SMITYPE_TYPE2                       (2)
+#define HC_SMITYPE_TYPE3                       (3)
+
+#define ESM_APM_CMD                            (0x0A0)
+#define ESM_APM_POWER_CYCLE                    (0x10)
+#define ESM_STATUS_CMD_UNSUCCESSFUL            (-1)
+
+#define CMOS_BASE_PORT                         (0x070)
+#define CMOS_PAGE1_INDEX_PORT                  (0)
+#define CMOS_PAGE1_DATA_PORT                   (1)
+#define CMOS_PAGE2_INDEX_PORT_PIIX4            (2)
+#define CMOS_PAGE2_DATA_PORT_PIIX4             (3)
+#define PE1400_APM_CONTROL_PORT                        (0x0B0)
+#define PCAT_APM_CONTROL_PORT                  (0x0B2)
+#define PCAT_APM_STATUS_PORT                   (0x0B3)
+#define PE1300_CMOS_CMD_STRUCT_PTR             (0x38)
+#define PE1400_CMOS_CMD_STRUCT_PTR             (0x70)
+
+#define MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN       (14)
+#define MAX_SYSMGMT_LONGCMD_SGENTRY_NUM                (16)
+
+#define TIMEOUT_USEC_SHORT_SEMA_BLOCKING       (10000)
+#define EXPIRED_TIMER                          (0)
+
+#define SMI_CMD_MAGIC                          (0x534D4931)
+#define SMM_EPS_SIG                            "$SCB"
+
+#define DCDBAS_DEV_ATTR_RW(_name) \
+       DEVICE_ATTR(_name,0600,_name##_show,_name##_store);
+
+#define DCDBAS_DEV_ATTR_RO(_name) \
+       DEVICE_ATTR(_name,0400,_name##_show,NULL);
+
+#define DCDBAS_DEV_ATTR_WO(_name) \
+       DEVICE_ATTR(_name,0200,NULL,_name##_store);
+
+#define DCDBAS_BIN_ATTR_RW(_name) \
+struct bin_attribute bin_attr_##_name = { \
+       .attr =  { .name = __stringify(_name), \
+                  .mode = 0600 }, \
+       .read =  _name##_read, \
+       .write = _name##_write, \
+}
+
+struct smi_cmd {
+       __u32 magic;
+       __u32 ebx;
+       __u32 ecx;
+       __u16 command_address;
+       __u8 command_code;
+       __u8 reserved;
+       __u8 command_buffer[1];
+} __attribute__ ((packed));
+
+struct apm_cmd {
+       __u8 command;
+       __s8 status;
+       __u16 reserved;
+       union {
+               struct {
+                       __u8 parm[MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN];
+               } __attribute__ ((packed)) shortreq;
+
+               struct {
+                       __u16 num_sg_entries;
+                       struct {
+                               __u32 size;
+                               __u64 addr;
+                       } __attribute__ ((packed))
+                           sglist[MAX_SYSMGMT_LONGCMD_SGENTRY_NUM];
+               } __attribute__ ((packed)) longreq;
+       } __attribute__ ((packed)) parameters;
+} __attribute__ ((packed));
+
+int dcdbas_smi_request(struct smi_cmd *smi_cmd);
+
+struct smm_eps_table {
+       char smm_comm_buff_anchor[4];
+       u8 length;
+       u8 checksum;
+       u8 version;
+       u64 smm_comm_buff_addr;
+       u64 num_of_4k_pages;
+} __packed;
+
+#endif /* _DCDBAS_H_ */
+
index 97a90bebc36079f5ff716b8d739bd27928aa442a..ab9b822a6dfe6df42a0ba237f7aa50fb984d39db 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
-#include "../../firmware/dcdbas.h"
+#include "dcdbas.h"
 #include "dell-smbios.h"
 
 static int da_command_address;
diff --git a/drivers/platform/x86/dell_rbu.c b/drivers/platform/x86/dell_rbu.c
new file mode 100644 (file)
index 0000000..ccefa84
--- /dev/null
@@ -0,0 +1,753 @@
+/*
+ * dell_rbu.c
+ * Bios Update driver for Dell systems
+ * Author: Dell Inc
+ *         Abhay Salunke <abhay_salunke@dell.com>
+ *
+ * Copyright (C) 2005 Dell Inc.
+ *
+ * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
+ * creating entries in the /sys file systems on Linux 2.6 and higher
+ * kernels. The driver supports two mechanism to update the BIOS namely
+ * contiguous and packetized. Both these methods still require having some
+ * application to set the CMOS bit indicating the BIOS to update itself
+ * after a reboot.
+ *
+ * Contiguous method:
+ * This driver writes the incoming data in a monolithic image by allocating
+ * contiguous physical pages large enough to accommodate the incoming BIOS
+ * image size.
+ *
+ * Packetized method:
+ * The driver writes the incoming packet image by allocating a new packet
+ * on every time the packet data is written. This driver requires an
+ * application to break the BIOS image in to fixed sized packet chunks.
+ *
+ * See Documentation/dell_rbu.txt for more info.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/blkdev.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <asm/set_memory.h>
+
+MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
+MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("3.2");
+
+#define BIOS_SCAN_LIMIT 0xffffffff
+#define MAX_IMAGE_LENGTH 16
+static struct _rbu_data {
+       void *image_update_buffer;
+       unsigned long image_update_buffer_size;
+       unsigned long bios_image_size;
+       int image_update_ordernum;
+       int dma_alloc;
+       spinlock_t lock;
+       unsigned long packet_read_count;
+       unsigned long num_packets;
+       unsigned long packetsize;
+       unsigned long imagesize;
+       int entry_created;
+} rbu_data;
+
+static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
+module_param_string(image_type, image_type, sizeof (image_type), 0);
+MODULE_PARM_DESC(image_type,
+       "BIOS image type. choose- mono or packet or init");
+
+static unsigned long allocation_floor = 0x100000;
+module_param(allocation_floor, ulong, 0644);
+MODULE_PARM_DESC(allocation_floor,
+    "Minimum address for allocations when using Packet mode");
+
+struct packet_data {
+       struct list_head list;
+       size_t length;
+       void *data;
+       int ordernum;
+};
+
+static struct packet_data packet_data_head;
+
+static struct platform_device *rbu_device;
+static int context;
+static dma_addr_t dell_rbu_dmaaddr;
+
+static void init_packet_head(void)
+{
+       INIT_LIST_HEAD(&packet_data_head.list);
+       rbu_data.packet_read_count = 0;
+       rbu_data.num_packets = 0;
+       rbu_data.packetsize = 0;
+       rbu_data.imagesize = 0;
+}
+
+static int create_packet(void *data, size_t length)
+{
+       struct packet_data *newpacket;
+       int ordernum = 0;
+       int retval = 0;
+       unsigned int packet_array_size = 0;
+       void **invalid_addr_packet_array = NULL;
+       void *packet_data_temp_buf = NULL;
+       unsigned int idx = 0;
+
+       pr_debug("create_packet: entry \n");
+
+       if (!rbu_data.packetsize) {
+               pr_debug("create_packet: packetsize not specified\n");
+               retval = -EINVAL;
+               goto out_noalloc;
+       }
+
+       spin_unlock(&rbu_data.lock);
+
+       newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);
+
+       if (!newpacket) {
+               printk(KERN_WARNING
+                       "dell_rbu:%s: failed to allocate new "
+                       "packet\n", __func__);
+               retval = -ENOMEM;
+               spin_lock(&rbu_data.lock);
+               goto out_noalloc;
+       }
+
+       ordernum = get_order(length);
+
+       /*
+        * BIOS errata mean we cannot allocate packets below 1MB or they will
+        * be overwritten by BIOS.
+        *
+        * array to temporarily hold packets
+        * that are below the allocation floor
+        *
+        * NOTE: very simplistic because we only need the floor to be at 1MB
+        *       due to BIOS errata. This shouldn't be used for higher floors
+        *       or you will run out of mem trying to allocate the array.
+        */
+       packet_array_size = max(
+                       (unsigned int)(allocation_floor / rbu_data.packetsize),
+                       (unsigned int)1);
+       invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *),
+                                               GFP_KERNEL);
+
+       if (!invalid_addr_packet_array) {
+               printk(KERN_WARNING
+                       "dell_rbu:%s: failed to allocate "
+                       "invalid_addr_packet_array \n",
+                       __func__);
+               retval = -ENOMEM;
+               spin_lock(&rbu_data.lock);
+               goto out_alloc_packet;
+       }
+
+       while (!packet_data_temp_buf) {
+               packet_data_temp_buf = (unsigned char *)
+                       __get_free_pages(GFP_KERNEL, ordernum);
+               if (!packet_data_temp_buf) {
+                       printk(KERN_WARNING
+                               "dell_rbu:%s: failed to allocate new "
+                               "packet\n", __func__);
+                       retval = -ENOMEM;
+                       spin_lock(&rbu_data.lock);
+                       goto out_alloc_packet_array;
+               }
+
+               if ((unsigned long)virt_to_phys(packet_data_temp_buf)
+                               < allocation_floor) {
+                       pr_debug("packet 0x%lx below floor at 0x%lx.\n",
+                                       (unsigned long)virt_to_phys(
+                                               packet_data_temp_buf),
+                                       allocation_floor);
+                       invalid_addr_packet_array[idx++] = packet_data_temp_buf;
+                       packet_data_temp_buf = NULL;
+               }
+       }
+       /*
+        * set to uncachable or it may never get written back before reboot
+        */
+       set_memory_uc((unsigned long)packet_data_temp_buf, 1 << ordernum);
+
+       spin_lock(&rbu_data.lock);
+
+       newpacket->data = packet_data_temp_buf;
+
+       pr_debug("create_packet: newpacket at physical addr %lx\n",
+               (unsigned long)virt_to_phys(newpacket->data));
+
+       /* packets may not have fixed size */
+       newpacket->length = length;
+       newpacket->ordernum = ordernum;
+       ++rbu_data.num_packets;
+
+       /* initialize the newly created packet headers */
+       INIT_LIST_HEAD(&newpacket->list);
+       list_add_tail(&newpacket->list, &packet_data_head.list);
+
+       memcpy(newpacket->data, data, length);
+
+       pr_debug("create_packet: exit \n");
+
+out_alloc_packet_array:
+       /* always free packet array */
+       for (;idx>0;idx--) {
+               pr_debug("freeing unused packet below floor 0x%lx.\n",
+                       (unsigned long)virt_to_phys(
+                               invalid_addr_packet_array[idx-1]));
+               free_pages((unsigned long)invalid_addr_packet_array[idx-1],
+                       ordernum);
+       }
+       kfree(invalid_addr_packet_array);
+
+out_alloc_packet:
+       /* if error, free data */
+       if (retval)
+               kfree(newpacket);
+
+out_noalloc:
+       return retval;
+}
+
+static int packetize_data(const u8 *data, size_t length)
+{
+       int rc = 0;
+       int done = 0;
+       int packet_length;
+       u8 *temp;
+       u8 *end = (u8 *) data + length;
+       pr_debug("packetize_data: data length %zd\n", length);
+       if (!rbu_data.packetsize) {
+               printk(KERN_WARNING
+                       "dell_rbu: packetsize not specified\n");
+               return -EIO;
+       }
+
+       temp = (u8 *) data;
+
+       /* packetize the hunk */
+       while (!done) {
+               if ((temp + rbu_data.packetsize) < end)
+                       packet_length = rbu_data.packetsize;
+               else {
+                       /* this is the last packet */
+                       packet_length = end - temp;
+                       done = 1;
+               }
+
+               if ((rc = create_packet(temp, packet_length)))
+                       return rc;
+
+               pr_debug("%p:%td\n", temp, (end - temp));
+               temp += packet_length;
+       }
+
+       rbu_data.imagesize = length;
+
+       return rc;
+}
+
+static int do_packet_read(char *data, struct list_head *ptemp_list,
+       int length, int bytes_read, int *list_read_count)
+{
+       void *ptemp_buf;
+       struct packet_data *newpacket = NULL;
+       int bytes_copied = 0;
+       int j = 0;
+
+       newpacket = list_entry(ptemp_list, struct packet_data, list);
+       *list_read_count += newpacket->length;
+
+       if (*list_read_count > bytes_read) {
+               /* point to the start of unread data */
+               j = newpacket->length - (*list_read_count - bytes_read);
+               /* point to the offset in the packet buffer */
+               ptemp_buf = (u8 *) newpacket->data + j;
+               /*
+                * check if there is enough room in
+                * * the incoming buffer
+                */
+               if (length > (*list_read_count - bytes_read))
+                       /*
+                        * copy what ever is there in this
+                        * packet and move on
+                        */
+                       bytes_copied = (*list_read_count - bytes_read);
+               else
+                       /* copy the remaining */
+                       bytes_copied = length;
+               memcpy(data, ptemp_buf, bytes_copied);
+       }
+       return bytes_copied;
+}
+
+static int packet_read_list(char *data, size_t * pread_length)
+{
+       struct list_head *ptemp_list;
+       int temp_count = 0;
+       int bytes_copied = 0;
+       int bytes_read = 0;
+       int remaining_bytes = 0;
+       char *pdest = data;
+
+       /* check if we have any packets */
+       if (0 == rbu_data.num_packets)
+               return -ENOMEM;
+
+       remaining_bytes = *pread_length;
+       bytes_read = rbu_data.packet_read_count;
+
+       ptemp_list = (&packet_data_head.list)->next;
+       while (!list_empty(ptemp_list)) {
+               bytes_copied = do_packet_read(pdest, ptemp_list,
+                       remaining_bytes, bytes_read, &temp_count);
+               remaining_bytes -= bytes_copied;
+               bytes_read += bytes_copied;
+               pdest += bytes_copied;
+               /*
+                * check if we reached end of buffer before reaching the
+                * last packet
+                */
+               if (remaining_bytes == 0)
+                       break;
+
+               ptemp_list = ptemp_list->next;
+       }
+       /*finally set the bytes read */
+       *pread_length = bytes_read - rbu_data.packet_read_count;
+       rbu_data.packet_read_count = bytes_read;
+       return 0;
+}
+
+static void packet_empty_list(void)
+{
+       struct list_head *ptemp_list;
+       struct list_head *pnext_list;
+       struct packet_data *newpacket;
+
+       ptemp_list = (&packet_data_head.list)->next;
+       while (!list_empty(ptemp_list)) {
+               newpacket =
+                       list_entry(ptemp_list, struct packet_data, list);
+               pnext_list = ptemp_list->next;
+               list_del(ptemp_list);
+               ptemp_list = pnext_list;
+               /*
+                * zero out the RBU packet memory before freeing
+                * to make sure there are no stale RBU packets left in memory
+                */
+               memset(newpacket->data, 0, rbu_data.packetsize);
+               set_memory_wb((unsigned long)newpacket->data,
+                       1 << newpacket->ordernum);
+               free_pages((unsigned long) newpacket->data,
+                       newpacket->ordernum);
+               kfree(newpacket);
+       }
+       rbu_data.packet_read_count = 0;
+       rbu_data.num_packets = 0;
+       rbu_data.imagesize = 0;
+}
+
+/*
+ * img_update_free: Frees the buffer allocated for storing BIOS image
+ * Always called with lock held and returned with lock held
+ */
+static void img_update_free(void)
+{
+       if (!rbu_data.image_update_buffer)
+               return;
+       /*
+        * zero out this buffer before freeing it to get rid of any stale
+        * BIOS image copied in memory.
+        */
+       memset(rbu_data.image_update_buffer, 0,
+               rbu_data.image_update_buffer_size);
+       if (rbu_data.dma_alloc == 1)
+               dma_free_coherent(NULL, rbu_data.bios_image_size,
+                       rbu_data.image_update_buffer, dell_rbu_dmaaddr);
+       else
+               free_pages((unsigned long) rbu_data.image_update_buffer,
+                       rbu_data.image_update_ordernum);
+
+       /*
+        * Re-initialize the rbu_data variables after a free
+        */
+       rbu_data.image_update_ordernum = -1;
+       rbu_data.image_update_buffer = NULL;
+       rbu_data.image_update_buffer_size = 0;
+       rbu_data.bios_image_size = 0;
+       rbu_data.dma_alloc = 0;
+}
+
+/*
+ * img_update_realloc: This function allocates the contiguous pages to
+ * accommodate the requested size of data. The memory address and size
+ * values are stored globally and on every call to this function the new
+ * size is checked to see if more data is required than the existing size.
+ * If true the previous memory is freed and new allocation is done to
+ * accommodate the new size. If the incoming size is less then than the
+ * already allocated size, then that memory is reused. This function is
+ * called with lock held and returns with lock held.
+ */
+static int img_update_realloc(unsigned long size)
+{
+       unsigned char *image_update_buffer = NULL;
+       unsigned long rc;
+       unsigned long img_buf_phys_addr;
+       int ordernum;
+       int dma_alloc = 0;
+
+       /*
+        * check if the buffer of sufficient size has been
+        * already allocated
+        */
+       if (rbu_data.image_update_buffer_size >= size) {
+               /*
+                * check for corruption
+                */
+               if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
+                       printk(KERN_ERR "dell_rbu:%s: corruption "
+                               "check failed\n", __func__);
+                       return -EINVAL;
+               }
+               /*
+                * we have a valid pre-allocated buffer with
+                * sufficient size
+                */
+               return 0;
+       }
+
+       /*
+        * free any previously allocated buffer
+        */
+       img_update_free();
+
+       spin_unlock(&rbu_data.lock);
+
+       ordernum = get_order(size);
+       image_update_buffer =
+               (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
+
+       img_buf_phys_addr =
+               (unsigned long) virt_to_phys(image_update_buffer);
+
+       if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
+               free_pages((unsigned long) image_update_buffer, ordernum);
+               ordernum = -1;
+               image_update_buffer = dma_alloc_coherent(NULL, size,
+                       &dell_rbu_dmaaddr, GFP_KERNEL);
+               dma_alloc = 1;
+       }
+
+       spin_lock(&rbu_data.lock);
+
+       if (image_update_buffer != NULL) {
+               rbu_data.image_update_buffer = image_update_buffer;
+               rbu_data.image_update_buffer_size = size;
+               rbu_data.bios_image_size =
+                       rbu_data.image_update_buffer_size;
+               rbu_data.image_update_ordernum = ordernum;
+               rbu_data.dma_alloc = dma_alloc;
+               rc = 0;
+       } else {
+               pr_debug("Not enough memory for image update:"
+                       "size = %ld\n", size);
+               rc = -ENOMEM;
+       }
+
+       return rc;
+}
+
+static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
+{
+       int retval;
+       size_t bytes_left;
+       size_t data_length;
+       char *ptempBuf = buffer;
+
+       /* check to see if we have something to return */
+       if (rbu_data.num_packets == 0) {
+               pr_debug("read_packet_data: no packets written\n");
+               retval = -ENOMEM;
+               goto read_rbu_data_exit;
+       }
+
+       if (pos > rbu_data.imagesize) {
+               retval = 0;
+               printk(KERN_WARNING "dell_rbu:read_packet_data: "
+                       "data underrun\n");
+               goto read_rbu_data_exit;
+       }
+
+       bytes_left = rbu_data.imagesize - pos;
+       data_length = min(bytes_left, count);
+
+       if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
+               goto read_rbu_data_exit;
+
+       if ((pos + count) > rbu_data.imagesize) {
+               rbu_data.packet_read_count = 0;
+               /* this was the last copy */
+               retval = bytes_left;
+       } else
+               retval = count;
+
+      read_rbu_data_exit:
+       return retval;
+}
+
+static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
+{
+       /* check to see if we have something to return */
+       if ((rbu_data.image_update_buffer == NULL) ||
+               (rbu_data.bios_image_size == 0)) {
+               pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
+                       "bios_image_size %lu\n",
+                       rbu_data.image_update_buffer,
+                       rbu_data.bios_image_size);
+               return -ENOMEM;
+       }
+
+       return memory_read_from_buffer(buffer, count, &pos,
+                       rbu_data.image_update_buffer, rbu_data.bios_image_size);
+}
+
+static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj,
+                            struct bin_attribute *bin_attr,
+                            char *buffer, loff_t pos, size_t count)
+{
+       ssize_t ret_count = 0;
+
+       spin_lock(&rbu_data.lock);
+
+       if (!strcmp(image_type, "mono"))
+               ret_count = read_rbu_mono_data(buffer, pos, count);
+       else if (!strcmp(image_type, "packet"))
+               ret_count = read_packet_data(buffer, pos, count);
+       else
+               pr_debug("read_rbu_data: invalid image type specified\n");
+
+       spin_unlock(&rbu_data.lock);
+       return ret_count;
+}
+
+static void callbackfn_rbu(const struct firmware *fw, void *context)
+{
+       rbu_data.entry_created = 0;
+
+       if (!fw)
+               return;
+
+       if (!fw->size)
+               goto out;
+
+       spin_lock(&rbu_data.lock);
+       if (!strcmp(image_type, "mono")) {
+               if (!img_update_realloc(fw->size))
+                       memcpy(rbu_data.image_update_buffer,
+                               fw->data, fw->size);
+       } else if (!strcmp(image_type, "packet")) {
+               /*
+                * we need to free previous packets if a
+                * new hunk of packets needs to be downloaded
+                */
+               packet_empty_list();
+               if (packetize_data(fw->data, fw->size))
+                       /* Incase something goes wrong when we are
+                        * in middle of packetizing the data, we
+                        * need to free up whatever packets might
+                        * have been created before we quit.
+                        */
+                       packet_empty_list();
+       } else
+               pr_debug("invalid image type specified.\n");
+       spin_unlock(&rbu_data.lock);
+ out:
+       release_firmware(fw);
+}
+
+static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj,
+                                  struct bin_attribute *bin_attr,
+                                  char *buffer, loff_t pos, size_t count)
+{
+       int size = 0;
+       if (!pos)
+               size = scnprintf(buffer, count, "%s\n", image_type);
+       return size;
+}
+
+static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj,
+                                   struct bin_attribute *bin_attr,
+                                   char *buffer, loff_t pos, size_t count)
+{
+       int rc = count;
+       int req_firm_rc = 0;
+       int i;
+       spin_lock(&rbu_data.lock);
+       /*
+        * Find the first newline or space
+        */
+       for (i = 0; i < count; ++i)
+               if (buffer[i] == '\n' || buffer[i] == ' ') {
+                       buffer[i] = '\0';
+                       break;
+               }
+       if (i == count)
+               buffer[count] = '\0';
+
+       if (strstr(buffer, "mono"))
+               strcpy(image_type, "mono");
+       else if (strstr(buffer, "packet"))
+               strcpy(image_type, "packet");
+       else if (strstr(buffer, "init")) {
+               /*
+                * If due to the user error the driver gets in a bad
+                * state where even though it is loaded , the
+                * /sys/class/firmware/dell_rbu entries are missing.
+                * to cover this situation the user can recreate entries
+                * by writing init to image_type.
+                */
+               if (!rbu_data.entry_created) {
+                       spin_unlock(&rbu_data.lock);
+                       req_firm_rc = request_firmware_nowait(THIS_MODULE,
+                               FW_ACTION_NOHOTPLUG, "dell_rbu",
+                               &rbu_device->dev, GFP_KERNEL, &context,
+                               callbackfn_rbu);
+                       if (req_firm_rc) {
+                               printk(KERN_ERR
+                                       "dell_rbu:%s request_firmware_nowait"
+                                       " failed %d\n", __func__, rc);
+                               rc = -EIO;
+                       } else
+                               rbu_data.entry_created = 1;
+
+                       spin_lock(&rbu_data.lock);
+               }
+       } else {
+               printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
+               spin_unlock(&rbu_data.lock);
+               return -EINVAL;
+       }
+
+       /* we must free all previous allocations */
+       packet_empty_list();
+       img_update_free();
+       spin_unlock(&rbu_data.lock);
+
+       return rc;
+}
+
+static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj,
+                                   struct bin_attribute *bin_attr,
+                                   char *buffer, loff_t pos, size_t count)
+{
+       int size = 0;
+       if (!pos) {
+               spin_lock(&rbu_data.lock);
+               size = scnprintf(buffer, count, "%lu\n", rbu_data.packetsize);
+               spin_unlock(&rbu_data.lock);
+       }
+       return size;
+}
+
+static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj,
+                                    struct bin_attribute *bin_attr,
+                                    char *buffer, loff_t pos, size_t count)
+{
+       unsigned long temp;
+       spin_lock(&rbu_data.lock);
+       packet_empty_list();
+       sscanf(buffer, "%lu", &temp);
+       if (temp < 0xffffffff)
+               rbu_data.packetsize = temp;
+
+       spin_unlock(&rbu_data.lock);
+       return count;
+}
+
+static struct bin_attribute rbu_data_attr = {
+       .attr = {.name = "data", .mode = 0444},
+       .read = read_rbu_data,
+};
+
+static struct bin_attribute rbu_image_type_attr = {
+       .attr = {.name = "image_type", .mode = 0644},
+       .read = read_rbu_image_type,
+       .write = write_rbu_image_type,
+};
+
+static struct bin_attribute rbu_packet_size_attr = {
+       .attr = {.name = "packet_size", .mode = 0644},
+       .read = read_rbu_packet_size,
+       .write = write_rbu_packet_size,
+};
+
+static int __init dcdrbu_init(void)
+{
+       int rc;
+       spin_lock_init(&rbu_data.lock);
+
+       init_packet_head();
+       rbu_device = platform_device_register_simple("dell_rbu", -1, NULL, 0);
+       if (IS_ERR(rbu_device)) {
+               printk(KERN_ERR
+                       "dell_rbu:%s:platform_device_register_simple "
+                       "failed\n", __func__);
+               return PTR_ERR(rbu_device);
+       }
+
+       rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
+       if (rc)
+               goto out_devreg;
+       rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+       if (rc)
+               goto out_data;
+       rc = sysfs_create_bin_file(&rbu_device->dev.kobj,
+               &rbu_packet_size_attr);
+       if (rc)
+               goto out_imtype;
+
+       rbu_data.entry_created = 0;
+       return 0;
+
+out_imtype:
+       sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+out_data:
+       sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
+out_devreg:
+       platform_device_unregister(rbu_device);
+       return rc;
+}
+
+static __exit void dcdrbu_exit(void)
+{
+       spin_lock(&rbu_data.lock);
+       packet_empty_list();
+       img_update_free();
+       spin_unlock(&rbu_data.lock);
+       platform_device_unregister(rbu_device);
+}
+
+module_exit(dcdrbu_exit);
+module_init(dcdrbu_init);
+
+/* vim:noet:ts=8:sw=8
+*/
index d4f1259ff5a233bc22bb0700ddb354ace4b40e58..b6489cba29853e1919cd21c36e7fd19f3c720748 100644 (file)
@@ -212,7 +212,7 @@ static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
                        return 0;
                }
        }
-       pr_err("timeout in read_ec_cmd\n");
+       pr_err("timeout in %s\n", __func__);
        return -1;
 }
 
@@ -1146,6 +1146,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBM"),
                },
        },
+       {
+               .ident = "Lenovo Legion Y530-15ICH",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion Y530-15ICH"),
+               },
+       },
        {
                .ident = "Lenovo Legion Y720-15IKB",
                .matches = {
index 6cf9b7fa5bf0486fcf7e9d0b3ed805cfe07ca19d..e28bcf61b12698c6bf88668fe542e49cca463d32 100644 (file)
@@ -1,19 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Intel HID event & 5 button array driver
  *
  *  Copyright (C) 2015 Alex Hung <alex.hung@canonical.com>
  *  Copyright (C) 2015 Andrew Lutomirski <luto@kernel.org>
- *
- *  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.
- *
  */
 
 #include <linux/acpi.h>
index 7344d841f4d98d17810b5f6bdbee8965415af6e5..3b81cb896fedff37c231ed62de5c9d859a2df3ac 100644 (file)
@@ -1,26 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Copyright 2013 Matthew Garrett <mjg59@srcf.ucam.org>
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-
-#include <linux/init.h>
+#include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/acpi.h>
 
 MODULE_LICENSE("GPL");
 
@@ -53,12 +38,10 @@ static ssize_t irst_store_wakeup_events(struct device *dev,
        acpi = to_acpi_device(dev);
 
        error = kstrtoul(buf, 0, &value);
-
        if (error)
                return error;
 
        status = acpi_execute_simple_method(acpi->handle, "SFFS", value);
-
        if (ACPI_FAILURE(status))
                return -EINVAL;
 
@@ -99,12 +82,10 @@ static ssize_t irst_store_wakeup_time(struct device *dev,
        acpi = to_acpi_device(dev);
 
        error = kstrtoul(buf, 0, &value);
-
        if (error)
                return error;
 
        status = acpi_execute_simple_method(acpi->handle, "SFTV", value);
-
        if (ACPI_FAILURE(status))
                return -EINVAL;
 
index bbe4c06c769f66eabf8ed956cbb3361ef8407220..64c2dc93472f474869b98e418ac1a67bb74d5559 100644 (file)
@@ -1,25 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Copyright 2013 Matthew Garrett <mjg59@srcf.ucam.org>
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-
-#include <linux/init.h>
-#include <linux/module.h>
 #include <linux/acpi.h>
+#include <linux/module.h>
 
 MODULE_LICENSE("GPL");
 
@@ -44,6 +29,7 @@ static const struct acpi_device_id smartconnect_ids[] = {
        {"INT33A0", 0},
        {"", 0}
 };
+MODULE_DEVICE_TABLE(acpi, smartconnect_ids);
 
 static struct acpi_driver smartconnect_driver = {
        .owner = THIS_MODULE,
@@ -56,5 +42,3 @@ static struct acpi_driver smartconnect_driver = {
 };
 
 module_acpi_driver(smartconnect_driver);
-
-MODULE_DEVICE_TABLE(acpi, smartconnect_ids);
index c2257bd06f1863d848fc384b2ac5577294bef8f5..9ded8e2af312f23293a5a6a8a56a3c7b8d499c3e 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * WMI Thunderbolt driver
  *
  * Copyright (C) 2017 Dell Inc. All Rights Reserved.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  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
@@ -38,12 +30,16 @@ static ssize_t force_power_store(struct device *dev,
        input.length = sizeof(u8);
        input.pointer = &mode;
        mode = hex_to_bin(buf[0]);
+       dev_dbg(dev, "force_power: storing %#x\n", mode);
        if (mode == 0 || mode == 1) {
                status = wmi_evaluate_method(INTEL_WMI_THUNDERBOLT_GUID, 0, 1,
                                             &input, NULL);
-               if (ACPI_FAILURE(status))
+               if (ACPI_FAILURE(status)) {
+                       dev_dbg(dev, "force_power: failed to evaluate ACPI method\n");
                        return -ENODEV;
+               }
        } else {
+               dev_dbg(dev, "force_power: unsupported mode\n");
                return -EINVAL;
        }
        return count;
@@ -95,4 +91,4 @@ module_wmi_driver(intel_wmi_thunderbolt_driver);
 MODULE_ALIAS("wmi:" INTEL_WMI_THUNDERBOLT_GUID);
 MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>");
 MODULE_DESCRIPTION("Intel WMI Thunderbolt force power driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/intel_atomisp2_pm.c b/drivers/platform/x86/intel_atomisp2_pm.c
new file mode 100644 (file)
index 0000000..9371603
--- /dev/null
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Dummy driver for Intel's Image Signal Processor found on Bay and Cherry
+ * Trail devices. The sole purpose of this driver is to allow the ISP to
+ * be put in D3.
+ *
+ * Copyright (C) 2018 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on various non upstream patches for ISP support:
+ * Copyright (C) 2010-2017 Intel Corporation. All rights reserved.
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <asm/iosf_mbi.h>
+
+/* PCI configuration regs */
+#define PCI_INTERRUPT_CTRL             0x9c
+
+#define PCI_CSI_CONTROL                        0xe8
+#define PCI_CSI_CONTROL_PORTS_OFF_MASK 0x7
+
+/* IOSF BT_MBI_UNIT_PMC regs */
+#define ISPSSPM0                       0x39
+#define ISPSSPM0_ISPSSC_OFFSET         0
+#define ISPSSPM0_ISPSSC_MASK           0x00000003
+#define ISPSSPM0_ISPSSS_OFFSET         24
+#define ISPSSPM0_ISPSSS_MASK           0x03000000
+#define ISPSSPM0_IUNIT_POWER_ON                0x0
+#define ISPSSPM0_IUNIT_POWER_OFF       0x3
+
+static int isp_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       unsigned long timeout;
+       u32 val;
+
+       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, 0);
+
+       /*
+        * MRFLD IUNIT DPHY is located in an always-power-on island
+        * MRFLD HW design need all CSI ports are disabled before
+        * powering down the IUNIT.
+        */
+       pci_read_config_dword(dev, PCI_CSI_CONTROL, &val);
+       val |= PCI_CSI_CONTROL_PORTS_OFF_MASK;
+       pci_write_config_dword(dev, PCI_CSI_CONTROL, val);
+
+       /* Write 0x3 to ISPSSPM0 bit[1:0] to power off the IUNIT */
+       iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0,
+                       ISPSSPM0_IUNIT_POWER_OFF, ISPSSPM0_ISPSSC_MASK);
+
+       /*
+        * There should be no IUNIT access while power-down is
+        * in progress HW sighting: 4567865
+        * Wait up to 50 ms for the IUNIT to shut down.
+        */
+       timeout = jiffies + msecs_to_jiffies(50);
+       while (1) {
+               /* Wait until ISPSSPM0 bit[25:24] shows 0x3 */
+               iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &val);
+               val = (val & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET;
+               if (val == ISPSSPM0_IUNIT_POWER_OFF)
+                       break;
+
+               if (time_after(jiffies, timeout)) {
+                       dev_err(&dev->dev, "IUNIT power-off timeout.\n");
+                       return -EBUSY;
+               }
+               usleep_range(1000, 2000);
+       }
+
+       pm_runtime_allow(&dev->dev);
+       pm_runtime_put_sync_suspend(&dev->dev);
+
+       return 0;
+}
+
+static void isp_remove(struct pci_dev *dev)
+{
+       pm_runtime_get_sync(&dev->dev);
+       pm_runtime_forbid(&dev->dev);
+}
+
+static int isp_pci_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int isp_pci_resume(struct device *dev)
+{
+       return 0;
+}
+
+static UNIVERSAL_DEV_PM_OPS(isp_pm_ops, isp_pci_suspend,
+                           isp_pci_resume, NULL);
+
+static const struct pci_device_id isp_id_table[] = {
+       { PCI_VDEVICE(INTEL, 0x22b8), },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, isp_id_table);
+
+static struct pci_driver isp_pci_driver = {
+       .name = "intel_atomisp2_pm",
+       .id_table = isp_id_table,
+       .probe = isp_probe,
+       .remove = isp_remove,
+       .driver.pm = &isp_pm_ops,
+};
+
+module_pci_driver(isp_pci_driver);
+
+MODULE_DESCRIPTION("Intel AtomISP2 dummy / power-management drv (for suspend)");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL v2");
index 227943a20212cca12188cc18730bc42d6807da4e..951c105bafc1b8b1fc276ee04274690fd5f15f30 100644 (file)
@@ -1,21 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_bxtwc_tmu.c - Intel BXT Whiskey Cove PMIC TMU driver
+ * Intel BXT Whiskey Cove PMIC TMU driver
  *
  * Copyright (C) 2016 Intel Corporation. All rights reserved.
  *
  * This driver adds TMU (Time Management Unit) support for Intel BXT platform.
  * It enables the alarm wake-up functionality in the TMU unit of Whiskey Cove
  * PMIC.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * 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.
- *
  */
 
 #include <linux/module.h>
index f40b1c1921064b734614705c72dc212700f979fc..464fe93657b53e03268eabb2f41f5cdd0583d96e 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel Cherry Trail ACPI INT33FE pseudo device driver
  *
  * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * Some Intel Cherry Trail based device which ship with Windows 10, have
  * this weird INT33FE ACPI device with a CRS table with 4 I2cSerialBusV2
  * resources, for 4 different chips attached to various i2c busses:
@@ -257,4 +254,4 @@ module_platform_driver(cht_int33fe_driver);
 
 MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE pseudo device driver");
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index 38b8e7cfe88c06a68fa351b7048247324fc89e31..0df2e82dd24924bd6d92ff74f2434b4eb1f30d64 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Power-button driver for Dollar Cove TI PMIC
  * Copyright (C) 2014 Intel Corp
index e89ad4964dc139daec390560bfcecb145cdd5505..4b8f7305fc8a773b8a0e06291b69672ef559a7ab 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel INT0002 "Virtual GPIO" driver
  *
@@ -9,10 +10,6 @@
  *
  * Author: Dyut Kumar Sil <dyut.k.sil@intel.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * Some peripherals on Bay Trail and Cherry Trail platforms signal a Power
  * Management Event (PME) to the Power Management Controller (PMC) to wakeup
  * the system. When this happens software needs to clear the PME bus 0 status
 #define ICPU(model)    { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
 
 static const struct x86_cpu_id int0002_cpu_ids[] = {
-/*
- * Limit ourselves to Cherry Trail for now, until testing shows we
- * need to handle the INT0002 device on Baytrail too.
- *     ICPU(INTEL_FAM6_ATOM_SILVERMONT),        * Valleyview, Bay Trail *
- */
+       ICPU(INTEL_FAM6_ATOM_SILVERMONT),       /* Valleyview, Bay Trail  */
        ICPU(INTEL_FAM6_ATOM_AIRMONT),          /* Braswell, Cherry Trail */
        {}
 };
@@ -110,6 +103,21 @@ static void int0002_irq_mask(struct irq_data *data)
        outl(gpe_en_reg, GPE0A_EN_PORT);
 }
 
+static int int0002_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+       struct platform_device *pdev = to_platform_device(chip->parent);
+       int irq = platform_get_irq(pdev, 0);
+
+       /* Propagate to parent irq */
+       if (on)
+               enable_irq_wake(irq);
+       else
+               disable_irq_wake(irq);
+
+       return 0;
+}
+
 static irqreturn_t int0002_irq(int irq, void *data)
 {
        struct gpio_chip *chip = data;
@@ -132,6 +140,7 @@ static struct irq_chip int0002_irqchip = {
        .irq_ack                = int0002_irq_ack,
        .irq_mask               = int0002_irq_mask,
        .irq_unmask             = int0002_irq_unmask,
+       .irq_set_wake           = int0002_irq_set_wake,
 };
 
 static int int0002_probe(struct platform_device *pdev)
@@ -216,4 +225,4 @@ module_platform_driver(int0002_driver);
 
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_DESCRIPTION("Intel INT0002 Virtual GPIO driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index c5ece7ef08c6df36b2d1ccff788f99c3cb408abe..225638a1b09e45d762668615cc9de93a0db100ba 100644 (file)
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2009-2010 Intel Corporation
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
  * Authors:
  *     Jesse Barnes <jbarnes@virtuousgeek.org>
  */
@@ -1697,6 +1686,6 @@ static struct pci_driver ips_pci_driver = {
 
 module_pci_driver(ips_pci_driver);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Jesse Barnes <jbarnes@virtuousgeek.org>");
 MODULE_DESCRIPTION("Intelligent Power Sharing Driver");
index 60f4e3ddbe9f5b3f84e02030a57b98793141e615..512ad234ad0d67fccdb05d241d37fd887da164d5 100644 (file)
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2010 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
  */
 
 void ips_link_to_i915_driver(void);
index ef9b0af8cdd36a6adc68fb2f3b835993bfa46ebe..77eb8709c931c03dbeda565b71c65e8d6f1d564e 100644 (file)
@@ -1,25 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- *  intel_menlow.c - Intel menlow Driver for thermal management extension
+ *  Intel menlow Driver for thermal management extension
  *
  *  Copyright (C) 2008 Intel Corp
  *  Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
  *  Copyright (C) 2008 Zhang Rui <rui.zhang@intel.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; version 2 of the License.
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  *  This driver creates the sys I/F for programming the sensors.
  *  It also implements the driver for intel menlow memory controller (hardware
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/acpi.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/pm.h>
+#include <linux/slab.h>
 #include <linux/thermal.h>
-#include <linux/acpi.h>
+#include <linux/types.h>
 
 MODULE_AUTHOR("Thomas Sujith");
 MODULE_AUTHOR("Zhang Rui");
 MODULE_DESCRIPTION("Intel Menlow platform specific driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 
 /*
  * Memory controller device control
index 5ad44204a9c3c997bf237aacfb1bbb99ab292ef7..292bace83f1e3d95a8dae813370b1fc6610bc0df 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Power button driver for Intel MID platforms.
  *
@@ -5,18 +6,8 @@
  *
  * Author: Hong Liu <hong.liu@intel.com>
  * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.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; version 2 of the License.
- *
- * 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.
  */
 
-#include <linux/init.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/intel_msic.h>
@@ -121,12 +112,9 @@ static const struct mid_pb_ddata mrfld_ddata = {
        .setup  = mrfld_setup,
 };
 
-#define ICPU(model, ddata)     \
-       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (kernel_ulong_t)&ddata }
-
 static const struct x86_cpu_id mid_pb_cpu_ids[] = {
-       ICPU(INTEL_FAM6_ATOM_SALTWELL_MID,              mfld_ddata),
-       ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID,    mrfld_ddata),
+       INTEL_CPU_FAM6(ATOM_SALTWELL_MID,       mfld_ddata),
+       INTEL_CPU_FAM6(ATOM_SILVERMONT_MID,     mrfld_ddata),
        {}
 };
 
index 008a76903cbfb62221ac4fd4bb8aaa7b46c56fb1..f402e2e74a38392e9abf1eae8debc3630dcc828c 100644 (file)
@@ -1,39 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_mid_thermal.c - Intel MID platform thermal driver
+ * Intel MID platform thermal driver
  *
  * Copyright (C) 2011 Intel Corporation
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * 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; version 2 of the License.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  * Author: Durgadoss R <durgadoss.r@intel.com>
  */
 
 #define pr_fmt(fmt) "intel_mid_thermal: " fmt
 
-#include <linux/module.h>
-#include <linux/init.h>
+#include <linux/device.h>
 #include <linux/err.h>
+#include <linux/mfd/intel_msic.h>
+#include <linux/module.h>
 #include <linux/param.h>
-#include <linux/device.h>
 #include <linux/platform_device.h>
-#include <linux/slab.h>
 #include <linux/pm.h>
+#include <linux/slab.h>
 #include <linux/thermal.h>
-#include <linux/mfd/intel_msic.h>
 
 /* Number of thermal sensors */
 #define MSIC_THERMAL_SENSORS   4
@@ -567,4 +551,4 @@ module_platform_driver(mid_thermal_driver);
 
 MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
 MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index 5747f63c8d9f490c51edb31f5fc836ee89dab33f..3c0438ba385ee8494c14a4d24147201e04dcaee6 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
- * intel_oaktrail.c - Intel OakTrail Platform support.
+ * Intel OakTrail Platform support
  *
  * Copyright (C) 2010-2011 Intel Corporation
  * Author: Yin Kangkai (kangkai.yin@intel.com)
@@ -8,21 +9,6 @@
  * <cezary.jackiewicz (at) gmail.com>, based on MSI driver
  * Copyright (C) 2006 Lennart Poettering <mzxreary (at) 0pointer (dot) de>
  *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- *
  * This driver does below things:
  * 1. registers itself in the Linux backlight control in
  *    /sys/class/backlight/intel_oaktrail/
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/acpi.h>
-#include <linux/fb.h>
-#include <linux/mutex.h>
+#include <linux/backlight.h>
+#include <linux/dmi.h>
 #include <linux/err.h>
+#include <linux/fb.h>
 #include <linux/i2c.h>
-#include <linux/backlight.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/platform_device.h>
-#include <linux/dmi.h>
 #include <linux/rfkill.h>
+
 #include <acpi/video.h>
 
 #define DRIVER_NAME    "intel_oaktrail"
index 2d272a3e017621365de7d38dfbfa68bef7d73ab2..6b31d410cb09abeb57aec266a7896c4dbbec1dc3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel Core SoC Power Management Controller Driver
  *
@@ -6,16 +7,6 @@
  *
  * Authors: Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>
  *          Vishwanath Somayaji <vishwanath.somayaji@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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
index 93a7e99e1f8b8a0a8d241416c1540cc66c779f20..be045348ad86b2674c3b08b3c1af54b3844ea339 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel Core SoC Power Management Controller Header File
  *
@@ -6,16 +7,6 @@
  *
  * Authors: Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>
  *          Vishwanath Somayaji <vishwanath.somayaji@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
  */
 
 #ifndef PMC_CORE_H
index e7edc8c6393674dfdcfcf53cccb80da50fd255f2..7964ba22ef8d997d31e3cd83af9a56feb90dd088 100644 (file)
@@ -1,39 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_pmc_ipc.c: Driver for the Intel PMC IPC mechanism
+ * Driver for the Intel PMC IPC mechanism
  *
  * (C) Copyright 2014-2015 Intel Corporation
  *
- * This driver is based on Intel SCU IPC driver(intel_scu_opc.c) by
+ * This driver is based on Intel SCU IPC driver(intel_scu_ipc.c) by
  *     Sreedhara DS <sreedhara.ds@intel.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; version 2
- * of the License.
- *
  * PMC running in ARC processor communicates with other entity running in IA
  * core through IPC mechanism which in turn messaging between IA core ad PMC.
  */
 
-#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/atomic.h>
+#include <linux/bitops.h>
 #include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
 #include <linux/device.h>
-#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
-#include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/pm_qos.h>
-#include <linux/kernel.h>
-#include <linux/bitops.h>
 #include <linux/sched.h>
-#include <linux/atomic.h>
-#include <linux/notifier.h>
-#include <linux/suspend.h>
-#include <linux/acpi.h>
-#include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/spinlock.h>
+#include <linux/suspend.h>
 
 #include <asm/intel_pmc_ipc.h>
 
@@ -1029,7 +1024,7 @@ static void __exit intel_pmc_ipc_exit(void)
 
 MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>");
 MODULE_DESCRIPTION("Intel PMC IPC driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 
 /* Some modules are dependent on this, so init earlier */
 fs_initcall(intel_pmc_ipc_init);
index 2efeab650345c044371aa7c56624e4d650ea7c93..79671927f4ef6ada5833419c58a8aeb23fd1621f 100644 (file)
@@ -1,25 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Driver for the Intel P-Unit Mailbox IPC mechanism
  *
  * (C) Copyright 2015 Intel Corporation
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * The heart of the P-Unit is the Foxton microcontroller and its firmware,
  * which provide mailbox interface for power management usage.
  */
 
-#include <linux/module.h>
-#include <linux/mod_devicetable.h>
 #include <linux/acpi.h>
-#include <linux/delay.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
+
 #include <asm/intel_punit_ipc.h>
 
 /* IPC Mailbox registers */
index 75c8fef7a482c41717c69aa8ef98b21ef4dd1043..cdab916fbf92775320400d1879e112dfdc8e4034 100644 (file)
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_scu_ipc.c: Driver for the Intel SCU IPC mechanism
+ * Driver for the Intel SCU IPC mechanism
  *
  * (C) Copyright 2008-2010,2015 Intel Corporation
  * Author: Sreedhara DS (sreedhara.ds@intel.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; version 2
- * of the License.
- *
  * SCU running in ARC processor communicates with other entity running in IA
  * core through IPC mechanism which in turn messaging between IA core ad SCU.
  * SCU has two IPC mechanism IPC-1 and IPC-2. IPC-1 is used between IA32 and
  * IPC-1 Driver provides an API for power control unit registers (e.g. MSIC)
  * along with other APIs.
  */
+
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/device.h>
-#include <linux/pm.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
 #include <linux/sfi.h>
+
 #include <asm/intel-mid.h>
 #include <asm/intel_scu_ipc.h>
 
index aa454241489c9f541864f34828e19318514d3560..8afe6fa06d7b8d45a1f9f68e5483f1e191f62e91 100644 (file)
@@ -1,32 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_scu_ipc.c: Driver for the Intel SCU IPC mechanism
+ * Driver for the Intel SCU IPC mechanism
  *
  * (C) Copyright 2008-2010 Intel Corporation
  * Author: Sreedhara DS (sreedhara.ds@intel.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; version 2
- * of the License.
- *
- * This driver provides ioctl interfaces to call intel scu ipc driver api
+ * This driver provides IOCTL interfaces to call Intel SCU IPC driver API.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/fs.h>
 #include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
 #include <asm/intel_scu_ipc.h>
 
 static int major;
 
-/* ioctl commnds */
+/* IOCTL commands */
 #define        INTE_SCU_IPC_REGISTER_READ      0
 #define INTE_SCU_IPC_REGISTER_WRITE    1
 #define INTE_SCU_IPC_REGISTER_UPDATE   2
index f378621b5fe9d86632a853a33599b1efff88b05a..d4040bb222b485ead8c8caa8a1b3c4463e72dffa 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel SoC Core Telemetry Driver
  * Copyright (C) 2015, Intel Corporation.
  * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
  * Telemetry Framework provides platform related PM and performance statistics.
  * This file provides the core telemetry API implementation.
  */
@@ -460,4 +452,4 @@ module_exit(telemetry_module_exit);
 
 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
 MODULE_DESCRIPTION("Intel SoC Telemetry Interface");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index cee08f23629245803783734af6229ac18c69e3e6..40bce560eb30d9cf2ca1a348d7b1eece30d00616 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel SOC Telemetry debugfs Driver: Currently supports APL
  * Copyright (c) 2015, Intel Corporation.
  * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
  * This file provides the debugfs interfaces for telemetry.
  * /sys/kernel/debug/telemetry/pss_info: Shows Primary Control Sub-Sys Counters
  * /sys/kernel/debug/telemetry/ioss_info: Shows IO Sub-System Counters
@@ -72,9 +64,6 @@
 #define TELEM_IOSS_DX_D0IX_EVTS                25
 #define TELEM_IOSS_PG_EVTS             30
 
-#define TELEM_DEBUGFS_CPU(model, data) \
-       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&data}
-
 #define TELEM_CHECK_AND_PARSE_EVTS(EVTID, EVTNUM, BUF, EVTLOG, EVTDAT, MASK) { \
        if (evtlog[index].telem_evtid == (EVTID)) { \
                for (idx = 0; idx < (EVTNUM); idx++) \
@@ -319,8 +308,8 @@ static struct telemetry_debugfs_conf telem_apl_debugfs_conf = {
 };
 
 static const struct x86_cpu_id telemetry_debugfs_cpu_ids[] = {
-       TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT, telem_apl_debugfs_conf),
-       TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, telem_apl_debugfs_conf),
+       INTEL_CPU_FAM6(ATOM_GOLDMONT, telem_apl_debugfs_conf),
+       INTEL_CPU_FAM6(ATOM_GOLDMONT_PLUS, telem_apl_debugfs_conf),
        {}
 };
 
@@ -951,12 +940,16 @@ static int __init telemetry_debugfs_init(void)
        debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data;
 
        err = telemetry_pltconfig_valid();
-       if (err < 0)
+       if (err < 0) {
+               pr_info("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n");
                return -ENODEV;
+       }
 
        err = telemetry_debugfs_check_evts();
-       if (err < 0)
+       if (err < 0) {
+               pr_info("telemetry_debugfs_check_evts failed\n");
                return -EINVAL;
+       }
 
        register_pm_notifier(&pm_notifier);
 
@@ -1037,4 +1030,4 @@ module_exit(telemetry_debugfs_exit);
 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
 MODULE_DESCRIPTION("Intel SoC Telemetry debugfs Interface");
 MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index fcc6bee51a422a1c95e205f0d2874fc746ed09e2..df8565bad595c72ba7b889a7d50afe2e0e75d9c6 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel SOC Telemetry Platform Driver: Currently supports APL
  * Copyright (c) 2015, Intel Corporation.
  * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
  * This file provides the platform specific telemetry implementation for APL.
  * It used the PUNIT and PMC IPC interfaces for configuring the counters.
  * The accumulated results are fetched from SRAM.
@@ -1242,4 +1234,4 @@ module_exit(telemetry_module_exit);
 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
 MODULE_DESCRIPTION("Intel SoC Telemetry Platform Driver");
 MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index a6d5aa0c3c479dbd7f345a3f5666ae0ef72e456d..7b9cc841ab6557157a71691cf131cd43cc7ecb9c 100644 (file)
@@ -1,28 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel Turbo Boost Max Technology 3.0 legacy (non HWP) enumeration driver
  * Copyright (c) 2017, Intel Corporation.
  * All rights reserved.
  *
  * Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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/cpufeature.h>
+#include <linux/cpuhotplug.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/topology.h>
 #include <linux/workqueue.h>
-#include <linux/cpuhotplug.h>
-#include <linux/cpufeature.h>
+
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 
diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c
new file mode 100644 (file)
index 0000000..c0bb1f8
--- /dev/null
@@ -0,0 +1,700 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * lg-laptop.c - LG Gram ACPI features and hotkeys Driver
+ *
+ * Copyright (C) 2018 Matan Ziv-Av <matan@svgalib.org>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/acpi.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#define LED_DEVICE(_name, max) struct led_classdev _name = { \
+       .name           = __stringify(_name),   \
+       .max_brightness = max,                  \
+       .brightness_set = _name##_set,          \
+       .brightness_get = _name##_get,          \
+}
+
+MODULE_AUTHOR("Matan Ziv-Av");
+MODULE_DESCRIPTION("LG WMI Hotkey Driver");
+MODULE_LICENSE("GPL");
+
+#define WMI_EVENT_GUID0        "E4FB94F9-7F2B-4173-AD1A-CD1D95086248"
+#define WMI_EVENT_GUID1        "023B133E-49D1-4E10-B313-698220140DC2"
+#define WMI_EVENT_GUID2        "37BE1AC0-C3F2-4B1F-BFBE-8FDEAF2814D6"
+#define WMI_EVENT_GUID3        "911BAD44-7DF8-4FBB-9319-BABA1C4B293B"
+#define WMI_METHOD_WMAB "C3A72B38-D3EF-42D3-8CBB-D5A57049F66D"
+#define WMI_METHOD_WMBB "2B4F501A-BD3C-4394-8DCF-00A7D2BC8210"
+#define WMI_EVENT_GUID  WMI_EVENT_GUID0
+
+#define WMAB_METHOD     "\\XINI.WMAB"
+#define WMBB_METHOD     "\\XINI.WMBB"
+#define SB_GGOV_METHOD  "\\_SB.GGOV"
+#define GOV_TLED        0x2020008
+#define WM_GET          1
+#define WM_SET          2
+#define WM_KEY_LIGHT    0x400
+#define WM_TLED         0x404
+#define WM_FN_LOCK      0x407
+#define WM_BATT_LIMIT   0x61
+#define WM_READER_MODE  0xBF
+#define WM_FAN_MODE    0x33
+#define WMBB_USB_CHARGE 0x10B
+#define WMBB_BATT_LIMIT 0x10C
+
+#define PLATFORM_NAME   "lg-laptop"
+
+MODULE_ALIAS("wmi:" WMI_EVENT_GUID0);
+MODULE_ALIAS("wmi:" WMI_EVENT_GUID1);
+MODULE_ALIAS("wmi:" WMI_EVENT_GUID2);
+MODULE_ALIAS("wmi:" WMI_EVENT_GUID3);
+MODULE_ALIAS("wmi:" WMI_METHOD_WMAB);
+MODULE_ALIAS("wmi:" WMI_METHOD_WMBB);
+MODULE_ALIAS("acpi*:LGEX0815:*");
+
+static struct platform_device *pf_device;
+static struct input_dev *wmi_input_dev;
+
+static u32 inited;
+#define INIT_INPUT_WMI_0        0x01
+#define INIT_INPUT_WMI_2        0x02
+#define INIT_INPUT_ACPI         0x04
+#define INIT_TPAD_LED           0x08
+#define INIT_KBD_LED            0x10
+#define INIT_SPARSE_KEYMAP        0x80
+
+static const struct key_entry wmi_keymap[] = {
+       {KE_KEY, 0x70, {KEY_F15} },      /* LG control panel (F1) */
+       {KE_KEY, 0x74, {KEY_F13} },      /* Touchpad toggle (F5) */
+       {KE_KEY, 0xf020000, {KEY_F14} }, /* Read mode (F9) */
+       {KE_KEY, 0x10000000, {KEY_F16} },/* Keyboard backlight (F8) - pressing
+                                         * this key both sends an event and
+                                         * changes backlight level.
+                                         */
+       {KE_KEY, 0x80, {KEY_RFKILL} },
+       {KE_END, 0}
+};
+
+static int ggov(u32 arg0)
+{
+       union acpi_object args[1];
+       union acpi_object *r;
+       acpi_status status;
+       acpi_handle handle;
+       struct acpi_object_list arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       int res;
+
+       args[0].type = ACPI_TYPE_INTEGER;
+       args[0].integer.value = arg0;
+
+       status = acpi_get_handle(NULL, (acpi_string) SB_GGOV_METHOD, &handle);
+       if (ACPI_FAILURE(status)) {
+               pr_err("Cannot get handle");
+               return -ENODEV;
+       }
+
+       arg.count = 1;
+       arg.pointer = args;
+
+       status = acpi_evaluate_object(handle, NULL, &arg, &buffer);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_err(handle, "GGOV: call failed.\n");
+               return -EINVAL;
+       }
+
+       r = buffer.pointer;
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EINVAL;
+       }
+
+       res = r->integer.value;
+       kfree(r);
+
+       return res;
+}
+
+static union acpi_object *lg_wmab(u32 method, u32 arg1, u32 arg2)
+{
+       union acpi_object args[3];
+       acpi_status status;
+       acpi_handle handle;
+       struct acpi_object_list arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+       args[0].type = ACPI_TYPE_INTEGER;
+       args[0].integer.value = method;
+       args[1].type = ACPI_TYPE_INTEGER;
+       args[1].integer.value = arg1;
+       args[2].type = ACPI_TYPE_INTEGER;
+       args[2].integer.value = arg2;
+
+       status = acpi_get_handle(NULL, (acpi_string) WMAB_METHOD, &handle);
+       if (ACPI_FAILURE(status)) {
+               pr_err("Cannot get handle");
+               return NULL;
+       }
+
+       arg.count = 3;
+       arg.pointer = args;
+
+       status = acpi_evaluate_object(handle, NULL, &arg, &buffer);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_err(handle, "WMAB: call failed.\n");
+               return NULL;
+       }
+
+       return buffer.pointer;
+}
+
+static union acpi_object *lg_wmbb(u32 method_id, u32 arg1, u32 arg2)
+{
+       union acpi_object args[3];
+       acpi_status status;
+       acpi_handle handle;
+       struct acpi_object_list arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       u8 buf[32];
+
+       *(u32 *)buf = method_id;
+       *(u32 *)(buf + 4) = arg1;
+       *(u32 *)(buf + 16) = arg2;
+       args[0].type = ACPI_TYPE_INTEGER;
+       args[0].integer.value = 0; /* ignored */
+       args[1].type = ACPI_TYPE_INTEGER;
+       args[1].integer.value = 1; /* Must be 1 or 2. Does not matter which */
+       args[2].type = ACPI_TYPE_BUFFER;
+       args[2].buffer.length = 32;
+       args[2].buffer.pointer = buf;
+
+       status = acpi_get_handle(NULL, (acpi_string)WMBB_METHOD, &handle);
+       if (ACPI_FAILURE(status)) {
+               pr_err("Cannot get handle");
+               return NULL;
+       }
+
+       arg.count = 3;
+       arg.pointer = args;
+
+       status = acpi_evaluate_object(handle, NULL, &arg, &buffer);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_err(handle, "WMAB: call failed.\n");
+               return NULL;
+       }
+
+       return (union acpi_object *)buffer.pointer;
+}
+
+static void wmi_notify(u32 value, void *context)
+{
+       struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+       long data = (long)context;
+
+       pr_debug("event guid %li\n", data);
+       status = wmi_get_event_data(value, &response);
+       if (ACPI_FAILURE(status)) {
+               pr_err("Bad event status 0x%x\n", status);
+               return;
+       }
+
+       obj = (union acpi_object *)response.pointer;
+       if (!obj)
+               return;
+
+       if (obj->type == ACPI_TYPE_INTEGER) {
+               int eventcode = obj->integer.value;
+               struct key_entry *key;
+
+               key =
+                   sparse_keymap_entry_from_scancode(wmi_input_dev, eventcode);
+               if (key && key->type == KE_KEY)
+                       sparse_keymap_report_entry(wmi_input_dev, key, 1, true);
+       }
+
+       pr_debug("Type: %i    Eventcode: 0x%llx\n", obj->type,
+                obj->integer.value);
+       kfree(response.pointer);
+}
+
+static void wmi_input_setup(void)
+{
+       acpi_status status;
+
+       wmi_input_dev = input_allocate_device();
+       if (wmi_input_dev) {
+               wmi_input_dev->name = "LG WMI hotkeys";
+               wmi_input_dev->phys = "wmi/input0";
+               wmi_input_dev->id.bustype = BUS_HOST;
+
+               if (sparse_keymap_setup(wmi_input_dev, wmi_keymap, NULL) ||
+                   input_register_device(wmi_input_dev)) {
+                       pr_info("Cannot initialize input device");
+                       input_free_device(wmi_input_dev);
+                       return;
+               }
+
+               inited |= INIT_SPARSE_KEYMAP;
+               status = wmi_install_notify_handler(WMI_EVENT_GUID0, wmi_notify,
+                                                   (void *)0);
+               if (ACPI_SUCCESS(status))
+                       inited |= INIT_INPUT_WMI_0;
+
+               status = wmi_install_notify_handler(WMI_EVENT_GUID2, wmi_notify,
+                                                   (void *)2);
+               if (ACPI_SUCCESS(status))
+                       inited |= INIT_INPUT_WMI_2;
+       } else {
+               pr_info("Cannot allocate input device");
+       }
+}
+
+static void acpi_notify(struct acpi_device *device, u32 event)
+{
+       struct key_entry *key;
+
+       acpi_handle_debug(device->handle, "notify: %d\n", event);
+       if (inited & INIT_SPARSE_KEYMAP) {
+               key = sparse_keymap_entry_from_scancode(wmi_input_dev, 0x80);
+               if (key && key->type == KE_KEY)
+                       sparse_keymap_report_entry(wmi_input_dev, key, 1, true);
+       }
+}
+
+static ssize_t fan_mode_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buffer, size_t count)
+{
+       bool value;
+       union acpi_object *r;
+       u32 m;
+       int ret;
+
+       ret = kstrtobool(buffer, &value);
+       if (ret)
+               return ret;
+
+       r = lg_wmab(WM_FAN_MODE, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       m = r->integer.value;
+       kfree(r);
+       r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xffffff0f) | (value << 4));
+       kfree(r);
+       r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xfffffff0) | value);
+       kfree(r);
+
+       return count;
+}
+
+static ssize_t fan_mode_show(struct device *dev,
+                            struct device_attribute *attr, char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmab(WM_FAN_MODE, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = r->integer.value & 0x01;
+       kfree(r);
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static ssize_t usb_charge_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buffer, size_t count)
+{
+       bool value;
+       union acpi_object *r;
+       int ret;
+
+       ret = kstrtobool(buffer, &value);
+       if (ret)
+               return ret;
+
+       r = lg_wmbb(WMBB_USB_CHARGE, WM_SET, value);
+       if (!r)
+               return -EIO;
+
+       kfree(r);
+       return count;
+}
+
+static ssize_t usb_charge_show(struct device *dev,
+                              struct device_attribute *attr, char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmbb(WMBB_USB_CHARGE, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_BUFFER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = !!r->buffer.pointer[0x10];
+
+       kfree(r);
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static ssize_t reader_mode_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buffer, size_t count)
+{
+       bool value;
+       union acpi_object *r;
+       int ret;
+
+       ret = kstrtobool(buffer, &value);
+       if (ret)
+               return ret;
+
+       r = lg_wmab(WM_READER_MODE, WM_SET, value);
+       if (!r)
+               return -EIO;
+
+       kfree(r);
+       return count;
+}
+
+static ssize_t reader_mode_show(struct device *dev,
+                               struct device_attribute *attr, char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmab(WM_READER_MODE, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = !!r->integer.value;
+
+       kfree(r);
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static ssize_t fn_lock_store(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buffer, size_t count)
+{
+       bool value;
+       union acpi_object *r;
+       int ret;
+
+       ret = kstrtobool(buffer, &value);
+       if (ret)
+               return ret;
+
+       r = lg_wmab(WM_FN_LOCK, WM_SET, value);
+       if (!r)
+               return -EIO;
+
+       kfree(r);
+       return count;
+}
+
+static ssize_t fn_lock_show(struct device *dev,
+                           struct device_attribute *attr, char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmab(WM_FN_LOCK, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_BUFFER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = !!r->buffer.pointer[0];
+       kfree(r);
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static ssize_t battery_care_limit_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buffer, size_t count)
+{
+       unsigned long value;
+       int ret;
+
+       ret = kstrtoul(buffer, 10, &value);
+       if (ret)
+               return ret;
+
+       if (value == 100 || value == 80) {
+               union acpi_object *r;
+
+               r = lg_wmab(WM_BATT_LIMIT, WM_SET, value);
+               if (!r)
+                       return -EIO;
+
+               kfree(r);
+               return count;
+       }
+
+       return -EINVAL;
+}
+
+static ssize_t battery_care_limit_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmab(WM_BATT_LIMIT, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = r->integer.value;
+       kfree(r);
+       if (status != 80 && status != 100)
+               status = 0;
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static DEVICE_ATTR_RW(fan_mode);
+static DEVICE_ATTR_RW(usb_charge);
+static DEVICE_ATTR_RW(reader_mode);
+static DEVICE_ATTR_RW(fn_lock);
+static DEVICE_ATTR_RW(battery_care_limit);
+
+static struct attribute *dev_attributes[] = {
+       &dev_attr_fan_mode.attr,
+       &dev_attr_usb_charge.attr,
+       &dev_attr_reader_mode.attr,
+       &dev_attr_fn_lock.attr,
+       &dev_attr_battery_care_limit.attr,
+       NULL
+};
+
+static const struct attribute_group dev_attribute_group = {
+       .attrs = dev_attributes,
+};
+
+static void tpad_led_set(struct led_classdev *cdev,
+                        enum led_brightness brightness)
+{
+       union acpi_object *r;
+
+       r = lg_wmab(WM_TLED, WM_SET, brightness > LED_OFF);
+       kfree(r);
+}
+
+static enum led_brightness tpad_led_get(struct led_classdev *cdev)
+{
+       return ggov(GOV_TLED) > 0 ? LED_ON : LED_OFF;
+}
+
+static LED_DEVICE(tpad_led, 1);
+
+static void kbd_backlight_set(struct led_classdev *cdev,
+                             enum led_brightness brightness)
+{
+       u32 val;
+       union acpi_object *r;
+
+       val = 0x22;
+       if (brightness <= LED_OFF)
+               val = 0;
+       if (brightness >= LED_FULL)
+               val = 0x24;
+       r = lg_wmab(WM_KEY_LIGHT, WM_SET, val);
+       kfree(r);
+}
+
+static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
+{
+       union acpi_object *r;
+       int val;
+
+       r = lg_wmab(WM_KEY_LIGHT, WM_GET, 0);
+
+       if (!r)
+               return LED_OFF;
+
+       if (r->type != ACPI_TYPE_BUFFER || r->buffer.pointer[1] != 0x05) {
+               kfree(r);
+               return LED_OFF;
+       }
+
+       switch (r->buffer.pointer[0] & 0x27) {
+       case 0x24:
+               val = LED_FULL;
+               break;
+       case 0x22:
+               val = LED_HALF;
+               break;
+       default:
+               val = LED_OFF;
+       }
+
+       kfree(r);
+
+       return val;
+}
+
+static LED_DEVICE(kbd_backlight, 255);
+
+static void wmi_input_destroy(void)
+{
+       if (inited & INIT_INPUT_WMI_2)
+               wmi_remove_notify_handler(WMI_EVENT_GUID2);
+
+       if (inited & INIT_INPUT_WMI_0)
+               wmi_remove_notify_handler(WMI_EVENT_GUID0);
+
+       if (inited & INIT_SPARSE_KEYMAP)
+               input_unregister_device(wmi_input_dev);
+
+       inited &= ~(INIT_INPUT_WMI_0 | INIT_INPUT_WMI_2 | INIT_SPARSE_KEYMAP);
+}
+
+static struct platform_driver pf_driver = {
+       .driver = {
+                  .name = PLATFORM_NAME,
+       }
+};
+
+static int acpi_add(struct acpi_device *device)
+{
+       int ret;
+
+       if (pf_device)
+               return 0;
+
+       ret = platform_driver_register(&pf_driver);
+       if (ret)
+               return ret;
+
+       pf_device = platform_device_register_simple(PLATFORM_NAME,
+                                                   PLATFORM_DEVID_NONE,
+                                                   NULL, 0);
+       if (IS_ERR(pf_device)) {
+               ret = PTR_ERR(pf_device);
+               pf_device = NULL;
+               pr_err("unable to register platform device\n");
+               goto out_platform_registered;
+       }
+
+       ret = sysfs_create_group(&pf_device->dev.kobj, &dev_attribute_group);
+       if (ret)
+               goto out_platform_device;
+
+       if (!led_classdev_register(&pf_device->dev, &kbd_backlight))
+               inited |= INIT_KBD_LED;
+
+       if (!led_classdev_register(&pf_device->dev, &tpad_led))
+               inited |= INIT_TPAD_LED;
+
+       wmi_input_setup();
+
+       return 0;
+
+out_platform_device:
+       platform_device_unregister(pf_device);
+out_platform_registered:
+       platform_driver_unregister(&pf_driver);
+       return ret;
+}
+
+static int acpi_remove(struct acpi_device *device)
+{
+       sysfs_remove_group(&pf_device->dev.kobj, &dev_attribute_group);
+       if (inited & INIT_KBD_LED)
+               led_classdev_unregister(&kbd_backlight);
+
+       if (inited & INIT_TPAD_LED)
+               led_classdev_unregister(&tpad_led);
+
+       wmi_input_destroy();
+       platform_device_unregister(pf_device);
+       pf_device = NULL;
+       platform_driver_unregister(&pf_driver);
+
+       return 0;
+}
+
+static const struct acpi_device_id device_ids[] = {
+       {"LGEX0815", 0},
+       {"", 0}
+};
+MODULE_DEVICE_TABLE(acpi, device_ids);
+
+static struct acpi_driver acpi_driver = {
+       .name = "LG Gram Laptop Support",
+       .class = "lg-laptop",
+       .ids = device_ids,
+       .ops = {
+               .add = acpi_add,
+               .remove = acpi_remove,
+               .notify = acpi_notify,
+               },
+       .owner = THIS_MODULE,
+};
+
+static int __init acpi_init(void)
+{
+       int result;
+
+       result = acpi_bus_register_driver(&acpi_driver);
+       if (result < 0) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering driver\n"));
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void __exit acpi_exit(void)
+{
+       acpi_bus_unregister_driver(&acpi_driver);
+}
+
+module_init(acpi_init);
+module_exit(acpi_exit);
index d89936c93ba0fe069900d739e6f8d8ac1e02f902..c2c3a1a19879596bd905952a9e028e96ea7cba01 100644 (file)
@@ -575,7 +575,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = {
 
 static
 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = {
-       .items = mlxplat_mlxcpld_msn21xx_items,
+       .items = mlxplat_mlxcpld_msn201x_items,
        .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items),
        .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
        .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
index cb204f9734913a4cc40b656bb125f8ac1e3c22b4..5f2d7ea912b56e89beb0fa75f8d502e1ef3e9f99 100644 (file)
@@ -42,10 +42,13 @@ static const struct ts_dmi_data chuwi_hi8_data = {
 };
 
 static const struct property_entry chuwi_hi8_pro_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 6),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 3),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
@@ -56,6 +59,8 @@ static const struct ts_dmi_data chuwi_hi8_pro_data = {
 };
 
 static const struct property_entry chuwi_vi8_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 4),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 6),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1724),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
@@ -88,9 +93,9 @@ static const struct ts_dmi_data chuwi_vi10_data = {
 
 static const struct property_entry connect_tablet9_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-min-x", 9),
-       PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 10),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1664),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 878),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
        PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-connect-tablet9.fw"),
@@ -104,8 +109,10 @@ static const struct ts_dmi_data connect_tablet9_data = {
 };
 
 static const struct property_entry cube_iwork8_air_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 3),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1664),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 896),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
@@ -179,11 +186,14 @@ static const struct ts_dmi_data gp_electronic_t701_data = {
 };
 
 static const struct property_entry itworks_tw891_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 5),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 890),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 896),
        PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-itworks-tw891.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        { }
 };
 
@@ -207,8 +217,10 @@ static const struct ts_dmi_data jumper_ezpad_6_pro_data = {
 };
 
 static const struct property_entry jumper_ezpad_mini3_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 23),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1138),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
@@ -237,6 +249,24 @@ static const struct ts_dmi_data onda_obook_20_plus_data = {
        .properties     = onda_obook_20_plus_props,
 };
 
+static const struct property_entry onda_v80_plus_v3_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 22),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 15),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1698),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl3676-onda-v80-plus-v3.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       { }
+};
+
+static const struct ts_dmi_data onda_v80_plus_v3_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = onda_v80_plus_v3_props,
+};
+
 static const struct property_entry onda_v820w_32g_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
@@ -322,11 +352,14 @@ static const struct ts_dmi_data pov_mobii_wintab_p800w_v20_data = {
 };
 
 static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1794),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name",
                              "gsl3692-pov-mobii-wintab-p800w.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
@@ -366,6 +399,22 @@ static const struct ts_dmi_data teclast_x98plus2_data = {
        .properties     = teclast_x98plus2_props,
 };
 
+static const struct property_entry trekstor_primebook_c11_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1970),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1530),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl1680-trekstor-primebook-c11.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       { }
+};
+
+static const struct ts_dmi_data trekstor_primebook_c11_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = trekstor_primebook_c11_props,
+};
+
 static const struct property_entry trekstor_primebook_c13_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 2624),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
@@ -381,6 +430,22 @@ static const struct ts_dmi_data trekstor_primebook_c13_data = {
        .properties     = trekstor_primebook_c13_props,
 };
 
+static const struct property_entry trekstor_primetab_t13b_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 2500),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1900),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl1680-trekstor-primetab-t13b.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+       { }
+};
+
+static const struct ts_dmi_data trekstor_primetab_t13b_data = {
+       .acpi_name  = "MSSL1680:00",
+       .properties = trekstor_primetab_t13b_props,
+};
+
 static const struct property_entry trekstor_surftab_twin_10_1_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1900),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
@@ -397,6 +462,8 @@ static const struct ts_dmi_data trekstor_surftab_twin_10_1_data = {
 };
 
 static const struct property_entry trekstor_surftab_wintron70_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 12),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 884),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 632),
        PROPERTY_ENTRY_STRING("firmware-name",
@@ -555,6 +622,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "OBOOK 20 PLUS"),
                },
        },
+       {
+               /* ONDA V80 plus v3 (P80PSBG9V3A01501) */
+               .driver_data = (void *)&onda_v80_plus_v3_data,
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONDA"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "V80 PLUS")
+               },
+       },
        {
                /* ONDA V820w DualOS */
                .driver_data = (void *)&onda_v820w_32g_data,
@@ -640,6 +715,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
                },
        },
+       {
+               /* Trekstor Primebook C11 */
+               .driver_data = (void *)&trekstor_primebook_c11_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C11"),
+               },
+       },
        {
                /* Trekstor Primebook C13 */
                .driver_data = (void *)&trekstor_primebook_c13_data,
@@ -648,6 +731,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
                },
        },
+       {
+               /* Trekstor Primetab T13B */
+               .driver_data = (void *)&trekstor_primetab_t13b_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Primetab T13B"),
+               },
+       },
        {
                /* TrekStor SurfTab twin 10.1 ST10432-8 */
                .driver_data = (void *)&trekstor_surftab_twin_10_1_data,
index 04791ea5d97b69f9ed9fc30fb7de46cf2370acbe..bea35be68706d733cf156b993fe0a8b3d3a675e5 100644 (file)
@@ -987,19 +987,19 @@ static struct bus_type wmi_bus_type = {
        .remove = wmi_dev_remove,
 };
 
-static struct device_type wmi_type_event = {
+static const struct device_type wmi_type_event = {
        .name = "event",
        .groups = wmi_event_groups,
        .release = wmi_dev_release,
 };
 
-static struct device_type wmi_type_method = {
+static const struct device_type wmi_type_method = {
        .name = "method",
        .groups = wmi_method_groups,
        .release = wmi_dev_release,
 };
 
-static struct device_type wmi_type_data = {
+static const struct device_type wmi_type_data = {
        .name = "data",
        .groups = wmi_data_groups,
        .release = wmi_dev_release,
index f52008bb8df76e2760dce41a656be7407aff4738..3a5f81a66d34f0b5d19d09d16f9e07451e7958ff 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/sched/mm.h>
 #include <linux/sched/signal.h>
 #include <linux/interval_tree_generic.h>
+#include <linux/nospec.h>
 
 #include "vhost.h"
 
@@ -1387,6 +1388,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg
        if (idx >= d->nvqs)
                return -ENOBUFS;
 
+       idx = array_index_nospec(idx, d->nvqs);
        vq = d->vqs[idx];
 
        mutex_lock(&vq->mutex);
index 2c9756bd9c4cdc4b07ac9e8f6158480b0e58d88f..b2488055fd1d18a5e2986fe9fb27ec4b4bf572df 100644 (file)
 /* Error Codes */
 enum virtchnl_status_code {
        VIRTCHNL_STATUS_SUCCESS                         = 0,
-       VIRTCHNL_ERR_PARAM                              = -5,
+       VIRTCHNL_STATUS_ERR_PARAM                       = -5,
+       VIRTCHNL_STATUS_ERR_NO_MEMORY                   = -18,
        VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH             = -38,
        VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR             = -39,
        VIRTCHNL_STATUS_ERR_INVALID_VF_ID               = -40,
-       VIRTCHNL_STATUS_NOT_SUPPORTED                   = -64,
+       VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR           = -53,
+       VIRTCHNL_STATUS_ERR_NOT_SUPPORTED               = -64,
 };
 
+/* Backward compatibility */
+#define VIRTCHNL_ERR_PARAM VIRTCHNL_STATUS_ERR_PARAM
+#define VIRTCHNL_STATUS_NOT_SUPPORTED VIRTCHNL_STATUS_ERR_NOT_SUPPORTED
+
 #define VIRTCHNL_LINK_SPEED_100MB_SHIFT                0x1
 #define VIRTCHNL_LINK_SPEED_1000MB_SHIFT       0x2
 #define VIRTCHNL_LINK_SPEED_10GB_SHIFT         0x3
@@ -831,7 +837,7 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
        case VIRTCHNL_OP_EVENT:
        case VIRTCHNL_OP_UNKNOWN:
        default:
-               return VIRTCHNL_ERR_PARAM;
+               return VIRTCHNL_STATUS_ERR_PARAM;
        }
        /* few more checks */
        if (err_msg_format || valid_len != msglen)
index 9e8056ec20faab8c3ffd4e99843a166ace95a0a1..d93e89761a8b429c2b5568688b7bf388e5b977d7 100644 (file)
@@ -51,6 +51,9 @@ struct bpf_reg_state {
                 *   PTR_TO_MAP_VALUE_OR_NULL
                 */
                struct bpf_map *map_ptr;
+
+               /* Max size from any of the above. */
+               unsigned long raw;
        };
        /* Fixed part of pointer offset, pointer types only */
        s32 off;
index c759d1cbcedd8d7f19f835457641dee9761a0fa0..a64f21a97369a5a7f8eb35c5a5040d359ffd6681 100644 (file)
@@ -37,7 +37,9 @@ struct in_device {
        unsigned long           mr_v1_seen;
        unsigned long           mr_v2_seen;
        unsigned long           mr_maxdelay;
-       unsigned char           mr_qrv;
+       unsigned long           mr_qi;          /* Query Interval */
+       unsigned long           mr_qri;         /* Query Response Interval */
+       unsigned char           mr_qrv;         /* Query Robustness Variable */
        unsigned char           mr_gq_running;
        unsigned char           mr_ifc_count;
        struct timer_list       mr_gq_timer;    /* general query timer */
index 20949dde35cdff149f259a526e2fadb8fa9f3a34..e44e3ec8a9c7d0e4c389a4c65360dbc3e14ab86a 100644 (file)
@@ -36,7 +36,7 @@
  * I2C requires 1 additional byte for requests.
  * I2C requires 2 additional bytes for responses.
  * SPI requires up to 32 additional bytes for responses.
- * */
+ */
 #define EC_PROTO_VERSION_UNKNOWN       0
 #define EC_MAX_REQUEST_OVERHEAD                1
 #define EC_MAX_RESPONSE_OVERHEAD       32
@@ -58,13 +58,14 @@ enum {
        EC_MAX_MSG_BYTES                = 64 * 1024,
 };
 
-/*
- * @version: Command version number (often 0)
- * @command: Command to send (EC_CMD_...)
- * @outsize: Outgoing length in bytes
- * @insize: Max number of bytes to accept from EC
- * @result: EC's response to the command (separate from communication failure)
- * @data: Where to put the incoming data from EC and outgoing data to EC
+/**
+ * struct cros_ec_command - Information about a ChromeOS EC command.
+ * @version: Command version number (often 0).
+ * @command: Command to send (EC_CMD_...).
+ * @outsize: Outgoing length in bytes.
+ * @insize: Max number of bytes to accept from the EC.
+ * @result: EC's response to the command (separate from communication failure).
+ * @data: Where to put the incoming data from EC and outgoing data to EC.
  */
 struct cros_ec_command {
        uint32_t version;
@@ -76,48 +77,55 @@ struct cros_ec_command {
 };
 
 /**
- * struct cros_ec_device - Information about a ChromeOS EC device
- *
- * @phys_name: name of physical comms layer (e.g. 'i2c-4')
+ * struct cros_ec_device - Information about a ChromeOS EC device.
+ * @phys_name: Name of physical comms layer (e.g. 'i2c-4').
  * @dev: Device pointer for physical comms device
- * @was_wake_device: true if this device was set to wake the system from
- * sleep at the last suspend
- * @cmd_readmem: direct read of the EC memory-mapped region, if supported
- *     @offset is within EC_LPC_ADDR_MEMMAP region.
- *     @bytes: number of bytes to read. zero means "read a string" (including
- *     the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be read.
- *     Caller must ensure that the buffer is large enough for the result when
- *     reading a string.
- *
- * @priv: Private data
- * @irq: Interrupt to use
- * @id: Device id
- * @din: input buffer (for data from EC)
- * @dout: output buffer (for data to EC)
- * \note
- * These two buffers will always be dword-aligned and include enough
- * space for up to 7 word-alignment bytes also, so we can ensure that
- * the body of the message is always dword-aligned (64-bit).
- * We use this alignment to keep ARM and x86 happy. Probably word
- * alignment would be OK, there might be a small performance advantage
- * to using dword.
- * @din_size: size of din buffer to allocate (zero to use static din)
- * @dout_size: size of dout buffer to allocate (zero to use static dout)
- * @wake_enabled: true if this device can wake the system from sleep
- * @suspended: true if this device had been suspended
- * @cmd_xfer: send command to EC and get response
- *     Returns the number of bytes received if the communication succeeded, but
- *     that doesn't mean the EC was happy with the command. The caller
- *     should check msg.result for the EC's result code.
- * @pkt_xfer: send packet to EC and get response
- * @lock: one transaction at a time
- * @mkbp_event_supported: true if this EC supports the MKBP event protocol.
- * @event_notifier: interrupt event notifier for transport devices.
- * @event_data: raw payload transferred with the MKBP event.
- * @event_size: size in bytes of the event data.
+ * @was_wake_device: True if this device was set to wake the system from
+ *                   sleep at the last suspend.
+ * @cros_class: The class structure for this device.
+ * @cmd_readmem: Direct read of the EC memory-mapped region, if supported.
+ *     @offset: Is within EC_LPC_ADDR_MEMMAP region.
+ *     @bytes: Number of bytes to read. zero means "read a string" (including
+ *             the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be
+ *             read. Caller must ensure that the buffer is large enough for the
+ *             result when reading a string.
+ * @max_request: Max size of message requested.
+ * @max_response: Max size of message response.
+ * @max_passthru: Max sice of passthru message.
+ * @proto_version: The protocol version used for this device.
+ * @priv: Private data.
+ * @irq: Interrupt to use.
+ * @id: Device id.
+ * @din: Input buffer (for data from EC). This buffer will always be
+ *       dword-aligned and include enough space for up to 7 word-alignment
+ *       bytes also, so we can ensure that the body of the message is always
+ *       dword-aligned (64-bit). We use this alignment to keep ARM and x86
+ *       happy. Probably word alignment would be OK, there might be a small
+ *       performance advantage to using dword.
+ * @dout: Output buffer (for data to EC). This buffer will always be
+ *        dword-aligned and include enough space for up to 7 word-alignment
+ *        bytes also, so we can ensure that the body of the message is always
+ *        dword-aligned (64-bit). We use this alignment to keep ARM and x86
+ *        happy. Probably word alignment would be OK, there might be a small
+ *        performance advantage to using dword.
+ * @din_size: Size of din buffer to allocate (zero to use static din).
+ * @dout_size: Size of dout buffer to allocate (zero to use static dout).
+ * @wake_enabled: True if this device can wake the system from sleep.
+ * @suspended: True if this device had been suspended.
+ * @cmd_xfer: Send command to EC and get response.
+ *            Returns the number of bytes received if the communication
+ *            succeeded, but that doesn't mean the EC was happy with the
+ *            command. The caller should check msg.result for the EC's result
+ *            code.
+ * @pkt_xfer: Send packet to EC and get response.
+ * @lock: One transaction at a time.
+ * @mkbp_event_supported: True if this EC supports the MKBP event protocol.
+ * @event_notifier: Interrupt event notifier for transport devices.
+ * @event_data: Raw payload transferred with the MKBP event.
+ * @event_size: Size in bytes of the event data.
+ * @host_event_wake_mask: Mask of host events that cause wake from suspend.
  */
 struct cros_ec_device {
-
        /* These are used by other drivers that want to talk to the EC */
        const char *phys_name;
        struct device *dev;
@@ -153,20 +161,19 @@ struct cros_ec_device {
 };
 
 /**
- * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information
- *
+ * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information.
  * @sensor_num: Id of the sensor, as reported by the EC.
  */
 struct cros_ec_sensor_platform {
        u8 sensor_num;
 };
 
-/* struct cros_ec_platform - ChromeOS EC platform information
- *
- * @ec_name: name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
- * used in /dev/ and sysfs.
- * @cmd_offset: offset to apply for each command. Set when
- * registering a devicde behind another one.
+/**
+ * struct cros_ec_platform - ChromeOS EC platform information.
+ * @ec_name: Name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
+ *           used in /dev/ and sysfs.
+ * @cmd_offset: Offset to apply for each command. Set when
+ *              registering a device behind another one.
  */
 struct cros_ec_platform {
        const char *ec_name;
@@ -175,16 +182,16 @@ struct cros_ec_platform {
 
 struct cros_ec_debugfs;
 
-/*
- * struct cros_ec_dev - ChromeOS EC device entry point
- *
- * @class_dev: Device structure used in sysfs
- * @cdev: Character device structure in /dev
- * @ec_dev: cros_ec_device structure to talk to the physical device
- * @dev: pointer to the platform device
- * @debug_info: cros_ec_debugfs structure for debugging information
- * @has_kb_wake_angle: true if at least 2 accelerometer are connected to the EC.
- * @cmd_offset: offset to apply for each command.
+/**
+ * struct cros_ec_dev - ChromeOS EC device entry point.
+ * @class_dev: Device structure used in sysfs.
+ * @cdev: Character device structure in /dev.
+ * @ec_dev: cros_ec_device structure to talk to the physical device.
+ * @dev: Pointer to the platform device.
+ * @debug_info: cros_ec_debugfs structure for debugging information.
+ * @has_kb_wake_angle: True if at least 2 accelerometer are connected to the EC.
+ * @cmd_offset: Offset to apply for each command.
+ * @features: Features supported by the EC.
  */
 struct cros_ec_dev {
        struct device class_dev;
@@ -200,124 +207,129 @@ struct cros_ec_dev {
 #define to_cros_ec_dev(dev)  container_of(dev, struct cros_ec_dev, class_dev)
 
 /**
- * cros_ec_suspend - Handle a suspend operation for the ChromeOS EC device
+ * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
+ * @ec_dev: Device to suspend.
  *
  * This can be called by drivers to handle a suspend event.
  *
- * ec_dev: Device to suspend
- * @return 0 if ok, -ve on error
+ * Return: 0 on success or negative error code.
  */
 int cros_ec_suspend(struct cros_ec_device *ec_dev);
 
 /**
- * cros_ec_resume - Handle a resume operation for the ChromeOS EC device
+ * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
+ * @ec_dev: Device to resume.
  *
  * This can be called by drivers to handle a resume event.
  *
- * @ec_dev: Device to resume
- * @return 0 if ok, -ve on error
+ * Return: 0 on success or negative error code.
  */
 int cros_ec_resume(struct cros_ec_device *ec_dev);
 
 /**
- * cros_ec_prepare_tx - Prepare an outgoing message in the output buffer
+ * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
+ * @ec_dev: Device to register.
+ * @msg: Message to write.
  *
  * This is intended to be used by all ChromeOS EC drivers, but at present
  * only SPI uses it. Once LPC uses the same protocol it can start using it.
  * I2C could use it now, with a refactor of the existing code.
  *
- * @ec_dev: Device to register
- * @msg: Message to write
+ * Return: 0 on success or negative error code.
  */
 int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
                       struct cros_ec_command *msg);
 
 /**
- * cros_ec_check_result - Check ec_msg->result
+ * cros_ec_check_result() - Check ec_msg->result.
+ * @ec_dev: EC device.
+ * @msg: Message to check.
  *
  * This is used by ChromeOS EC drivers to check the ec_msg->result for
  * errors and to warn about them.
  *
- * @ec_dev: EC device
- * @msg: Message to check
+ * Return: 0 on success or negative error code.
  */
 int cros_ec_check_result(struct cros_ec_device *ec_dev,
                         struct cros_ec_command *msg);
 
 /**
- * cros_ec_cmd_xfer - Send a command to the ChromeOS EC
+ * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
+ * @ec_dev: EC device.
+ * @msg: Message to write.
  *
  * Call this to send a command to the ChromeOS EC.  This should be used
  * instead of calling the EC's cmd_xfer() callback directly.
  *
- * @ec_dev: EC device
- * @msg: Message to write
+ * Return: 0 on success or negative error code.
  */
 int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
                     struct cros_ec_command *msg);
 
 /**
- * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
+ * @ec_dev: EC device.
+ * @msg: Message to write.
  *
  * This function is identical to cros_ec_cmd_xfer, except it returns success
  * status only if both the command was transmitted successfully and the EC
  * replied with success status. It's not necessary to check msg->result when
  * using this function.
  *
- * @ec_dev: EC device
- * @msg: Message to write
- * @return: Num. of bytes transferred on success, <0 on failure
+ * Return: The number of bytes transferred on success or negative error code.
  */
 int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
                            struct cros_ec_command *msg);
 
 /**
- * cros_ec_remove - Remove a ChromeOS EC
+ * cros_ec_remove() - Remove a ChromeOS EC.
+ * @ec_dev: Device to register.
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
  *
- * @ec_dev: Device to register
- * @return 0 if ok, -ve on error
+ * Return: 0 on success or negative error code.
  */
 int cros_ec_remove(struct cros_ec_device *ec_dev);
 
 /**
- * cros_ec_register - Register a new ChromeOS EC, using the provided info
+ * cros_ec_register() - Register a new ChromeOS EC, using the provided info.
+ * @ec_dev: Device to register.
  *
  * Before calling this, allocate a pointer to a new device and then fill
  * in all the fields up to the --private-- marker.
  *
- * @ec_dev: Device to register
- * @return 0 if ok, -ve on error
+ * Return: 0 on success or negative error code.
  */
 int cros_ec_register(struct cros_ec_device *ec_dev);
 
 /**
- * cros_ec_query_all -  Query the protocol version supported by the ChromeOS EC
+ * cros_ec_query_all() -  Query the protocol version supported by the
+ *         ChromeOS EC.
+ * @ec_dev: Device to register.
  *
- * @ec_dev: Device to register
- * @return 0 if ok, -ve on error
+ * Return: 0 on success or negative error code.
  */
 int cros_ec_query_all(struct cros_ec_device *ec_dev);
 
 /**
- * cros_ec_get_next_event -  Fetch next event from the ChromeOS EC
- *
- * @ec_dev: Device to fetch event from
+ * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
+ * @ec_dev: Device to fetch event from.
  * @wake_event: Pointer to a bool set to true upon return if the event might be
  *              treated as a wake event. Ignored if null.
  *
- * Returns: 0 on success, Linux error number on failure
+ * Return: 0 on success or negative error code.
  */
 int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event);
 
 /**
- * cros_ec_get_host_event - Return a mask of event set by the EC.
+ * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
+ * @ec_dev: Device to fetch event from.
  *
- * When MKBP is supported, when the EC raises an interrupt,
- * We collect the events raised and call the functions in the ec notifier.
+ * When MKBP is supported, when the EC raises an interrupt, we collect the
+ * events raised and call the functions in the ec notifier. This function
+ * is a helper to know which events are raised.
  *
- * This function is a helper to know which events are raised.
+ * Return: 0 on success or negative error code.
  */
 u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
 
index 5fd0e429f47202cce036218562f2e4c4b445a4cb..9a9631f0559e295763105520c1918abd9895b6dd 100644 (file)
@@ -306,15 +306,18 @@ enum host_event_code {
 /* Host event mask */
 #define EC_HOST_EVENT_MASK(event_code) (1UL << ((event_code) - 1))
 
-/* Arguments at EC_LPC_ADDR_HOST_ARGS */
+/**
+ * struct ec_lpc_host_args - Arguments at EC_LPC_ADDR_HOST_ARGS
+ * @flags: The host argument flags.
+ * @command_version: Command version.
+ * @data_size: The length of data.
+ * @checksum: Checksum; sum of command + flags + command_version + data_size +
+ *            all params/response data bytes.
+ */
 struct ec_lpc_host_args {
        uint8_t flags;
        uint8_t command_version;
        uint8_t data_size;
-       /*
-        * Checksum; sum of command + flags + command_version + data_size +
-        * all params/response data bytes.
-        */
        uint8_t checksum;
 } __packed;
 
@@ -468,54 +471,43 @@ struct ec_lpc_host_args {
 
 #define EC_HOST_REQUEST_VERSION 3
 
-/* Version 3 request from host */
+/**
+ * struct ec_host_request - Version 3 request from host.
+ * @struct_version: Should be 3. The EC will return EC_RES_INVALID_HEADER if it
+ *                  receives a header with a version it doesn't know how to
+ *                  parse.
+ * @checksum: Checksum of request and data; sum of all bytes including checksum
+ *            should total to 0.
+ * @command: Command to send (EC_CMD_...)
+ * @command_version: Command version.
+ * @reserved: Unused byte in current protocol version; set to 0.
+ * @data_len: Length of data which follows this header.
+ */
 struct ec_host_request {
-       /* Struct version (=3)
-        *
-        * EC will return EC_RES_INVALID_HEADER if it receives a header with a
-        * version it doesn't know how to parse.
-        */
        uint8_t struct_version;
-
-       /*
-        * Checksum of request and data; sum of all bytes including checksum
-        * should total to 0.
-        */
        uint8_t checksum;
-
-       /* Command code */
        uint16_t command;
-
-       /* Command version */
        uint8_t command_version;
-
-       /* Unused byte in current protocol version; set to 0 */
        uint8_t reserved;
-
-       /* Length of data which follows this header */
        uint16_t data_len;
 } __packed;
 
 #define EC_HOST_RESPONSE_VERSION 3
 
-/* Version 3 response from EC */
+/**
+ * struct ec_host_response - Version 3 response from EC.
+ * @struct_version: Struct version (=3).
+ * @checksum: Checksum of response and data; sum of all bytes including
+ *            checksum should total to 0.
+ * @result: EC's response to the command (separate from communication failure)
+ * @data_len: Length of data which follows this header.
+ * @reserved: Unused bytes in current protocol version; set to 0.
+ */
 struct ec_host_response {
-       /* Struct version (=3) */
        uint8_t struct_version;
-
-       /*
-        * Checksum of response and data; sum of all bytes including checksum
-        * should total to 0.
-        */
        uint8_t checksum;
-
-       /* Result code (EC_RES_*) */
        uint16_t result;
-
-       /* Length of data which follows this header */
        uint16_t data_len;
-
-       /* Unused bytes in current protocol version; set to 0 */
        uint16_t reserved;
 } __packed;
 
@@ -540,6 +532,10 @@ struct ec_host_response {
  */
 #define EC_CMD_PROTO_VERSION 0x00
 
+/**
+ * struct ec_response_proto_version - Response to the proto version command.
+ * @version: The protocol version.
+ */
 struct ec_response_proto_version {
        uint32_t version;
 } __packed;
@@ -550,12 +546,20 @@ struct ec_response_proto_version {
  */
 #define EC_CMD_HELLO 0x01
 
+/**
+ * struct ec_params_hello - Parameters to the hello command.
+ * @in_data: Pass anything here.
+ */
 struct ec_params_hello {
-       uint32_t in_data;  /* Pass anything here */
+       uint32_t in_data;
 } __packed;
 
+/**
+ * struct ec_response_hello - Response to the hello command.
+ * @out_data: Output will be in_data + 0x01020304.
+ */
 struct ec_response_hello {
-       uint32_t out_data;  /* Output will be in_data + 0x01020304 */
+       uint32_t out_data;
 } __packed;
 
 /* Get version number */
@@ -567,22 +571,37 @@ enum ec_current_image {
        EC_IMAGE_RW
 };
 
+/**
+ * struct ec_response_get_version - Response to the get version command.
+ * @version_string_ro: Null-terminated RO firmware version string.
+ * @version_string_rw: Null-terminated RW firmware version string.
+ * @reserved: Unused bytes; was previously RW-B firmware version string.
+ * @current_image: One of ec_current_image.
+ */
 struct ec_response_get_version {
-       /* Null-terminated version strings for RO, RW */
        char version_string_ro[32];
        char version_string_rw[32];
-       char reserved[32];       /* Was previously RW-B string */
-       uint32_t current_image;  /* One of ec_current_image */
+       char reserved[32];
+       uint32_t current_image;
 } __packed;
 
 /* Read test */
 #define EC_CMD_READ_TEST 0x03
 
+/**
+ * struct ec_params_read_test - Parameters for the read test command.
+ * @offset: Starting value for read buffer.
+ * @size: Size to read in bytes.
+ */
 struct ec_params_read_test {
-       uint32_t offset;   /* Starting value for read buffer */
-       uint32_t size;     /* Size to read in bytes */
+       uint32_t offset;
+       uint32_t size;
 } __packed;
 
+/**
+ * struct ec_response_read_test - Response to the read test command.
+ * @data: Data returned by the read test command.
+ */
 struct ec_response_read_test {
        uint32_t data[32];
 } __packed;
@@ -597,18 +616,27 @@ struct ec_response_read_test {
 /* Get chip info */
 #define EC_CMD_GET_CHIP_INFO 0x05
 
+/**
+ * struct ec_response_get_chip_info - Response to the get chip info command.
+ * @vendor: Null-terminated string for chip vendor.
+ * @name: Null-terminated string for chip name.
+ * @revision: Null-terminated string for chip mask version.
+ */
 struct ec_response_get_chip_info {
-       /* Null-terminated strings */
        char vendor[32];
        char name[32];
-       char revision[32];  /* Mask version */
+       char revision[32];
 } __packed;
 
 /* Get board HW version */
 #define EC_CMD_GET_BOARD_VERSION 0x06
 
+/**
+ * struct ec_response_board_version - Response to the board version command.
+ * @board_version: A monotonously incrementing number.
+ */
 struct ec_response_board_version {
-       uint16_t board_version;  /* A monotonously incrementing number. */
+       uint16_t board_version;
 } __packed;
 
 /*
@@ -621,27 +649,42 @@ struct ec_response_board_version {
  */
 #define EC_CMD_READ_MEMMAP 0x07
 
+/**
+ * struct ec_params_read_memmap - Parameters for the read memory map command.
+ * @offset: Offset in memmap (EC_MEMMAP_*).
+ * @size: Size to read in bytes.
+ */
 struct ec_params_read_memmap {
-       uint8_t offset;   /* Offset in memmap (EC_MEMMAP_*) */
-       uint8_t size;     /* Size to read in bytes */
+       uint8_t offset;
+       uint8_t size;
 } __packed;
 
 /* Read versions supported for a command */
 #define EC_CMD_GET_CMD_VERSIONS 0x08
 
+/**
+ * struct ec_params_get_cmd_versions - Parameters for the get command versions.
+ * @cmd: Command to check.
+ */
 struct ec_params_get_cmd_versions {
-       uint8_t cmd;      /* Command to check */
+       uint8_t cmd;
 } __packed;
 
+/**
+ * struct ec_params_get_cmd_versions_v1 - Parameters for the get command
+ *         versions (v1)
+ * @cmd: Command to check.
+ */
 struct ec_params_get_cmd_versions_v1 {
-       uint16_t cmd;     /* Command to check */
+       uint16_t cmd;
 } __packed;
 
+/**
+ * struct ec_response_get_cmd_version - Response to the get command versions.
+ * @version_mask: Mask of supported versions; use EC_VER_MASK() to compare with
+ *                a desired version.
+ */
 struct ec_response_get_cmd_versions {
-       /*
-        * Mask of supported versions; use EC_VER_MASK() to compare with a
-        * desired version.
-        */
        uint32_t version_mask;
 } __packed;
 
@@ -659,6 +702,11 @@ enum ec_comms_status {
        EC_COMMS_STATUS_PROCESSING      = 1 << 0,       /* Processing cmd */
 };
 
+/**
+ * struct ec_response_get_comms_status - Response to the get comms status
+ *         command.
+ * @flags: Mask of enum ec_comms_status.
+ */
 struct ec_response_get_comms_status {
        uint32_t flags;         /* Mask of enum ec_comms_status */
 } __packed;
@@ -685,19 +733,19 @@ struct ec_response_test_protocol {
 /* EC_RES_IN_PROGRESS may be returned if a command is slow */
 #define EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED (1 << 0)
 
+/**
+ * struct ec_response_get_protocol_info - Response to the get protocol info.
+ * @protocol_versions: Bitmask of protocol versions supported (1 << n means
+ *                     version n).
+ * @max_request_packet_size: Maximum request packet size in bytes.
+ * @max_response_packet_size: Maximum response packet size in bytes.
+ * @flags: see EC_PROTOCOL_INFO_*
+ */
 struct ec_response_get_protocol_info {
        /* Fields which exist if at least protocol version 3 supported */
-
-       /* Bitmask of protocol versions supported (1 << n means version n)*/
        uint32_t protocol_versions;
-
-       /* Maximum request packet size, in bytes */
        uint16_t max_request_packet_size;
-
-       /* Maximum response packet size, in bytes */
        uint16_t max_response_packet_size;
-
-       /* Flags; see EC_PROTOCOL_INFO_* */
        uint32_t flags;
 } __packed;
 
@@ -708,8 +756,10 @@ struct ec_response_get_protocol_info {
 /* The upper byte of .flags tells what to do (nothing means "get") */
 #define EC_GSV_SET        0x80000000
 
-/* The lower three bytes of .flags identifies the parameter, if that has
-   meaning for an individual command. */
+/*
+ * The lower three bytes of .flags identifies the parameter, if that has
+ * meaning for an individual command.
+ */
 #define EC_GSV_PARAM_MASK 0x00ffffff
 
 struct ec_params_get_set_value {
@@ -810,6 +860,7 @@ enum ec_feature_code {
 
 #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
 #define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32))
+
 struct ec_response_get_features {
        uint32_t flags[2];
 } __packed;
@@ -820,24 +871,22 @@ struct ec_response_get_features {
 /* Get flash info */
 #define EC_CMD_FLASH_INFO 0x10
 
-/* Version 0 returns these fields */
+/**
+ * struct ec_response_flash_info - Response to the flash info command.
+ * @flash_size: Usable flash size in bytes.
+ * @write_block_size: Write block size. Write offset and size must be a
+ *                    multiple of this.
+ * @erase_block_size: Erase block size. Erase offset and size must be a
+ *                    multiple of this.
+ * @protect_block_size: Protection block size. Protection offset and size
+ *                      must be a multiple of this.
+ *
+ * Version 0 returns these fields.
+ */
 struct ec_response_flash_info {
-       /* Usable flash size, in bytes */
        uint32_t flash_size;
-       /*
-        * Write block size.  Write offset and size must be a multiple
-        * of this.
-        */
        uint32_t write_block_size;
-       /*
-        * Erase block size.  Erase offset and size must be a multiple
-        * of this.
-        */
        uint32_t erase_block_size;
-       /*
-        * Protection block size.  Protection offset and size must be a
-        * multiple of this.
-        */
        uint32_t protect_block_size;
 } __packed;
 
@@ -845,7 +894,22 @@ struct ec_response_flash_info {
 /* EC flash erases bits to 0 instead of 1 */
 #define EC_FLASH_INFO_ERASE_TO_0 (1 << 0)
 
-/*
+/**
+ * struct ec_response_flash_info_1 - Response to the flash info v1 command.
+ * @flash_size: Usable flash size in bytes.
+ * @write_block_size: Write block size. Write offset and size must be a
+ *                    multiple of this.
+ * @erase_block_size: Erase block size. Erase offset and size must be a
+ *                    multiple of this.
+ * @protect_block_size: Protection block size. Protection offset and size
+ *                      must be a multiple of this.
+ * @write_ideal_size: Ideal write size in bytes.  Writes will be fastest if
+ *                    size is exactly this and offset is a multiple of this.
+ *                    For example, an EC may have a write buffer which can do
+ *                    half-page operations if data is aligned, and a slower
+ *                    word-at-a-time write mode.
+ * @flags: Flags; see EC_FLASH_INFO_*
+ *
  * Version 1 returns the same initial fields as version 0, with additional
  * fields following.
  *
@@ -860,15 +924,7 @@ struct ec_response_flash_info_1 {
        uint32_t protect_block_size;
 
        /* Version 1 adds these fields: */
-       /*
-        * Ideal write size in bytes.  Writes will be fastest if size is
-        * exactly this and offset is a multiple of this.  For example, an EC
-        * may have a write buffer which can do half-page operations if data is
-        * aligned, and a slower word-at-a-time write mode.
-        */
        uint32_t write_ideal_size;
-
-       /* Flags; see EC_FLASH_INFO_* */
        uint32_t flags;
 } __packed;
 
@@ -879,9 +935,14 @@ struct ec_response_flash_info_1 {
  */
 #define EC_CMD_FLASH_READ 0x11
 
+/**
+ * struct ec_params_flash_read - Parameters for the flash read command.
+ * @offset: Byte offset to read.
+ * @size: Size to read in bytes.
+ */
 struct ec_params_flash_read {
-       uint32_t offset;   /* Byte offset to read */
-       uint32_t size;     /* Size to read in bytes */
+       uint32_t offset;
+       uint32_t size;
 } __packed;
 
 /* Write flash */
@@ -891,18 +952,28 @@ struct ec_params_flash_read {
 /* Version 0 of the flash command supported only 64 bytes of data */
 #define EC_FLASH_WRITE_VER0_SIZE 64
 
+/**
+ * struct ec_params_flash_write - Parameters for the flash write command.
+ * @offset: Byte offset to write.
+ * @size: Size to write in bytes.
+ */
 struct ec_params_flash_write {
-       uint32_t offset;   /* Byte offset to write */
-       uint32_t size;     /* Size to write in bytes */
+       uint32_t offset;
+       uint32_t size;
        /* Followed by data to write */
 } __packed;
 
 /* Erase flash */
 #define EC_CMD_FLASH_ERASE 0x13
 
+/**
+ * struct ec_params_flash_erase - Parameters for the flash erase command.
+ * @offset: Byte offset to erase.
+ * @size: Size to erase in bytes.
+ */
 struct ec_params_flash_erase {
-       uint32_t offset;   /* Byte offset to erase */
-       uint32_t size;     /* Size to erase in bytes */
+       uint32_t offset;
+       uint32_t size;
 } __packed;
 
 /*
@@ -941,21 +1012,28 @@ struct ec_params_flash_erase {
 /* Entile flash code protected when the EC boots */
 #define EC_FLASH_PROTECT_ALL_AT_BOOT        (1 << 6)
 
+/**
+ * struct ec_params_flash_protect - Parameters for the flash protect command.
+ * @mask: Bits in flags to apply.
+ * @flags: New flags to apply.
+ */
 struct ec_params_flash_protect {
-       uint32_t mask;   /* Bits in flags to apply */
-       uint32_t flags;  /* New flags to apply */
+       uint32_t mask;
+       uint32_t flags;
 } __packed;
 
+/**
+ * struct ec_response_flash_protect - Response to the flash protect command.
+ * @flags: Current value of flash protect flags.
+ * @valid_flags: Flags which are valid on this platform. This allows the
+ *               caller to distinguish between flags which aren't set vs. flags
+ *               which can't be set on this platform.
+ * @writable_flags: Flags which can be changed given the current protection
+ *                  state.
+ */
 struct ec_response_flash_protect {
-       /* Current value of flash protect flags */
        uint32_t flags;
-       /*
-        * Flags which are valid on this platform.  This allows the caller
-        * to distinguish between flags which aren't set vs. flags which can't
-        * be set on this platform.
-        */
        uint32_t valid_flags;
-       /* Flags which can be changed given the current protection state */
        uint32_t writable_flags;
 } __packed;
 
@@ -982,8 +1060,13 @@ enum ec_flash_region {
        EC_FLASH_REGION_COUNT,
 };
 
+/**
+ * struct ec_params_flash_region_info - Parameters for the flash region info
+ *         command.
+ * @region: Flash region; see EC_FLASH_REGION_*
+ */
 struct ec_params_flash_region_info {
-       uint32_t region;  /* enum ec_flash_region */
+       uint32_t region;
 } __packed;
 
 struct ec_response_flash_region_info {
@@ -1094,7 +1177,9 @@ struct rgb_s {
 };
 
 #define LB_BATTERY_LEVELS 4
-/* List of tweakable parameters. NOTE: It's __packed so it can be sent in a
+
+/*
+ * List of tweakable parameters. NOTE: It's __packed so it can be sent in a
  * host command, but the alignment is the same regardless. Keep it that way.
  */
 struct lightbar_params_v0 {
diff --git a/include/linux/mfd/cros_ec_lpc_mec.h b/include/linux/mfd/cros_ec_lpc_mec.h
deleted file mode 100644 (file)
index 176496d..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
- *
- * Copyright (C) 2016 Google, Inc
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- * This driver uses the Chrome OS EC byte-level message-based protocol for
- * communicating the keyboard state (which keys are pressed) from a keyboard EC
- * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
- * but everything else (including deghosting) is done here.  The main
- * motivation for this is to keep the EC firmware as simple as possible, since
- * it cannot be easily upgraded and EC flash/IRAM space is relatively
- * expensive.
- */
-
-#ifndef __LINUX_MFD_CROS_EC_MEC_H
-#define __LINUX_MFD_CROS_EC_MEC_H
-
-#include <linux/mfd/cros_ec_commands.h>
-
-enum cros_ec_lpc_mec_emi_access_mode {
-       /* 8-bit access */
-       ACCESS_TYPE_BYTE = 0x0,
-       /* 16-bit access */
-       ACCESS_TYPE_WORD = 0x1,
-       /* 32-bit access */
-       ACCESS_TYPE_LONG = 0x2,
-       /*
-        * 32-bit access, read or write of MEC_EMI_EC_DATA_B3 causes the
-        * EC data register to be incremented.
-        */
-       ACCESS_TYPE_LONG_AUTO_INCREMENT = 0x3,
-};
-
-enum cros_ec_lpc_mec_io_type {
-       MEC_IO_READ,
-       MEC_IO_WRITE,
-};
-
-/* Access IO ranges 0x800 thru 0x9ff using EMI interface instead of LPC */
-#define MEC_EMI_RANGE_START EC_HOST_CMD_REGION0
-#define MEC_EMI_RANGE_END   (EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE)
-
-/* EMI registers are relative to base */
-#define MEC_EMI_BASE 0x800
-#define MEC_EMI_HOST_TO_EC (MEC_EMI_BASE + 0)
-#define MEC_EMI_EC_TO_HOST (MEC_EMI_BASE + 1)
-#define MEC_EMI_EC_ADDRESS_B0 (MEC_EMI_BASE + 2)
-#define MEC_EMI_EC_ADDRESS_B1 (MEC_EMI_BASE + 3)
-#define MEC_EMI_EC_DATA_B0 (MEC_EMI_BASE + 4)
-#define MEC_EMI_EC_DATA_B1 (MEC_EMI_BASE + 5)
-#define MEC_EMI_EC_DATA_B2 (MEC_EMI_BASE + 6)
-#define MEC_EMI_EC_DATA_B3 (MEC_EMI_BASE + 7)
-
-/*
- * cros_ec_lpc_mec_init
- *
- * Initialize MEC I/O.
- */
-void cros_ec_lpc_mec_init(void);
-
-/*
- * cros_ec_lpc_mec_destroy
- *
- * Cleanup MEC I/O.
- */
-void cros_ec_lpc_mec_destroy(void);
-
-/**
- * cros_ec_lpc_io_bytes_mec - Read / write bytes to MEC EMI port
- *
- * @io_type: MEC_IO_READ or MEC_IO_WRITE, depending on request
- * @offset:  Base read / write address
- * @length:  Number of bytes to read / write
- * @buf:     Destination / source buffer
- *
- * @return 8-bit checksum of all bytes read / written
- */
-u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
-                           unsigned int offset, unsigned int length, u8 *buf);
-
-#endif /* __LINUX_MFD_CROS_EC_MEC_H */
diff --git a/include/linux/mfd/cros_ec_lpc_reg.h b/include/linux/mfd/cros_ec_lpc_reg.h
deleted file mode 100644 (file)
index 5560bef..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller
- *
- * Copyright (C) 2016 Google, Inc
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- * This driver uses the Chrome OS EC byte-level message-based protocol for
- * communicating the keyboard state (which keys are pressed) from a keyboard EC
- * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
- * but everything else (including deghosting) is done here.  The main
- * motivation for this is to keep the EC firmware as simple as possible, since
- * it cannot be easily upgraded and EC flash/IRAM space is relatively
- * expensive.
- */
-
-#ifndef __LINUX_MFD_CROS_EC_REG_H
-#define __LINUX_MFD_CROS_EC_REG_H
-
-/**
- * cros_ec_lpc_read_bytes - Read bytes from a given LPC-mapped address.
- * Returns 8-bit checksum of all bytes read.
- *
- * @offset: Base read address
- * @length: Number of bytes to read
- * @dest: Destination buffer
- */
-u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest);
-
-/**
- * cros_ec_lpc_write_bytes - Write bytes to a given LPC-mapped address.
- * Returns 8-bit checksum of all bytes written.
- *
- * @offset: Base write address
- * @length: Number of bytes to write
- * @msg: Write data buffer
- */
-u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg);
-
-/**
- * cros_ec_lpc_reg_init
- *
- * Initialize register I/O.
- */
-void cros_ec_lpc_reg_init(void);
-
-/**
- * cros_ec_lpc_reg_destroy
- *
- * Cleanup reg I/O.
- */
-void cros_ec_lpc_reg_destroy(void);
-
-#endif /* __LINUX_MFD_CROS_EC_REG_H */
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
new file mode 100644 (file)
index 0000000..53dfc25
--- /dev/null
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PLATFORM_DATA_X86_ASUS_WMI_H
+#define __PLATFORM_DATA_X86_ASUS_WMI_H
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+/* WMI Methods */
+#define ASUS_WMI_METHODID_SPEC         0x43455053 /* BIOS SPECification */
+#define ASUS_WMI_METHODID_SFBD         0x44424653 /* Set First Boot Device */
+#define ASUS_WMI_METHODID_GLCD         0x44434C47 /* Get LCD status */
+#define ASUS_WMI_METHODID_GPID         0x44495047 /* Get Panel ID?? (Resol) */
+#define ASUS_WMI_METHODID_QMOD         0x444F4D51 /* Quiet MODe */
+#define ASUS_WMI_METHODID_SPLV         0x4C425053 /* Set Panel Light Value */
+#define ASUS_WMI_METHODID_AGFN         0x4E464741 /* FaN? */
+#define ASUS_WMI_METHODID_SFUN         0x4E554653 /* FUNCtionalities */
+#define ASUS_WMI_METHODID_SDSP         0x50534453 /* Set DiSPlay output */
+#define ASUS_WMI_METHODID_GDSP         0x50534447 /* Get DiSPlay output */
+#define ASUS_WMI_METHODID_DEVP         0x50564544 /* DEVice Policy */
+#define ASUS_WMI_METHODID_OSVR         0x5256534F /* OS VeRsion */
+#define ASUS_WMI_METHODID_DSTS         0x53544344 /* Device STatuS */
+#define ASUS_WMI_METHODID_DSTS2                0x53545344 /* Device STatuS #2*/
+#define ASUS_WMI_METHODID_BSTS         0x53545342 /* Bios STatuS ? */
+#define ASUS_WMI_METHODID_DEVS         0x53564544 /* DEVice Set */
+#define ASUS_WMI_METHODID_CFVS         0x53564643 /* CPU Frequency Volt Set */
+#define ASUS_WMI_METHODID_KBFT         0x5446424B /* KeyBoard FilTer */
+#define ASUS_WMI_METHODID_INIT         0x54494E49 /* INITialize */
+#define ASUS_WMI_METHODID_HKEY         0x59454B48 /* Hot KEY ?? */
+
+#define ASUS_WMI_UNSUPPORTED_METHOD    0xFFFFFFFE
+
+/* Wireless */
+#define ASUS_WMI_DEVID_HW_SWITCH       0x00010001
+#define ASUS_WMI_DEVID_WIRELESS_LED    0x00010002
+#define ASUS_WMI_DEVID_CWAP            0x00010003
+#define ASUS_WMI_DEVID_WLAN            0x00010011
+#define ASUS_WMI_DEVID_WLAN_LED                0x00010012
+#define ASUS_WMI_DEVID_BLUETOOTH       0x00010013
+#define ASUS_WMI_DEVID_GPS             0x00010015
+#define ASUS_WMI_DEVID_WIMAX           0x00010017
+#define ASUS_WMI_DEVID_WWAN3G          0x00010019
+#define ASUS_WMI_DEVID_UWB             0x00010021
+
+/* Leds */
+/* 0x000200XX and 0x000400XX */
+#define ASUS_WMI_DEVID_LED1            0x00020011
+#define ASUS_WMI_DEVID_LED2            0x00020012
+#define ASUS_WMI_DEVID_LED3            0x00020013
+#define ASUS_WMI_DEVID_LED4            0x00020014
+#define ASUS_WMI_DEVID_LED5            0x00020015
+#define ASUS_WMI_DEVID_LED6            0x00020016
+
+/* Backlight and Brightness */
+#define ASUS_WMI_DEVID_ALS_ENABLE      0x00050001 /* Ambient Light Sensor */
+#define ASUS_WMI_DEVID_BACKLIGHT       0x00050011
+#define ASUS_WMI_DEVID_BRIGHTNESS      0x00050012
+#define ASUS_WMI_DEVID_KBD_BACKLIGHT   0x00050021
+#define ASUS_WMI_DEVID_LIGHT_SENSOR    0x00050022 /* ?? */
+#define ASUS_WMI_DEVID_LIGHTBAR                0x00050025
+
+/* Misc */
+#define ASUS_WMI_DEVID_CAMERA          0x00060013
+
+/* Storage */
+#define ASUS_WMI_DEVID_CARDREADER      0x00080013
+
+/* Input */
+#define ASUS_WMI_DEVID_TOUCHPAD                0x00100011
+#define ASUS_WMI_DEVID_TOUCHPAD_LED    0x00100012
+
+/* Fan, Thermal */
+#define ASUS_WMI_DEVID_THERMAL_CTRL    0x00110011
+#define ASUS_WMI_DEVID_FAN_CTRL                0x00110012
+
+/* Power */
+#define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
+
+/* Deep S3 / Resume on LID open */
+#define ASUS_WMI_DEVID_LID_RESUME      0x00120031
+
+/* DSTS masks */
+#define ASUS_WMI_DSTS_STATUS_BIT       0x00000001
+#define ASUS_WMI_DSTS_UNKNOWN_BIT      0x00000002
+#define ASUS_WMI_DSTS_PRESENCE_BIT     0x00010000
+#define ASUS_WMI_DSTS_USER_BIT         0x00020000
+#define ASUS_WMI_DSTS_BIOS_BIT         0x00040000
+#define ASUS_WMI_DSTS_BRIGHTNESS_MASK  0x000000FF
+#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK  0x0000FF00
+#define ASUS_WMI_DSTS_LIGHTBAR_MASK    0x0000000F
+
+#if IS_REACHABLE(CONFIG_ASUS_WMI)
+int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval);
+#else
+static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
+                                          u32 *retval)
+{
+       return -ENODEV;
+}
+#endif
+
+#endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */
index e2695c4bf3580323d9df2edd100388cf7db7e256..ddbba838d048df8f7d2d080442b77fa89130b561 100644 (file)
@@ -13,7 +13,7 @@ void unix_notinflight(struct user_struct *user, struct file *fp);
 void unix_gc(void);
 void wait_for_unix_gc(void);
 struct sock *unix_get_socket(struct file *filp);
-struct sock *unix_peer_get(struct sock *);
+struct sock *unix_peer_get(struct sock *sk);
 
 #define UNIX_HASH_SIZE 256
 #define UNIX_HASH_BITS 8
@@ -40,7 +40,7 @@ struct unix_skb_parms {
        u32                     consumed;
 } __randomize_layout;
 
-#define UNIXCB(skb)    (*(struct unix_skb_parms *)&((skb)->cb))
+#define UNIXCB(skb)    (*(struct unix_skb_parms *)&((skb)->cb))
 
 #define unix_state_lock(s)     spin_lock(&unix_sk(s)->lock)
 #define unix_state_unlock(s)   spin_unlock(&unix_sk(s)->lock)
index 31aa101783351547469f4efc67b0bb9c9e0f10f1..93722e60204c607377bf20efeca54df08e78bbd4 100644 (file)
@@ -41,6 +41,7 @@
 #define EM_TILEPRO     188     /* Tilera TILEPro */
 #define EM_MICROBLAZE  189     /* Xilinx MicroBlaze */
 #define EM_TILEGX      191     /* Tilera TILE-Gx */
+#define EM_RISCV       243     /* RISC-V */
 #define EM_BPF         247     /* Linux BPF - in-kernel virtual machine */
 #define EM_FRV         0x5441  /* Fujitsu FR-V */
 
index 171a2c88e77ddd28ea5f9d5ba135d424cd09714e..1971ca325fb4e765be7156299e7f02983687019f 100644 (file)
@@ -2852,10 +2852,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
                regs[BPF_REG_0].type = NOT_INIT;
        } else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL ||
                   fn->ret_type == RET_PTR_TO_MAP_VALUE) {
-               if (fn->ret_type == RET_PTR_TO_MAP_VALUE)
-                       regs[BPF_REG_0].type = PTR_TO_MAP_VALUE;
-               else
-                       regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL;
                /* There is no offset yet applied, variable or fixed */
                mark_reg_known_zero(env, regs, BPF_REG_0);
                /* remember map_ptr, so that check_map_access()
@@ -2868,7 +2864,12 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
                        return -EINVAL;
                }
                regs[BPF_REG_0].map_ptr = meta.map_ptr;
-               regs[BPF_REG_0].id = ++env->id_gen;
+               if (fn->ret_type == RET_PTR_TO_MAP_VALUE) {
+                       regs[BPF_REG_0].type = PTR_TO_MAP_VALUE;
+               } else {
+                       regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL;
+                       regs[BPF_REG_0].id = ++env->id_gen;
+               }
        } else if (fn->ret_type == RET_PTR_TO_SOCKET_OR_NULL) {
                int id = acquire_reference_state(env, insn_idx);
                if (id < 0)
@@ -3046,7 +3047,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
                        dst_reg->umax_value = umax_ptr;
                        dst_reg->var_off = ptr_reg->var_off;
                        dst_reg->off = ptr_reg->off + smin_val;
-                       dst_reg->range = ptr_reg->range;
+                       dst_reg->raw = ptr_reg->raw;
                        break;
                }
                /* A new variable offset is created.  Note that off_reg->off
@@ -3076,10 +3077,11 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
                }
                dst_reg->var_off = tnum_add(ptr_reg->var_off, off_reg->var_off);
                dst_reg->off = ptr_reg->off;
+               dst_reg->raw = ptr_reg->raw;
                if (reg_is_pkt_pointer(ptr_reg)) {
                        dst_reg->id = ++env->id_gen;
                        /* something was added to pkt_ptr, set range to zero */
-                       dst_reg->range = 0;
+                       dst_reg->raw = 0;
                }
                break;
        case BPF_SUB:
@@ -3108,7 +3110,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
                        dst_reg->var_off = ptr_reg->var_off;
                        dst_reg->id = ptr_reg->id;
                        dst_reg->off = ptr_reg->off - smin_val;
-                       dst_reg->range = ptr_reg->range;
+                       dst_reg->raw = ptr_reg->raw;
                        break;
                }
                /* A new variable offset is created.  If the subtrahend is known
@@ -3134,11 +3136,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
                }
                dst_reg->var_off = tnum_sub(ptr_reg->var_off, off_reg->var_off);
                dst_reg->off = ptr_reg->off;
+               dst_reg->raw = ptr_reg->raw;
                if (reg_is_pkt_pointer(ptr_reg)) {
                        dst_reg->id = ++env->id_gen;
                        /* something was added to pkt_ptr, set range to zero */
                        if (smin_val < 0)
-                               dst_reg->range = 0;
+                               dst_reg->raw = 0;
                }
                break;
        case BPF_AND:
index b0875b327f5c3d5c733f79337bef40d5d600fbd1..c3fd849d4a8f93c27d18713ae1e492faa5d24ec9 100644 (file)
@@ -115,7 +115,7 @@ static int module_trace_bprintk_format_notify(struct notifier_block *self,
  * section, then we need to read the link list pointers. The trick is
  * we pass the address of the string to the seq function just like
  * we do for the kernel core formats. To get back the structure that
- * holds the format, we simply use containerof() and then go to the
+ * holds the format, we simply use container_of() and then go to the
  * next format in the list.
  */
 static const char **
index d1573a16aa926cc2446b0629e6a5cec573de97d5..a9965f4af4dd391cce6fb3875bd48332560e3598 100644 (file)
@@ -624,6 +624,3 @@ config GENERIC_LIB_CMPDI2
 
 config GENERIC_LIB_UCMPDI2
        bool
-
-config GENERIC_LIB_UMODDI3
-       bool
index 988949c4fd3a7f49df646f3fcd195d0d1ad01dec..db06d123789834252c41e58f183e134bb127ae59 100644 (file)
@@ -274,4 +274,3 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o
 obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
 obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
 obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
-obj-$(CONFIG_GENERIC_LIB_UMODDI3) += umoddi3.o udivmoddi4.o
diff --git a/lib/udivmoddi4.c b/lib/udivmoddi4.c
deleted file mode 100644 (file)
index c08bc8a..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-/*
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.
- */
-
-#include <linux/libgcc.h>
-
-#define count_leading_zeros(COUNT, X)   ((COUNT) = __builtin_clz(X))
-
-#define W_TYPE_SIZE 32
-
-#define __ll_B ((unsigned long) 1 << (W_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((unsigned long) (t) & (__ll_B - 1))
-#define __ll_highpart(t) ((unsigned long) (t) >> (W_TYPE_SIZE / 2))
-
-/* If we still don't have umul_ppmm, define it using plain C. */
-#if !defined(umul_ppmm)
-#define umul_ppmm(w1, w0, u, v)                                                \
-       do {                                                            \
-               unsigned long __x0, __x1, __x2, __x3;                   \
-               unsigned short __ul, __vl, __uh, __vh;                  \
-                                                                       \
-               __ul = __ll_lowpart(u);                                 \
-               __uh = __ll_highpart(u);                                \
-               __vl = __ll_lowpart(v);                                 \
-               __vh = __ll_highpart(v);                                \
-                                                                       \
-               __x0 = (unsigned long) __ul * __vl;                     \
-               __x1 = (unsigned long) __ul * __vh;                     \
-               __x2 = (unsigned long) __uh * __vl;                     \
-               __x3 = (unsigned long) __uh * __vh;                     \
-                                                                       \
-               __x1 += __ll_highpart(__x0);                            \
-               __x1 += __x2;                                           \
-               if (__x1 < __x2)                                        \
-                       __x3 += __ll_B;                                 \
-                                                                       \
-               (w1) = __x3 + __ll_highpart(__x1);                      \
-               (w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0);\
-       } while (0)
-#endif
-
-#if !defined(sub_ddmmss)
-#define sub_ddmmss(sh, sl, ah, al, bh, bl)                             \
-       do {                                                            \
-               unsigned long __x;                                      \
-               __x = (al) - (bl);                                      \
-               (sh) = (ah) - (bh) - (__x > (al));                      \
-               (sl) = __x;                                             \
-       } while (0)
-#endif
-
-/* Define this unconditionally, so it can be used for debugging. */
-#define __udiv_qrnnd_c(q, r, n1, n0, d)                                        \
-       do {                                                            \
-               unsigned long __d1, __d0, __q1, __q0;                   \
-               unsigned long __r1, __r0, __m;                          \
-               __d1 = __ll_highpart(d);                                \
-               __d0 = __ll_lowpart(d);                         \
-                                                                       \
-               __r1 = (n1) % __d1;                                     \
-               __q1 = (n1) / __d1;                                     \
-               __m = (unsigned long) __q1 * __d0;                      \
-               __r1 = __r1 * __ll_B | __ll_highpart(n0);               \
-               if (__r1 < __m) {                                       \
-                       __q1--, __r1 += (d);                            \
-                       if (__r1 >= (d))                                \
-                               if (__r1 < __m)                         \
-                                       __q1--, __r1 += (d);            \
-               }                                                       \
-               __r1 -= __m;                                            \
-                                                                       \
-               __r0 = __r1 % __d1;                                     \
-               __q0 = __r1 / __d1;                                     \
-               __m = (unsigned long) __q0 * __d0;                      \
-               __r0 = __r0 * __ll_B | __ll_lowpart(n0);                \
-               if (__r0 < __m) {                                       \
-                       __q0--, __r0 += (d);                            \
-                       if (__r0 >= (d))                                \
-                               if (__r0 < __m)                         \
-                                       __q0--, __r0 += (d);            \
-               }                                                       \
-               __r0 -= __m;                                            \
-                                                                       \
-               (q) = (unsigned long) __q1 * __ll_B | __q0;             \
-               (r) = __r0;                                             \
-       } while (0)
-
-/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
-#if !defined(udiv_qrnnd)
-#define UDIV_NEEDS_NORMALIZATION 1
-#define udiv_qrnnd __udiv_qrnnd_c
-#endif
-
-unsigned long long __udivmoddi4(unsigned long long u, unsigned long long v,
-                               unsigned long long *rp)
-{
-       const DWunion nn = {.ll = u };
-       const DWunion dd = {.ll = v };
-       DWunion rr, ww;
-       unsigned long d0, d1, n0, n1, n2;
-       unsigned long q0 = 0, q1 = 0;
-       unsigned long b, bm;
-
-       d0 = dd.s.low;
-       d1 = dd.s.high;
-       n0 = nn.s.low;
-       n1 = nn.s.high;
-
-#if !UDIV_NEEDS_NORMALIZATION
-
-       if (d1 == 0) {
-               if (d0 > n1) {
-                       /* 0q = nn / 0D */
-
-                       udiv_qrnnd(q0, n0, n1, n0, d0);
-                       q1 = 0;
-
-                       /* Remainder in n0. */
-               } else {
-                       /* qq = NN / 0d */
-
-                       if (d0 == 0)
-                               /* Divide intentionally by zero. */
-                               d0 = 1 / d0;
-
-                       udiv_qrnnd(q1, n1, 0, n1, d0);
-                       udiv_qrnnd(q0, n0, n1, n0, d0);
-
-                       /* Remainder in n0. */
-               }
-
-               if (rp != 0) {
-                       rr.s.low = n0;
-                       rr.s.high = 0;
-                       *rp = rr.ll;
-               }
-
-#else /* UDIV_NEEDS_NORMALIZATION */
-
-       if (d1 == 0) {
-               if (d0 > n1) {
-                       /* 0q = nn / 0D */
-
-                       count_leading_zeros(bm, d0);
-
-                       if (bm != 0) {
-                               /*
-                                * Normalize, i.e. make the most significant bit
-                                * of the denominator set.
-                                */
-
-                               d0 = d0 << bm;
-                               n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
-                               n0 = n0 << bm;
-                       }
-
-                       udiv_qrnnd(q0, n0, n1, n0, d0);
-                       q1 = 0;
-
-                       /* Remainder in n0 >> bm. */
-               } else {
-                       /* qq = NN / 0d */
-
-                       if (d0 == 0)
-                               /* Divide intentionally by zero. */
-                               d0 = 1 / d0;
-
-                       count_leading_zeros(bm, d0);
-
-                       if (bm == 0) {
-                               /*
-                                * From (n1 >= d0) /\ (the most significant bit
-                                * of d0 is set), conclude (the most significant
-                                * bit of n1 is set) /\ (theleading quotient
-                                * digit q1 = 1).
-                                *
-                                * This special case is necessary, not an
-                                * optimization. (Shifts counts of W_TYPE_SIZE
-                                * are undefined.)
-                                */
-
-                               n1 -= d0;
-                               q1 = 1;
-                       } else {
-                               /* Normalize. */
-
-                               b = W_TYPE_SIZE - bm;
-
-                               d0 = d0 << bm;
-                               n2 = n1 >> b;
-                               n1 = (n1 << bm) | (n0 >> b);
-                               n0 = n0 << bm;
-
-                               udiv_qrnnd(q1, n1, n2, n1, d0);
-                       }
-
-                       /* n1 != d0... */
-
-                       udiv_qrnnd(q0, n0, n1, n0, d0);
-
-                       /* Remainder in n0 >> bm. */
-               }
-
-               if (rp != 0) {
-                       rr.s.low = n0 >> bm;
-                       rr.s.high = 0;
-                       *rp = rr.ll;
-               }
-
-#endif /* UDIV_NEEDS_NORMALIZATION */
-
-       } else {
-               if (d1 > n1) {
-                       /* 00 = nn / DD */
-
-                       q0 = 0;
-                       q1 = 0;
-
-                       /* Remainder in n1n0. */
-                       if (rp != 0) {
-                               rr.s.low = n0;
-                               rr.s.high = n1;
-                               *rp = rr.ll;
-                       }
-               } else {
-                       /* 0q = NN / dd */
-
-                       count_leading_zeros(bm, d1);
-                       if (bm == 0) {
-                               /*
-                                * From (n1 >= d1) /\ (the most significant bit
-                                * of d1 is set), conclude (the most significant
-                                * bit of n1 is set) /\ (the quotient digit q0 =
-                                * 0 or 1).
-                                *
-                                * This special case is necessary, not an
-                                * optimization.
-                                */
-
-                               /*
-                                * The condition on the next line takes
-                                * advantage of that n1 >= d1 (true due to
-                                * program flow).
-                                */
-                               if (n1 > d1 || n0 >= d0) {
-                                       q0 = 1;
-                                       sub_ddmmss(n1, n0, n1, n0, d1, d0);
-                               } else {
-                                       q0 = 0;
-                               }
-
-                               q1 = 0;
-
-                               if (rp != 0) {
-                                       rr.s.low = n0;
-                                       rr.s.high = n1;
-                                       *rp = rr.ll;
-                               }
-                       } else {
-                               unsigned long m1, m0;
-                               /* Normalize. */
-
-                               b = W_TYPE_SIZE - bm;
-
-                               d1 = (d1 << bm) | (d0 >> b);
-                               d0 = d0 << bm;
-                               n2 = n1 >> b;
-                               n1 = (n1 << bm) | (n0 >> b);
-                               n0 = n0 << bm;
-
-                               udiv_qrnnd(q0, n1, n2, n1, d1);
-                               umul_ppmm(m1, m0, q0, d0);
-
-                               if (m1 > n1 || (m1 == n1 && m0 > n0)) {
-                                       q0--;
-                                       sub_ddmmss(m1, m0, m1, m0, d1, d0);
-                               }
-
-                               q1 = 0;
-
-                               /* Remainder in (n1n0 - m1m0) >> bm. */
-                               if (rp != 0) {
-                                       sub_ddmmss(n1, n0, n1, n0, m1, m0);
-                                       rr.s.low = (n1 << b) | (n0 >> bm);
-                                       rr.s.high = n1 >> bm;
-                                       *rp = rr.ll;
-                               }
-                       }
-               }
-       }
-
-       ww.s.low = q0;
-       ww.s.high = q1;
-
-       return ww.ll;
-}
diff --git a/lib/umoddi3.c b/lib/umoddi3.c
deleted file mode 100644 (file)
index d7bbf0f..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-/*
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/libgcc.h>
-
-extern unsigned long long __udivmoddi4(unsigned long long u,
-                                      unsigned long long v,
-                                      unsigned long long *rp);
-
-unsigned long long __umoddi3(unsigned long long u, unsigned long long v)
-{
-       unsigned long long w;
-       (void)__udivmoddi4(u, v, &w);
-       return w;
-}
-EXPORT_SYMBOL(__umoddi3);
index a6b74c6fe0becd3ef42284aa643933ae4fb7f0cf..db86282fd024580cbf5c41f01cb6d5447a9e1791 100644 (file)
@@ -2591,7 +2591,7 @@ int __init pcpu_page_first_chunk(size_t reserved_size,
        BUG_ON(ai->nr_groups != 1);
        upa = ai->alloc_size/ai->unit_size;
        nr_g0_units = roundup(num_possible_cpus(), upa);
-       if (unlikely(WARN_ON(ai->groups[0].nr_units != nr_g0_units))) {
+       if (WARN_ON(ai->groups[0].nr_units != nr_g0_units)) {
                pcpu_free_alloc_info(ai);
                return -EINVAL;
        }
index f679c7a7d761a60b22f733a443e77b54cb51595f..e01274bd5e3e21addd346a887e24e2c709ef44c9 100644 (file)
@@ -3600,6 +3600,11 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh,
                return -EINVAL;
        }
 
+       if (dev->type != ARPHRD_ETHER) {
+               NL_SET_ERR_MSG(extack, "FDB add only supported for Ethernet devices");
+               return -EINVAL;
+       }
+
        addr = nla_data(tb[NDA_LLADDR]);
 
        err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
@@ -3704,6 +3709,11 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
                return -EINVAL;
        }
 
+       if (dev->type != ARPHRD_ETHER) {
+               NL_SET_ERR_MSG(extack, "FDB delete only supported for Ethernet devices");
+               return -EINVAL;
+       }
+
        addr = nla_data(tb[NDA_LLADDR]);
 
        err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
index 4da39446da2d89b529973eb33902577a0e6cbb54..765b2b32c4a4263640563f34b4dd93b5bdf471de 100644 (file)
 #ifdef CONFIG_IP_MULTICAST
 /* Parameter names and values are taken from igmp-v2-06 draft */
 
-#define IGMP_V1_ROUTER_PRESENT_TIMEOUT         (400*HZ)
-#define IGMP_V2_ROUTER_PRESENT_TIMEOUT         (400*HZ)
 #define IGMP_V2_UNSOLICITED_REPORT_INTERVAL    (10*HZ)
 #define IGMP_V3_UNSOLICITED_REPORT_INTERVAL    (1*HZ)
+#define IGMP_QUERY_INTERVAL                    (125*HZ)
 #define IGMP_QUERY_RESPONSE_INTERVAL           (10*HZ)
-#define IGMP_QUERY_ROBUSTNESS_VARIABLE         2
-
 
 #define IGMP_INITIAL_REPORT_DELAY              (1)
 
@@ -935,13 +932,15 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
 
                        max_delay = IGMP_QUERY_RESPONSE_INTERVAL;
                        in_dev->mr_v1_seen = jiffies +
-                               IGMP_V1_ROUTER_PRESENT_TIMEOUT;
+                               (in_dev->mr_qrv * in_dev->mr_qi) +
+                               in_dev->mr_qri;
                        group = 0;
                } else {
                        /* v2 router present */
                        max_delay = ih->code*(HZ/IGMP_TIMER_SCALE);
                        in_dev->mr_v2_seen = jiffies +
-                               IGMP_V2_ROUTER_PRESENT_TIMEOUT;
+                               (in_dev->mr_qrv * in_dev->mr_qi) +
+                               in_dev->mr_qri;
                }
                /* cancel the interface change timer */
                in_dev->mr_ifc_count = 0;
@@ -981,8 +980,21 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
                if (!max_delay)
                        max_delay = 1;  /* can't mod w/ 0 */
                in_dev->mr_maxdelay = max_delay;
-               if (ih3->qrv)
-                       in_dev->mr_qrv = ih3->qrv;
+
+               /* RFC3376, 4.1.6. QRV and 4.1.7. QQIC, when the most recently
+                * received value was zero, use the default or statically
+                * configured value.
+                */
+               in_dev->mr_qrv = ih3->qrv ?: net->ipv4.sysctl_igmp_qrv;
+               in_dev->mr_qi = IGMPV3_QQIC(ih3->qqic)*HZ ?: IGMP_QUERY_INTERVAL;
+
+               /* RFC3376, 8.3. Query Response Interval:
+                * The number of seconds represented by the [Query Response
+                * Interval] must be less than the [Query Interval].
+                */
+               if (in_dev->mr_qri >= in_dev->mr_qi)
+                       in_dev->mr_qri = (in_dev->mr_qi/HZ - 1)*HZ;
+
                if (!group) { /* general query */
                        if (ih3->nsrcs)
                                return true;    /* no sources allowed */
@@ -1723,18 +1735,30 @@ void ip_mc_down(struct in_device *in_dev)
        ip_mc_dec_group(in_dev, IGMP_ALL_HOSTS);
 }
 
-void ip_mc_init_dev(struct in_device *in_dev)
-{
 #ifdef CONFIG_IP_MULTICAST
+static void ip_mc_reset(struct in_device *in_dev)
+{
        struct net *net = dev_net(in_dev->dev);
+
+       in_dev->mr_qi = IGMP_QUERY_INTERVAL;
+       in_dev->mr_qri = IGMP_QUERY_RESPONSE_INTERVAL;
+       in_dev->mr_qrv = net->ipv4.sysctl_igmp_qrv;
+}
+#else
+static void ip_mc_reset(struct in_device *in_dev)
+{
+}
 #endif
+
+void ip_mc_init_dev(struct in_device *in_dev)
+{
        ASSERT_RTNL();
 
 #ifdef CONFIG_IP_MULTICAST
        timer_setup(&in_dev->mr_gq_timer, igmp_gq_timer_expire, 0);
        timer_setup(&in_dev->mr_ifc_timer, igmp_ifc_timer_expire, 0);
-       in_dev->mr_qrv = net->ipv4.sysctl_igmp_qrv;
 #endif
+       ip_mc_reset(in_dev);
 
        spin_lock_init(&in_dev->mc_tomb_lock);
 }
@@ -1744,15 +1768,10 @@ void ip_mc_init_dev(struct in_device *in_dev)
 void ip_mc_up(struct in_device *in_dev)
 {
        struct ip_mc_list *pmc;
-#ifdef CONFIG_IP_MULTICAST
-       struct net *net = dev_net(in_dev->dev);
-#endif
 
        ASSERT_RTNL();
 
-#ifdef CONFIG_IP_MULTICAST
-       in_dev->mr_qrv = net->ipv4.sysctl_igmp_qrv;
-#endif
+       ip_mc_reset(in_dev);
        ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
 
        for_each_pmc_rtnl(in_dev, pmc) {
index b7918d4caa300a15bec2858065b8f73d71cf6eb0..3b45fe530f91e2e1aa697888e11a78cf7e9d211e 100644 (file)
@@ -145,6 +145,7 @@ msg_bytes_ready:
                        ret = err;
                        goto out;
                }
+               copied = -EAGAIN;
        }
        ret = copied;
 out:
index a70097ecf33c2bf9e9df7b92c2359ab679ae6d7e..865ecef68196900157b29c59b6bd57aff53e9e07 100644 (file)
@@ -3030,7 +3030,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
                         * is already present */
                        if (mac_proto != MAC_PROTO_NONE)
                                return -EINVAL;
-                       mac_proto = MAC_PROTO_NONE;
+                       mac_proto = MAC_PROTO_ETHERNET;
                        break;
 
                case OVS_ACTION_ATTR_POP_ETH:
@@ -3038,7 +3038,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
                                return -EINVAL;
                        if (vlan_tci & htons(VLAN_TAG_PRESENT))
                                return -EINVAL;
-                       mac_proto = MAC_PROTO_ETHERNET;
+                       mac_proto = MAC_PROTO_NONE;
                        break;
 
                case OVS_ACTION_ATTR_PUSH_NSH:
index a827a1f562bf323d03cd5e70ffce67da53401a61..6a28b96e779e68d5259138e11da17c1216e18b71 100644 (file)
@@ -499,8 +499,9 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
 void sctp_assoc_rm_peer(struct sctp_association *asoc,
                        struct sctp_transport *peer)
 {
-       struct list_head        *pos;
-       struct sctp_transport   *transport;
+       struct sctp_transport *transport;
+       struct list_head *pos;
+       struct sctp_chunk *ch;
 
        pr_debug("%s: association:%p addr:%pISpc\n",
                 __func__, asoc, &peer->ipaddr.sa);
@@ -564,7 +565,6 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
         */
        if (!list_empty(&peer->transmitted)) {
                struct sctp_transport *active = asoc->peer.active_path;
-               struct sctp_chunk *ch;
 
                /* Reset the transport of each chunk on this list */
                list_for_each_entry(ch, &peer->transmitted,
@@ -586,6 +586,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
                                sctp_transport_hold(active);
        }
 
+       list_for_each_entry(ch, &asoc->outqueue.out_chunk_list, list)
+               if (ch->transport == peer)
+                       ch->transport = NULL;
+
        asoc->peer.transport_count--;
 
        sctp_transport_free(peer);
index fc0386e8ff23933a0e5eae47661d39d8799b6a66..739f3e50120ddf61c508cc677b46e0239054131c 100644 (file)
@@ -7083,14 +7083,15 @@ static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
        }
 
        policy = params.sprstat_policy;
-       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
+       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
+           ((policy & SCTP_PR_SCTP_ALL) && (policy & SCTP_PR_SCTP_MASK)))
                goto out;
 
        asoc = sctp_id2assoc(sk, params.sprstat_assoc_id);
        if (!asoc)
                goto out;
 
-       if (policy & SCTP_PR_SCTP_ALL) {
+       if (policy == SCTP_PR_SCTP_ALL) {
                params.sprstat_abandoned_unsent = 0;
                params.sprstat_abandoned_sent = 0;
                for (policy = 0; policy <= SCTP_PR_INDEX(MAX); policy++) {
@@ -7142,7 +7143,8 @@ static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
        }
 
        policy = params.sprstat_policy;
-       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
+       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
+           ((policy & SCTP_PR_SCTP_ALL) && (policy & SCTP_PR_SCTP_MASK)))
                goto out;
 
        asoc = sctp_id2assoc(sk, params.sprstat_assoc_id);
index 4a9ee2d83158ba87a4da985af1020faae8c440b7..140270a13d54f7c69584fa6aefbf6b1be0941ec6 100644 (file)
@@ -8,7 +8,6 @@ config XFRM
 
 config XFRM_OFFLOAD
        bool
-       depends on XFRM
 
 config XFRM_ALGO
        tristate
index b607be7236d3e580fda376f04cbe62302f698e4f..d6e62e90e8d44df2a3b710b6cfd875b32e20daec 100644 (file)
@@ -2084,19 +2084,19 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
        prog->expected_attach_type = type;
 }
 
-#define BPF_PROG_SEC_IMPL(string, ptype, eatype, atype) \
-       { string, sizeof(string) - 1, ptype, eatype, atype }
+#define BPF_PROG_SEC_IMPL(string, ptype, eatype, is_attachable, atype) \
+       { string, sizeof(string) - 1, ptype, eatype, is_attachable, atype }
 
 /* Programs that can NOT be attached. */
-#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, -EINVAL)
+#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 0)
 
 /* Programs that can be attached. */
 #define BPF_APROG_SEC(string, ptype, atype) \
-       BPF_PROG_SEC_IMPL(string, ptype, 0, atype)
+       BPF_PROG_SEC_IMPL(string, ptype, 0, 1, atype)
 
 /* Programs that must specify expected attach type at load time. */
 #define BPF_EAPROG_SEC(string, ptype, eatype) \
-       BPF_PROG_SEC_IMPL(string, ptype, eatype, eatype)
+       BPF_PROG_SEC_IMPL(string, ptype, eatype, 1, eatype)
 
 /* Programs that can be attached but attach type can't be identified by section
  * name. Kept for backward compatibility.
@@ -2108,6 +2108,7 @@ static const struct {
        size_t len;
        enum bpf_prog_type prog_type;
        enum bpf_attach_type expected_attach_type;
+       int is_attachable;
        enum bpf_attach_type attach_type;
 } section_names[] = {
        BPF_PROG_SEC("socket",                  BPF_PROG_TYPE_SOCKET_FILTER),
@@ -2198,7 +2199,7 @@ int libbpf_attach_type_by_name(const char *name,
        for (i = 0; i < ARRAY_SIZE(section_names); i++) {
                if (strncmp(name, section_names[i].sec, section_names[i].len))
                        continue;
-               if (section_names[i].attach_type == -EINVAL)
+               if (!section_names[i].is_attachable)
                        return -EINVAL;
                *attach_type = section_names[i].attach_type;
                return 0;
index d3273b5b3173e123d087c624a34f5b834395da54..ae8180b11d5fe6dde18f822a262405e07479bc68 100644 (file)
@@ -11,6 +11,8 @@
 #include <bpf/bpf.h>
 #include <bpf/libbpf.h>
 
+#include "bpf_rlimit.h"
+
 const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector";
 const char *cfg_map_name = "jmp_table";
 bool cfg_attach = true;
index 42544a969abc63b734267e696c78d2b338be0ca7..a9bc6f82abc163d47876d4af1f2dcbe540a6c814 100755 (executable)
@@ -10,7 +10,7 @@ wait_for_ip()
        echo -n "Wait for testing link-local IP to become available "
        for _i in $(seq ${MAX_PING_TRIES}); do
                echo -n "."
-               if ping -6 -q -c 1 -W 1 ff02::1%${TEST_IF} >/dev/null 2>&1; then
+               if $PING6 -c 1 -W 1 ff02::1%${TEST_IF} >/dev/null 2>&1; then
                        echo " OK"
                        return
                fi
@@ -58,5 +58,6 @@ BPF_PROG_OBJ="${DIR}/test_skb_cgroup_id_kern.o"
 BPF_PROG_SECTION="cgroup_id_logger"
 BPF_PROG_ID=0
 PROG="${DIR}/test_skb_cgroup_id_user"
+type ping6 >/dev/null 2>&1 && PING6="ping6" || PING6="ping -6"
 
 main
index 9832a875a828979be26b8756cbd589d5cf5e44f1..3b9fdb8094aa28b5e5abbe99f15b1e4502869a68 100755 (executable)
@@ -4,7 +4,8 @@ set -eu
 
 ping_once()
 {
-       ping -${1} -q -c 1 -W 1 ${2%%/*} >/dev/null 2>&1
+       type ping${1} >/dev/null 2>&1 && PING="ping${1}" || PING="ping -${1}"
+       $PING -q -c 1 -W 1 ${2%%/*} >/dev/null 2>&1
 }
 
 wait_for_ip()
index 36f3d3009d1a079e57032b47b57bc306d045a3a8..6f61df62f690c69adceb2c328b231ab39b8b9c49 100644 (file)
@@ -76,7 +76,7 @@ struct bpf_test {
        int fixup_percpu_cgroup_storage[MAX_FIXUPS];
        const char *errstr;
        const char *errstr_unpriv;
-       uint32_t retval;
+       uint32_t retval, retval_unpriv;
        enum {
                UNDEF,
                ACCEPT,
@@ -3084,6 +3084,8 @@ static struct bpf_test tests[] = {
                .fixup_prog1 = { 2 },
                .result = ACCEPT,
                .retval = 42,
+               /* Verifier rewrite for unpriv skips tail call here. */
+               .retval_unpriv = 2,
        },
        {
                "stack pointer arithmetic",
@@ -6454,6 +6456,256 @@ static struct bpf_test tests[] = {
                .errstr = "R1 min value is negative",
                .prog_type = BPF_PROG_TYPE_TRACEPOINT,
        },
+       {
+               "map access: known scalar += value_ptr",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
+                       BPF_MOV64_IMM(BPF_REG_1, 4),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = ACCEPT,
+               .retval = 1,
+       },
+       {
+               "map access: value_ptr += known scalar",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
+                       BPF_MOV64_IMM(BPF_REG_1, 4),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = ACCEPT,
+               .retval = 1,
+       },
+       {
+               "map access: unknown scalar += value_ptr",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = ACCEPT,
+               .retval = 1,
+       },
+       {
+               "map access: value_ptr += unknown scalar",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = ACCEPT,
+               .retval = 1,
+       },
+       {
+               "map access: value_ptr += value_ptr",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_0),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = REJECT,
+               .errstr = "R0 pointer += pointer prohibited",
+       },
+       {
+               "map access: known scalar -= value_ptr",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
+                       BPF_MOV64_IMM(BPF_REG_1, 4),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_0),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = REJECT,
+               .errstr = "R1 tried to subtract pointer from scalar",
+       },
+       {
+               "map access: value_ptr -= known scalar",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
+                       BPF_MOV64_IMM(BPF_REG_1, 4),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = REJECT,
+               .errstr = "R0 min value is outside of the array range",
+       },
+       {
+               "map access: value_ptr -= known scalar, 2",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
+                       BPF_MOV64_IMM(BPF_REG_1, 6),
+                       BPF_MOV64_IMM(BPF_REG_2, 4),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_2),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = ACCEPT,
+               .retval = 1,
+       },
+       {
+               "map access: unknown scalar -= value_ptr",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_0),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = REJECT,
+               .errstr = "R1 tried to subtract pointer from scalar",
+       },
+       {
+               "map access: value_ptr -= unknown scalar",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = REJECT,
+               .errstr = "R0 min value is negative",
+       },
+       {
+               "map access: value_ptr -= unknown scalar, 2",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
+                       BPF_ALU64_IMM(BPF_OR, BPF_REG_1, 0x7),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0x7),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = ACCEPT,
+               .retval = 1,
+       },
+       {
+               "map access: value_ptr -= value_ptr",
+               .insns = {
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
+                       BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_0),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 3 },
+               .result = REJECT,
+               .errstr = "R0 invalid mem access 'inv'",
+               .errstr_unpriv = "R0 pointer -= pointer prohibited",
+       },
        {
                "map lookup helper access to map",
                .insns = {
@@ -13899,6 +14151,33 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_map_type prog_type,
        }
 }
 
+static int set_admin(bool admin)
+{
+       cap_t caps;
+       const cap_value_t cap_val = CAP_SYS_ADMIN;
+       int ret = -1;
+
+       caps = cap_get_proc();
+       if (!caps) {
+               perror("cap_get_proc");
+               return -1;
+       }
+       if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val,
+                               admin ? CAP_SET : CAP_CLEAR)) {
+               perror("cap_set_flag");
+               goto out;
+       }
+       if (cap_set_proc(caps)) {
+               perror("cap_set_proc");
+               goto out;
+       }
+       ret = 0;
+out:
+       if (cap_free(caps))
+               perror("cap_free");
+       return ret;
+}
+
 static void do_test_single(struct bpf_test *test, bool unpriv,
                           int *passes, int *errors)
 {
@@ -13907,6 +14186,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
        struct bpf_insn *prog = test->insns;
        int map_fds[MAX_NR_MAPS];
        const char *expected_err;
+       uint32_t expected_val;
        uint32_t retval;
        int i, err;
 
@@ -13926,6 +14206,8 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
                       test->result_unpriv : test->result;
        expected_err = unpriv && test->errstr_unpriv ?
                       test->errstr_unpriv : test->errstr;
+       expected_val = unpriv && test->retval_unpriv ?
+                      test->retval_unpriv : test->retval;
 
        reject_from_alignment = fd_prog < 0 &&
                                (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) &&
@@ -13959,16 +14241,20 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
                __u8 tmp[TEST_DATA_LEN << 2];
                __u32 size_tmp = sizeof(tmp);
 
+               if (unpriv)
+                       set_admin(true);
                err = bpf_prog_test_run(fd_prog, 1, test->data,
                                        sizeof(test->data), tmp, &size_tmp,
                                        &retval, NULL);
+               if (unpriv)
+                       set_admin(false);
                if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) {
                        printf("Unexpected bpf_prog_test_run error\n");
                        goto fail_log;
                }
-               if (!err && retval != test->retval &&
-                   test->retval != POINTER_VALUE) {
-                       printf("FAIL retval %d != %d\n", retval, test->retval);
+               if (!err && retval != expected_val &&
+                   expected_val != POINTER_VALUE) {
+                       printf("FAIL retval %d != %d\n", retval, expected_val);
                        goto fail_log;
                }
        }
@@ -14011,33 +14297,6 @@ static bool is_admin(void)
        return (sysadmin == CAP_SET);
 }
 
-static int set_admin(bool admin)
-{
-       cap_t caps;
-       const cap_value_t cap_val = CAP_SYS_ADMIN;
-       int ret = -1;
-
-       caps = cap_get_proc();
-       if (!caps) {
-               perror("cap_get_proc");
-               return -1;
-       }
-       if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val,
-                               admin ? CAP_SET : CAP_CLEAR)) {
-               perror("cap_set_flag");
-               goto out;
-       }
-       if (cap_set_proc(caps)) {
-               perror("cap_set_proc");
-               goto out;
-       }
-       ret = 0;
-out:
-       if (cap_free(caps))
-               perror("cap_free");
-       return ret;
-}
-
 static void get_unpriv_disabled()
 {
        char buf[2];
index 0150bb2741eb1a0f2a3c219e7316b37753a17298..117f6f35d72fac57ad87f0ed4772a50511d45cb4 100755 (executable)
 # Thus we set MTU to 10K on all involved interfaces. Then both unicast and
 # multicast traffic uses 8K frames.
 #
-# +-----------------------+                +----------------------------------+
-# | H1                    |                |                               H2 |
-# |                       |                |  unicast --> + $h2.111           |
-# |                       |                |  traffic     | 192.0.2.129/28    |
-# |          multicast    |                |              | e-qos-map 0:1     |
-# |          traffic      |                |              |                   |
-# | $h1 + <-----          |                |              + $h2               |
-# +-----|-----------------+                +--------------|-------------------+
-#       |                                                 |
-# +-----|-------------------------------------------------|-------------------+
-# |     + $swp1                                           + $swp2             |
-# |     | >1Gbps                                          | >1Gbps            |
-# | +---|----------------+                     +----------|----------------+  |
-# | |   + $swp1.1        |                     |          + $swp2.111      |  |
+# +---------------------------+            +----------------------------------+
+# | H1                        |            |                               H2 |
+# |                           |            |  unicast --> + $h2.111           |
+# |                 multicast |            |  traffic     | 192.0.2.129/28    |
+# |                 traffic   |            |              | e-qos-map 0:1     |
+# |           $h1 + <-----    |            |              |                   |
+# | 192.0.2.65/28 |           |            |              + $h2               |
+# +---------------|-----------+            +--------------|-------------------+
+#                 |                                       |
+# +---------------|---------------------------------------|-------------------+
+# |         $swp1 +                                       + $swp2             |
+# |        >1Gbps |                                       | >1Gbps            |
+# | +-------------|------+                     +----------|----------------+  |
+# | |     $swp1.1 +      |                     |          + $swp2.111      |  |
 # | |                BR1 |             SW      | BR111                     |  |
-# | |   + $swp3.1        |                     |          + $swp3.111      |  |
-# | +---|----------------+                     +----------|----------------+  |
-# |     \_________________________________________________/                   |
+# | |     $swp3.1 +      |                     |          + $swp3.111      |  |
+# | +-------------|------+                     +----------|----------------+  |
+# |               \_______________________________________/                   |
 # |                                    |                                      |
 # |                                    + $swp3                                |
 # |                                    | 1Gbps bottleneck                     |
@@ -51,6 +51,7 @@
 #                                      |
 #                                   +--|-----------------+
 #                                   |  + $h3          H3 |
+#                                   |  | 192.0.2.66/28   |
 #                                   |  |                 |
 #                                   |  + $h3.111         |
 #                                   |    192.0.2.130/28  |
@@ -59,6 +60,7 @@
 ALL_TESTS="
        ping_ipv4
        test_mc_aware
+       test_uc_aware
 "
 
 lib_dir=$(dirname $0)/../../../net/forwarding
@@ -68,14 +70,14 @@ source $lib_dir/lib.sh
 
 h1_create()
 {
-       simple_if_init $h1
+       simple_if_init $h1 192.0.2.65/28
        mtu_set $h1 10000
 }
 
 h1_destroy()
 {
        mtu_restore $h1
-       simple_if_fini $h1
+       simple_if_fini $h1 192.0.2.65/28
 }
 
 h2_create()
@@ -97,7 +99,7 @@ h2_destroy()
 
 h3_create()
 {
-       simple_if_init $h3
+       simple_if_init $h3 192.0.2.66/28
        mtu_set $h3 10000
 
        vlan_create $h3 111 v$h3 192.0.2.130/28
@@ -108,7 +110,7 @@ h3_destroy()
        vlan_destroy $h3 111
 
        mtu_restore $h3
-       simple_if_fini $h3
+       simple_if_fini $h3 192.0.2.66/28
 }
 
 switch_create()
@@ -251,7 +253,7 @@ measure_uc_rate()
        # average ingress rate to somewhat mitigate this.
        local min_ingress=2147483648
 
-       mausezahn $h2.111 -p 8000 -A 192.0.2.129 -B 192.0.2.130 -c 0 \
+       $MZ $h2.111 -p 8000 -A 192.0.2.129 -B 192.0.2.130 -c 0 \
                -a own -b $h3mac -t udp -q &
        sleep 1
 
@@ -291,7 +293,7 @@ test_mc_aware()
        check_err $? "Could not get high enough UC-only ingress rate"
        local ucth1=${uc_rate[1]}
 
-       mausezahn $h1 -p 8000 -c 0 -a own -b bc -t udp -q &
+       $MZ $h1 -p 8000 -c 0 -a own -b bc -t udp -q &
 
        local d0=$(date +%s)
        local t0=$(ethtool_stats_get $h3 rx_octets_prio_0)
@@ -311,7 +313,7 @@ test_mc_aware()
                        ret = 100 * ($ucth1 - $ucth2) / $ucth1
                        if (ret > 0) { ret } else { 0 }
                    ")
-       check_err $(bc <<< "$deg > 10")
+       check_err $(bc <<< "$deg > 25")
 
        local interval=$((d1 - d0))
        local mc_ir=$(rate $u0 $u1 $interval)
@@ -335,6 +337,51 @@ test_mc_aware()
        echo "    egress UC throughput  $(humanize ${uc_rate_2[1]})"
        echo "    ingress MC throughput $(humanize $mc_ir)"
        echo "    egress MC throughput  $(humanize $mc_er)"
+       echo
+}
+
+test_uc_aware()
+{
+       RET=0
+
+       $MZ $h2.111 -p 8000 -A 192.0.2.129 -B 192.0.2.130 -c 0 \
+               -a own -b $h3mac -t udp -q &
+
+       local d0=$(date +%s)
+       local t0=$(ethtool_stats_get $h3 rx_octets_prio_1)
+       local u0=$(ethtool_stats_get $swp2 rx_octets_prio_1)
+       sleep 1
+
+       local attempts=50
+       local passes=0
+       local i
+
+       for ((i = 0; i < attempts; ++i)); do
+               if $ARPING -c 1 -I $h1 -b 192.0.2.66 -q -w 0.1; then
+                       ((passes++))
+               fi
+
+               sleep 0.1
+       done
+
+       local d1=$(date +%s)
+       local t1=$(ethtool_stats_get $h3 rx_octets_prio_1)
+       local u1=$(ethtool_stats_get $swp2 rx_octets_prio_1)
+
+       local interval=$((d1 - d0))
+       local uc_ir=$(rate $u0 $u1 $interval)
+       local uc_er=$(rate $t0 $t1 $interval)
+
+       ((attempts == passes))
+       check_err $?
+
+       # Suppress noise from killing mausezahn.
+       { kill %% && wait; } 2>/dev/null
+
+       log_test "MC performace under UC overload"
+       echo "    ingress UC throughput $(humanize ${uc_ir})"
+       echo "    egress UC throughput  $(humanize ${uc_er})"
+       echo "    sent $attempts BC ARPs, got $passes responses"
 }
 
 trap cleanup EXIT