The following commit has been merged in the master branch: commit 60f7c503d971a731ee3c4f884a9f2e80d476730d Merge: 69f637c33560b02ae7313e0c142d847361cc723a be1b500212541a70006887bae558ff834d7365d0 Author: Linus Torvalds torvalds@linux-foundation.org Date: Wed Dec 16 13:34:31 2020 -0800
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "This consists of the usual driver updates (ufs, qla2xxx, smartpqi, target, zfcp, fnic, mpt3sas, ibmvfc) plus a load of cleanups, a major power management rework and a load of assorted minor updates.
There are a few core updates (formatting fixes being the big one) but nothing major this cycle"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (279 commits) scsi: mpt3sas: Update driver version to 36.100.00.00 scsi: mpt3sas: Handle trigger page after firmware update scsi: mpt3sas: Add persistent MPI trigger page scsi: mpt3sas: Add persistent SCSI sense trigger page scsi: mpt3sas: Add persistent Event trigger page scsi: mpt3sas: Add persistent Master trigger page scsi: mpt3sas: Add persistent trigger pages support scsi: mpt3sas: Sync time periodically between driver and firmware scsi: qla2xxx: Update version to 10.02.00.104-k scsi: qla2xxx: Fix device loss on 4G and older HBAs scsi: qla2xxx: If fcport is undergoing deletion complete I/O with retry scsi: qla2xxx: Fix the call trace for flush workqueue scsi: qla2xxx: Fix flash update in 28XX adapters on big endian machines scsi: qla2xxx: Handle aborts correctly for port undergoing deletion scsi: qla2xxx: Fix N2N and NVMe connect retry failure scsi: qla2xxx: Fix FW initialization error on big endian machines scsi: qla2xxx: Fix crash during driver load on big endian machines scsi: qla2xxx: Fix compilation issue in PPC systems scsi: qla2xxx: Don't check for fw_started while posting NVMe command scsi: qla2xxx: Tear down session if FW say it is down ...
diff --combined MAINTAINERS index baabfb96c76b,c021a3704857..a14cad29c031 --- a/MAINTAINERS +++ b/MAINTAINERS @@@ -929,18 -929,12 +929,18 @@@ L: linux-i2c@vger.kernel.or S: Maintained F: drivers/i2c/busses/i2c-amd-mp2*
+AMD PMC DRIVER +M: Shyam Sundar S K Shyam-sundar.S-k@amd.com +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/amd-pmc.* + AMD POWERPLAY M: Evan Quan evan.quan@amd.com L: amd-gfx@lists.freedesktop.org S: Supported T: git git://people.freedesktop.org/~agd5f/linux -F: drivers/gpu/drm/amd/powerplay/ +F: drivers/gpu/drm/amd/pm/powerplay/
AMD SEATTLE DEVICE TREE SUPPORT M: Brijesh Singh brijeshkumar.singh@amd.com @@@ -984,7 -978,7 +984,7 @@@ M: Michael Hennerich <Michael.Hennerich L: linux-iio@vger.kernel.org S: Supported W: http://ez.analog.com/community/linux-device-drivers -F: Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.txt +F: Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml F: drivers/iio/adc/ad7768-1.c
ANALOG DEVICES INC AD7780 DRIVER @@@ -1079,7 -1073,6 +1079,7 @@@ M: Hans Verkuil <hverkuil-cisco@xs4all. L: linux-media@vger.kernel.org S: Maintained F: drivers/media/i2c/adv7604* +F: Documentation/devicetree/bindings/media/i2c/adv7604.yaml
ANALOG DEVICES INC ADV7842 DRIVER M: Hans Verkuil hverkuil-cisco@xs4all.nl @@@ -1180,6 -1173,16 +1180,6 @@@ S: Supporte F: Documentation/devicetree/bindings/rtc/google,goldfish-rtc.txt F: drivers/rtc/rtc-goldfish.c
-ANDROID ION DRIVER -M: Laura Abbott labbott@redhat.com -M: Sumit Semwal sumit.semwal@linaro.org -L: devel@driverdev.osuosl.org -L: dri-devel@lists.freedesktop.org -L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers) -S: Supported -F: drivers/staging/android/ion -F: drivers/staging/android/uapi/ion.h - AOA (Apple Onboard Audio) ALSA DRIVER M: Johannes Berg johannes@sipsolutions.net L: linuxppc-dev@lists.ozlabs.org @@@ -1276,7 -1279,7 +1276,7 @@@ M: Igor Russkikh <irusskikh@marvell.com L: netdev@vger.kernel.org S: Supported W: https://www.marvell.com/ -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ F: Documentation/networking/device_drivers/ethernet/aquantia/atlantic.rst F: drivers/net/ethernet/aquantia/atlantic/
@@@ -1483,20 -1486,10 +1483,20 @@@ F: Documentation/devicetree/bindings/io F: drivers/iommu/arm/ F: drivers/iommu/io-pgtable-arm*
+ARM AND ARM64 SoC SUB-ARCHITECTURES (COMMON PARTS) +M: Arnd Bergmann arnd@arndb.de +M: Olof Johansson olof@lixom.net +M: soc@kernel.org +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git +F: arch/arm/boot/dts/Makefile +F: arch/arm64/boot/dts/Makefile + ARM SUB-ARCHITECTURES L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained -T: git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git F: arch/arm/mach-*/ F: arch/arm/plat-*/
@@@ -1508,7 -1501,7 +1508,7 @@@ S: Maintaine F: Documentation/devicetree/bindings/arm/actions.yaml F: Documentation/devicetree/bindings/clock/actions,owl-cmu.txt F: Documentation/devicetree/bindings/dma/owl-dma.yaml -F: Documentation/devicetree/bindings/i2c/i2c-owl.txt +F: Documentation/devicetree/bindings/i2c/i2c-owl.yaml F: Documentation/devicetree/bindings/interrupt-controller/actions,owl-sirq.yaml F: Documentation/devicetree/bindings/mmc/owl-mmc.yaml F: Documentation/devicetree/bindings/pinctrl/actions,* @@@ -1553,7 -1546,6 +1553,7 @@@ F: drivers/clk/sunxi ARM/Allwinner sunXi SoC support M: Maxime Ripard mripard@kernel.org M: Chen-Yu Tsai wens@csie.org +R: Jernej Skrabec jernej.skrabec@siol.net L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git @@@ -1731,13 -1723,11 +1731,13 @@@ F: arch/arm/mach-ep93xx/micro9.
ARM/CORESIGHT FRAMEWORK AND DRIVERS M: Mathieu Poirier mathieu.poirier@linaro.org -R: Suzuki K Poulose suzuki.poulose@arm.com +M: Suzuki K Poulose suzuki.poulose@arm.com R: Mike Leach mike.leach@linaro.org +R: Leo Yan leo.yan@linaro.org L: coresight@lists.linaro.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux.git F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* F: Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt F: Documentation/devicetree/bindings/arm/coresight-cti.yaml @@@ -1799,6 -1789,14 +1799,6 @@@ F: drivers/firmware/turris-mox-rwtm. F: drivers/gpio/gpio-moxtet.c F: include/linux/moxtet.h
-ARM/EBSA110 MACHINE SUPPORT -M: Russell King linux@armlinux.org.uk -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained -W: http://www.armlinux.org.uk/ -F: arch/arm/mach-ebsa110/ -F: drivers/net/ethernet/amd/am79c961a.* - ARM/ENERGY MICRO (SILICON LABS) EFM32 SUPPORT M: Uwe Kleine-K��nig u.kleine-koenig@pengutronix.de R: Pengutronix Kernel Team kernel@pengutronix.de @@@ -1996,6 -1994,7 +1996,6 @@@ N: lpc18x
ARM/LPC32XX SOC SUPPORT M: Vladimir Zapolskiy vz@mleia.com -M: Sylvain Lemieux slemieux.tyco@gmail.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://github.com/vzapolskiy/linux-lpc32xx.git @@@ -2013,6 -2012,7 +2013,6 @@@ M: Philipp Zabel <philipp.zabel@gmail.c S: Maintained
ARM/Marvell Dove/MV78xx0/Orion SOC support -M: Jason Cooper jason@lakedaemon.net M: Andrew Lunn andrew@lunn.ch M: Sebastian Hesselbarth sebastian.hesselbarth@gmail.com M: Gregory Clement gregory.clement@bootlin.com @@@ -2029,6 -2029,7 +2029,6 @@@ F: arch/arm/plat-orion F: drivers/soc/dove/
ARM/Marvell Kirkwood and Armada 370, 375, 38x, 39x, XP, 3700, 7K/8K, CN9130 SOC support -M: Jason Cooper jason@lakedaemon.net M: Andrew Lunn andrew@lunn.ch M: Gregory Clement gregory.clement@bootlin.com M: Sebastian Hesselbarth sebastian.hesselbarth@gmail.com @@@ -2118,13 -2119,6 +2118,13 @@@ T: git git://github.com/microchip-ung/l F: arch/arm64/boot/dts/microchip/ N: sparx5
+Microchip Timer Counter Block (TCB) Capture Driver +M: Kamel Bouhara kamel.bouhara@bootlin.com +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/counter/microchip-tcb-capture.c + ARM/MIOA701 MACHINE SUPPORT M: Robert Jarzmik robert.jarzmik@free.fr L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@@ -2380,7 -2374,8 +2380,7 @@@ F: drivers/i2c/busses/i2c-rk3x. F: sound/soc/rockchip/ N: rockchip
-ARM/SAMSUNG EXYNOS ARM ARCHITECTURES -M: Kukjin Kim kgene@kernel.org +ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES M: Krzysztof Kozlowski krzk@kernel.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-samsung-soc@vger.kernel.org @@@ -2409,7 -2404,15 +2409,7 @@@ N: s3c241 N: s3c64xx N: s5pv210
-ARM/SAMSUNG MOBILE MACHINE SUPPORT -M: Kyungmin Park kyungmin.park@samsung.com -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained -F: arch/arm/mach-s5pv210/ - ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT -M: Kyungmin Park kyungmin.park@samsung.com -M: Kamil Debski kamil@wypas.org M: Andrzej Hajda a.hajda@samsung.com L: linux-arm-kernel@lists.infradead.org L: linux-media@vger.kernel.org @@@ -2434,6 -2437,9 +2434,6 @@@ S: Maintaine F: drivers/media/platform/s5p-jpeg/
ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT -M: Kyungmin Park kyungmin.park@samsung.com -M: Kamil Debski kamil@wypas.org -M: Jeongtae Park jtp.park@samsung.com M: Andrzej Hajda a.hajda@samsung.com L: linux-arm-kernel@lists.infradead.org L: linux-media@vger.kernel.org @@@ -2480,7 -2486,7 +2480,7 @@@ F: drivers/clk/socfpga ARM/SOCFPGA EDAC SUPPORT M: Dinh Nguyen dinguyen@kernel.org S: Maintained -F: drivers/edac/altera_edac. +F: drivers/edac/altera_edac.[ch]
ARM/SPREADTRUM SoC SUPPORT M: Orson Zhai orsonzhai@gmail.com @@@ -2636,8 -2642,10 +2636,8 @@@ F: drivers/pinctrl/visconti N: visconti
ARM/UNIPHIER ARCHITECTURE -M: Masahiro Yamada yamada.masahiro@socionext.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained -T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-uniphier.git +S: Orphan F: Documentation/devicetree/bindings/arm/socionext/uniphier.yaml F: Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml F: Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml @@@ -2958,7 -2966,7 +2958,7 @@@ ATMEL MAXTOUCH DRIVE M: Nick Dyer nick@shmanahar.org S: Maintained T: git git://github.com/ndyer/linux.git -F: Documentation/devicetree/bindings/input/atmel,maxtouch.txt +F: Documentation/devicetree/bindings/input/atmel,maxtouch.yaml F: drivers/input/touchscreen/atmel_mxt_ts.c
ATMEL WIRELESS DRIVER @@@ -2977,8 -2985,6 +2977,8 @@@ L: linux-kernel@vger.kernel.or S: Maintained F: arch/*/include/asm/atomic*.h F: include/*/atomic*.h +F: include/linux/refcount.h +F: Documentation/atomic_*.txt F: scripts/atomic/
ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER @@@ -3117,6 -3123,8 +3117,6 @@@ Q: https://patchwork.open-mesh.org/proj B: https://www.open-mesh.org/projects/batman-adv/issues C: irc://chat.freenode.net/batman T: git https://git.open-mesh.org/linux-merge.git -F: Documentation/ABI/obsolete/sysfs-class-net-batman-adv -F: Documentation/ABI/obsolete/sysfs-class-net-mesh F: Documentation/networking/batman-adv.rst F: include/uapi/linux/batadv_packet.h F: include/uapi/linux/batman_adv.h @@@ -3200,9 -3208,8 +3200,9 @@@ F: drivers/mtd/devices/block2mtd. BLUETOOTH DRIVERS M: Marcel Holtmann marcel@holtmann.org M: Johan Hedberg johan.hedberg@gmail.com +M: Luiz Augusto von Dentz luiz.dentz@gmail.com L: linux-bluetooth@vger.kernel.org -S: Maintained +S: Supported W: http://www.bluez.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git @@@ -3211,9 -3218,8 +3211,9 @@@ F: drivers/bluetooth BLUETOOTH SUBSYSTEM M: Marcel Holtmann marcel@holtmann.org M: Johan Hedberg johan.hedberg@gmail.com +M: Luiz Augusto von Dentz luiz.dentz@gmail.com L: linux-bluetooth@vger.kernel.org -S: Maintained +S: Supported W: http://www.bluez.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git @@@ -3240,12 -3246,12 +3240,12 @@@ F: drivers/iio/accel/bma400 BPF (Safe dynamic programs and tools) M: Alexei Starovoitov ast@kernel.org M: Daniel Borkmann daniel@iogearbox.net +M: Andrii Nakryiko andrii@kernel.org R: Martin KaFai Lau kafai@fb.com R: Song Liu songliubraving@fb.com R: Yonghong Song yhs@fb.com -R: Andrii Nakryiko andrii@kernel.org R: John Fastabend john.fastabend@gmail.com -R: KP Singh kpsingh@chromium.org +R: KP Singh kpsingh@kernel.org L: netdev@vger.kernel.org L: bpf@vger.kernel.org S: Supported @@@ -3363,17 -3369,6 +3363,17 @@@ S: Supporte F: arch/x86/net/ X: arch/x86/net/bpf_jit_comp32.c
+BPF LSM (Security Audit and Enforcement using BPF) +M: KP Singh kpsingh@kernel.org +R: Florent Revest revest@chromium.org +R: Brendan Jackman jackmanb@chromium.org +L: bpf@vger.kernel.org +S: Maintained +F: Documentation/bpf/bpf_lsm.rst +F: include/linux/bpf_lsm.h +F: kernel/bpf/bpf_lsm.c +F: security/bpf/ + BROADCOM B44 10/100 ETHERNET DRIVER M: Michael Chan michael.chan@broadcom.com L: netdev@vger.kernel.org @@@ -3546,12 -3541,11 +3546,12 @@@ BROADCOM BRCM80211 IEEE802.11n WIRELES M: Arend van Spriel arend.vanspriel@broadcom.com M: Franky Lin franky.lin@broadcom.com M: Hante Meuleman hante.meuleman@broadcom.com -M: Chi-Hsien Lin chi-hsien.lin@cypress.com -M: Wright Feng wright.feng@cypress.com +M: Chi-hsien Lin chi-hsien.lin@infineon.com +M: Wright Feng wright.feng@infineon.com +M: Chung-hsien Hsu chung-hsien.hsu@infineon.com L: linux-wireless@vger.kernel.org L: brcm80211-dev-list.pdl@broadcom.com -L: brcm80211-dev-list@cypress.com +L: SHA-cyfmac-dev-list@infineon.com S: Supported F: drivers/net/wireless/broadcom/brcm80211/
@@@ -3578,14 -3572,6 +3578,14 @@@ S: Maintaine F: Documentation/devicetree/bindings/usb/brcm,bcm7445-ehci.yaml F: drivers/usb/host/ehci-brcm.*
+BROADCOM BRCMSTB USB PIN MAP DRIVER +M: Al Cooper alcooperx@gmail.com +L: linux-usb@vger.kernel.org +L: bcm-kernel-feedback-list@broadcom.com +S: Maintained +F: Documentation/devicetree/bindings/usb/brcm,usb-pinmap.yaml +F: drivers/usb/misc/brcmstb-usb-pinmap.c + BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER M: Al Cooper alcooperx@gmail.com L: linux-kernel@vger.kernel.org @@@ -3871,11 -3857,10 +3871,11 @@@ CADENCE USB3 DRD IP DRIVE M: Peter Chen peter.chen@nxp.com M: Pawel Laszczak pawell@cadence.com M: Roger Quadros rogerq@ti.com +R: Aswath Govindraju a-govindraju@ti.com L: linux-usb@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git -F: Documentation/devicetree/bindings/usb/cdns-usb3.txt +F: Documentation/devicetree/bindings/usb/cdns,usb3.yaml F: drivers/usb/cdns3/
CADET FM/AM RADIO RECEIVER DRIVER @@@ -3887,8 -3872,9 +3887,8 @@@ T: git git://linuxtv.org/media_tree.gi F: drivers/media/radio/radio-cadet*
CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER -M: Jonathan Corbet corbet@lwn.net L: linux-media@vger.kernel.org -S: Maintained +S: Orphan T: git git://linuxtv.org/media_tree.git F: Documentation/admin-guide/media/cafe_ccic* F: drivers/media/platform/marvell-ccic/ @@@ -4301,7 -4287,6 +4301,7 @@@ B: https://github.com/ClangBuiltLinux/l C: irc://chat.freenode.net/clangbuiltlinux F: Documentation/kbuild/llvm.rst F: scripts/clang-tools/ +F: scripts/lld-version.sh K: \b(?i:clang|llvm)\b
CLEANCACHE API @@@ -4369,7 -4354,7 +4369,7 @@@ CODA V4L2 MEM2MEM DRIVE M: Philipp Zabel p.zabel@pengutronix.de L: linux-media@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/media/coda.txt +F: Documentation/devicetree/bindings/media/coda.yaml F: drivers/media/platform/coda/
CODE OF CONDUCT @@@ -4511,13 -4496,6 +4511,13 @@@ L: linux-hwmon@vger.kernel.or S: Maintained F: drivers/hwmon/corsair-cpro.c
+CORSAIR-PSU HARDWARE MONITOR DRIVER +M: Wilken Gottwalt wilken.gottwalt@posteo.net +L: linux-hwmon@vger.kernel.org +S: Maintained +F: Documentation/hwmon/corsair-psu.rst +F: drivers/hwmon/corsair-psu.c + COSA/SRP SYNC SERIAL DRIVER M: Jan "Yenya" Kasprzak kas@fi.muni.cz S: Maintained @@@ -4735,7 -4713,7 +4735,7 @@@ T: git git://linuxtv.org/anttip/media_t F: drivers/media/dvb-frontends/cxd2820r*
CXGB3 ETHERNET DRIVER (CXGB3) -M: Vishal Kulkarni vishal@chelsio.com +M: Raju Rangoju rajur@chelsio.com L: netdev@vger.kernel.org S: Supported W: http://www.chelsio.com @@@ -4767,7 -4745,7 +4767,7 @@@ W: http://www.chelsio.co F: drivers/net/ethernet/chelsio/inline_crypto/
CXGB4 ETHERNET DRIVER (CXGB4) -M: Vishal Kulkarni vishal@chelsio.com +M: Raju Rangoju rajur@chelsio.com L: netdev@vger.kernel.org S: Supported W: http://www.chelsio.com @@@ -4789,7 -4767,7 +4789,7 @@@ F: drivers/infiniband/hw/cxgb4 F: include/uapi/rdma/cxgb4-abi.h
CXGB4VF ETHERNET DRIVER (CXGB4VF) -M: Vishal Kulkarni vishal@gmail.com +M: Raju Rangoju rajur@chelsio.com L: netdev@vger.kernel.org S: Supported W: http://www.chelsio.com @@@ -5013,15 -4991,6 +5013,15 @@@ M: Mario Limonciello <mario.limonciello S: Maintained F: drivers/platform/x86/dell-wmi-descriptor.c
+DELL WMI SYSMAN DRIVER +M: Divya Bharathi divya.bharathi@dell.com +M: Mario Limonciello mario.limonciello@dell.com +M: Prasanth Ksr prasanth.ksr@dell.com +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: Documentation/ABI/testing/sysfs-class-firmware-attributes +F: drivers/platform/x86/dell-wmi-sysman/ + DELL WMI NOTIFICATIONS DRIVER M: Matthew Garrett mjg59@srcf.ucam.org M: Pali Roh��r pali@kernel.org @@@ -5037,8 -5006,9 +5037,8 @@@ T: git git://linuxtv.org/media_tree.gi F: drivers/media/platform/sti/delta
DENALI NAND DRIVER -M: Masahiro Yamada yamada.masahiro@socionext.com L: linux-mtd@lists.infradead.org -S: Supported +S: Orphan F: drivers/mtd/nand/raw/denali*
DESIGNWARE EDMA CORE IP DRIVER @@@ -5151,9 -5121,7 +5151,9 @@@ M: Support Opensource <support.opensour S: Supported W: http://www.dialog-semiconductor.com/products F: Documentation/devicetree/bindings/input/da90??-onkey.txt +F: Documentation/devicetree/bindings/input/dlg,da72??.txt F: Documentation/devicetree/bindings/mfd/da90*.txt +F: Documentation/devicetree/bindings/regulator/dlg,da9*.yaml F: Documentation/devicetree/bindings/regulator/da92*.txt F: Documentation/devicetree/bindings/regulator/slg51000.txt F: Documentation/devicetree/bindings/sound/da[79]*.txt @@@ -5163,7 -5131,6 +5163,7 @@@ F: Documentation/hwmon/da90??.rs F: drivers/gpio/gpio-da90??.c F: drivers/hwmon/da90??-hwmon.c F: drivers/iio/adc/da91??-*.c +F: drivers/input/misc/da72??.[ch] F: drivers/input/misc/da90??_onkey.c F: drivers/input/touchscreen/da9052_tsi.c F: drivers/leds/leds-da90??.c @@@ -5179,7 -5146,6 +5179,7 @@@ F: drivers/rtc/rtc-da90??. F: drivers/thermal/da90??-thermal.c F: drivers/video/backlight/da90??_bl.c F: drivers/watchdog/da90??_wdt.c +F: include/dt-bindings/regulator/dlg,da9*-regulator.h F: include/linux/mfd/da903x.h F: include/linux/mfd/da9052/ F: include/linux/mfd/da9055/ @@@ -5614,13 -5580,6 +5614,13 @@@ T: git git://anongit.freedesktop.org/dr F: Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml F: drivers/gpu/drm/panel/panel-novatek-nt35510.c
+DRM DRIVER FOR NOVATEK NT36672A PANELS +M: Sumit Semwal sumit.semwal@linaro.org +S: Maintained +T: git git://anongit.freedesktop.org/drm/drm-misc +F: Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml +F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c + DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS M: Ben Skeggs bskeggs@redhat.com L: dri-devel@lists.freedesktop.org @@@ -5908,7 -5867,6 +5908,7 @@@ S: Supporte F: Documentation/devicetree/bindings/display/mediatek/ F: drivers/gpu/drm/mediatek/ F: drivers/phy/mediatek/phy-mtk-hdmi* +F: drivers/phy/mediatek/phy-mtk-mipi*
DRM DRIVERS FOR NVIDIA TEGRA M: Thierry Reding thierry.reding@gmail.com @@@ -6001,7 -5959,6 +6001,7 @@@ F: include/uapi/drm/v3d_drm.
DRM DRIVERS FOR VC4 M: Eric Anholt eric@anholt.net +M: Maxime Ripard mripard@kernel.org S: Supported T: git git://github.com/anholt/linux T: git git://anongit.freedesktop.org/drm/drm-misc @@@ -6396,13 -6353,6 +6396,13 @@@ L: linux-edac@vger.kernel.or S: Maintained F: drivers/edac/ie31200_edac.c
+EDAC-IGEN6 +M: Tony Luck tony.luck@intel.com +R: Qiuxu Zhuo qiuxu.zhuo@intel.com +L: linux-edac@vger.kernel.org +S: Maintained +F: drivers/edac/igen6_edac.c + EDAC-MPC85XX M: Johannes Thumshirn morbidrsa@gmail.com L: linux-edac@vger.kernel.org @@@ -6452,7 -6402,7 +6452,7 @@@ EDAC-SKYLAK M: Tony Luck tony.luck@intel.com L: linux-edac@vger.kernel.org S: Maintained -F: drivers/edac/skx_*.c +F: drivers/edac/skx_*.[ch]
EDAC-TI M: Tero Kristo t-kristo@ti.com @@@ -6668,7 -6618,6 +6668,7 @@@ Q: http://patchwork.ozlabs.org/project/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git F: Documentation/filesystems/ext4/ F: fs/ext4/ +F: include/trace/events/ext4.h
Extended Verification Module (EVM) M: Mimi Zohar zohar@linux.ibm.com @@@ -6959,10 -6908,17 +6959,10 @@@ S: Maintaine W: http://floatingpoint.sourceforge.net/emulator/index.html F: arch/x86/math-emu/
-FRAME RELAY DLCI/FRAD (Sangoma drivers too) -L: netdev@vger.kernel.org -S: Orphan -F: drivers/net/wan/dlci.c -F: drivers/net/wan/sdla.c - FRAMEBUFFER LAYER -M: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com L: dri-devel@lists.freedesktop.org L: linux-fbdev@vger.kernel.org -S: Maintained +S: Orphan Q: http://patchwork.kernel.org/project/linux-fbdev/list/ T: git git://anongit.freedesktop.org/drm/drm-misc F: Documentation/fb/ @@@ -7339,6 -7295,7 +7339,6 @@@ F: drivers/staging/gasket
GCC PLUGINS M: Kees Cook keescook@chromium.org -R: Emese Revfy re.emese@gmail.com L: linux-hardening@vger.kernel.org S: Maintained F: Documentation/kbuild/gcc-plugins.rst @@@ -7380,17 -7337,6 +7380,17 @@@ S: Maintaine F: drivers/base/arch_topology.c F: include/linux/arch_topology.h
+GENERIC ENTRY CODE +M: Thomas Gleixner tglx@linutronix.de +M: Peter Zijlstra peterz@infradead.org +M: Andy Lutomirski luto@kernel.org +L: linux-kernel@vger.kernel.org +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/entry +F: include/linux/entry-common.h +F: include/linux/entry-kvm.h +F: kernel/entry/ + GENERIC GPIO I2C DRIVER M: Wolfram Sang wsa+renesas@sang-engineering.com S: Supported @@@ -7755,9 -7701,9 +7755,9 @@@ F: drivers/clocksource/h8300_*. F: drivers/irqchip/irq-renesas-h8*.c
HABANALABS PCI DRIVER -M: Oded Gabbay oded.gabbay@gmail.com +M: Oded Gabbay ogabbay@kernel.org S: Supported -T: git https://github.com/HabanaAI/linux.git +T: git https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/linux.git F: Documentation/ABI/testing/debugfs-driver-habanalabs F: Documentation/ABI/testing/sysfs-driver-habanalabs F: drivers/misc/habanalabs/ @@@ -7955,15 -7901,6 +7955,15 @@@ F: include/linux/hippidevice. F: include/uapi/linux/if_hippi.h F: net/802/hippi.c
+HIRSCHMANN HELLCREEK ETHERNET SWITCH DRIVER +M: Kurt Kanzenbach kurt@linutronix.de +L: netdev@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/net/dsa/hirschmann,hellcreek.yaml +F: drivers/net/dsa/hirschmann/* +F: include/linux/platform_data/hirschmann-hellcreek.h +F: net/dsa/tag_hellcreek.c + HISILICON DMA DRIVER M: Zhou Wang wangzhou1@hisilicon.com L: dmaengine@vger.kernel.org @@@ -7983,7 -7920,7 +7983,7 @@@ HISILICON LPC BUS DRIVE M: john.garry@huawei.com S: Maintained W: http://www.hisilicon.com -F: Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt +F: Documentation/devicetree/bindings/arm/hisilicon/low-pin-count.yaml F: drivers/bus/hisi_lpc.c
HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3) @@@ -8062,7 -7999,7 +8062,7 @@@ F: drivers/staging/hikey9xx HISILICON TRUE RANDOM NUMBER GENERATOR V2 SUPPORT M: Zaibo Xu xuzaibo@huawei.com S: Maintained -F: drivers/char/hw_random/hisi-trng-v2.c +F: drivers/crypto/hisilicon/trng/trng.c
HISILICON V3XX SPI NOR FLASH Controller Driver M: John Garry john.garry@huawei.com @@@ -8690,7 -8627,7 +8690,7 @@@ INA209 HARDWARE MONITOR DRIVE M: Guenter Roeck linux@roeck-us.net L: linux-hwmon@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/hwmon/ina2xx.txt +F: Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml F: Documentation/hwmon/ina209.rst F: drivers/hwmon/ina209.c
@@@ -8736,16 -8673,19 +8736,16 @@@ F: include/uapi/rdma F: samples/bpf/ibumad_kern.c F: samples/bpf/ibumad_user.c
-INGENIC JZ4780 DMA Driver -M: Zubair Lutfullah Kakakhel Zubair.Kakakhel@imgtec.com -S: Maintained -F: drivers/dma/dma-jz4780.c - INGENIC JZ4780 NAND DRIVER M: Harvey Hunt harveyhuntnexus@gmail.com L: linux-mtd@lists.infradead.org +L: linux-mips@vger.kernel.org S: Maintained F: drivers/mtd/nand/raw/ingenic/
INGENIC JZ47xx SoCs M: Paul Cercueil paul@crapouillou.net +L: linux-mips@vger.kernel.org S: Maintained F: arch/mips/boot/dts/ingenic/ F: arch/mips/generic/board-ingenic.c @@@ -8893,8 -8833,8 +8893,8 @@@ S: Supporte W: http://www.intel.com/support/feedback.htm W: http://e1000.sourceforge.net/ Q: http://patchwork.ozlabs.org/project/intel-wired-lan/list/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-queue.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue.git F: Documentation/networking/device_drivers/ethernet/intel/ F: drivers/net/ethernet/intel/ F: drivers/net/ethernet/intel/*/ @@@ -9018,23 -8958,6 +9018,23 @@@ M: Deepak Saxena <dsaxena@plexity.net S: Maintained F: drivers/char/hw_random/ixp4xx-rng.c
+INTEL KEEM BAY DRM DRIVER +M: Anitha Chrisanthus anitha.chrisanthus@intel.com +M: Edmund Dea edmund.j.dea@intel.com +S: Maintained +F: Documentation/devicetree/bindings/display/intel,kmb_display.yaml +F: drivers/gpu/drm/kmb/ + +INTEL KEEM BAY OCS AES/SM4 CRYPTO DRIVER +M: Daniele Alessandrelli daniele.alessandrelli@intel.com +S: Maintained +F: Documentation/devicetree/bindings/crypto/intel,keembay-ocs-aes.yaml +F: drivers/crypto/keembay/Kconfig +F: drivers/crypto/keembay/Makefile +F: drivers/crypto/keembay/keembay-ocs-aes-core.c +F: drivers/crypto/keembay/ocs-aes.c +F: drivers/crypto/keembay/ocs-aes.h + INTEL MANAGEMENT ENGINE (mei) M: Tomas Winkler tomas.winkler@intel.com L: linux-kernel@vger.kernel.org @@@ -9053,6 -8976,22 +9053,6 @@@ S: Supporte W: https://01.org/linux-acpi F: drivers/platform/x86/intel_menlow.c
-INTEL MIC DRIVERS (mic) -M: Sudeep Dutt sudeep.dutt@intel.com -M: Ashutosh Dixit ashutosh.dixit@intel.com -S: Supported -W: https://github.com/sudeepdutt/mic -W: http://software.intel.com/en-us/mic-developer -F: Documentation/misc-devices/mic/ -F: drivers/dma/mic_x100_dma.c -F: drivers/dma/mic_x100_dma.h -F: drivers/misc/mic/ -F: include/linux/mic_bus.h -F: include/linux/scif.h -F: include/uapi/linux/mic_common.h -F: include/uapi/linux/mic_ioctl.h -F: include/uapi/linux/scif_ioctl.h - INTEL P-Unit IPC DRIVER M: Zha Qipeng qipeng.zha@intel.com L: platform-driver-x86@vger.kernel.org @@@ -9082,12 -9021,6 +9082,12 @@@ F: drivers/mfd/intel_soc_pmic F: include/linux/mfd/intel_msic.h F: include/linux/mfd/intel_soc_pmic*
+INTEL PMT DRIVER +M: "David E. Box" david.e.box@linux.intel.com +S: Maintained +F: drivers/mfd/intel_pmt.c +F: drivers/platform/x86/intel_pmt_* + INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT M: Stanislav Yakovlev stas.yakovlev@gmail.com L: linux-wireless@vger.kernel.org @@@ -9163,13 -9096,26 +9163,13 @@@ S: Supporte F: drivers/net/wireless/intel/iwlegacy/
INTEL WIRELESS WIFI LINK (iwlwifi) -M: Johannes Berg johannes.berg@intel.com -M: Emmanuel Grumbach emmanuel.grumbach@intel.com M: Luca Coelho luciano.coelho@intel.com -M: Intel Linux Wireless linuxwifi@intel.com L: linux-wireless@vger.kernel.org S: Supported W: https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git F: drivers/net/wireless/intel/iwlwifi/
-INTEL WIRELESS WIMAX CONNECTION 2400 -M: Inaky Perez-Gonzalez inaky.perez-gonzalez@intel.com -M: linux-wimax@intel.com -L: wimax@linuxwimax.org (subscribers-only) -S: Supported -W: http://linuxwimax.org -F: Documentation/admin-guide/wimax/i2400m.rst -F: drivers/net/wimax/i2400m/ -F: include/uapi/linux/wimax/i2400m.h - INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER M: Jithu Joseph jithu.joseph@intel.com R: Maurice Ma maurice.ma@intel.com @@@ -9199,19 -9145,6 +9199,19 @@@ F: Documentation/x86/intel_txt.rs F: arch/x86/kernel/tboot.c F: include/linux/tboot.h
+INTEL SGX +M: Jarkko Sakkinen jarkko@kernel.org +L: linux-sgx@vger.kernel.org +S: Supported +Q: https://patchwork.kernel.org/project/intel-sgx/list/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-sgx.git +F: Documentation/x86/sgx.rst +F: arch/x86/entry/vdso/vsgx.S +F: arch/x86/include/uapi/asm/sgx.h +F: arch/x86/kernel/cpu/sgx/* +F: tools/testing/selftests/sgx/* +K: \bSGX_ + INTERCONNECT API M: Georgi Djakov georgi.djakov@linaro.org L: linux-pm@vger.kernel.org @@@ -9227,7 -9160,7 +9227,7 @@@ INVENSENSE ICM-426xx IMU DRIVE M: Jean-Baptiste Maneyrol jmaneyrol@invensense.com L: linux-iio@vger.kernel.org S: Maintained -W https://invensense.tdk.com/ +W: https://invensense.tdk.com/ F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml F: drivers/iio/imu/inv_icm42600/
@@@ -9258,7 -9191,6 +9258,7 @@@ F: include/linux/iomap.
IOMMU DRIVERS M: Joerg Roedel joro@8bytes.org +M: Will Deacon will@kernel.org L: iommu@lists.linux-foundation.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git @@@ -9342,6 -9274,7 +9342,6 @@@ F: kernel/irq
IRQCHIP DRIVERS M: Thomas Gleixner tglx@linutronix.de -M: Jason Cooper jason@lakedaemon.net M: Marc Zyngier maz@kernel.org L: linux-kernel@vger.kernel.org S: Maintained @@@ -9707,7 -9640,7 +9707,7 @@@ F: arch/arm64/kvm F: include/kvm/arm_*
KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips) -M: Huacai Chen chenhc@lemote.com +M: Huacai Chen chenhuacai@kernel.org M: Aleksandar Markovic aleksandar.qemu.devel@gmail.com L: linux-mips@vger.kernel.org L: kvm@vger.kernel.org @@@ -9741,7 -9674,6 +9741,7 @@@ F: Documentation/virt/kvm/s390 F: arch/s390/include/asm/gmap.h F: arch/s390/include/asm/kvm* F: arch/s390/include/uapi/asm/kvm* +F: arch/s390/kernel/uv.c F: arch/s390/kvm/ F: arch/s390/mm/gmap.c F: tools/testing/selftests/kvm/*/s390x/ @@@ -9930,6 -9862,13 +9930,6 @@@ S: Maintaine F: arch/mips/lantiq F: drivers/soc/lantiq
-LAPB module -L: linux-x25@vger.kernel.org -S: Orphan -F: Documentation/networking/lapb-module.rst -F: include/*/lapb.h -F: net/lapb/ - LASI 53c700 driver for PARISC M: "James E.J. Bottomley" James.Bottomley@HansenPartnership.com L: linux-scsi@vger.kernel.org @@@ -10458,8 -10397,6 +10458,8 @@@ L: linux-m68k@lists.linux-m68k.or S: Maintained W: http://www.mac.linux-m68k.org/ F: arch/m68k/mac/ +F: drivers/macintosh/adb-iop.c +F: drivers/macintosh/via-macii.c
M68K ON HP9000/300 M: Philip Blundell philb@gnu.org @@@ -10559,7 -10496,6 +10559,7 @@@ M: Srujana Challa <schalla@marvell.com L: linux-crypto@vger.kernel.org S: Maintained F: drivers/crypto/marvell/ +F: include/linux/soc/marvell/octeontx2/
MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) M: Mirko Lindner mlindner@marvell.com @@@ -10603,14 -10539,6 +10603,14 @@@ L: netdev@vger.kernel.or S: Maintained F: drivers/net/ethernet/marvell/mvneta.*
+MARVELL MVPP2 ETHERNET DRIVER +M: Marcin Wojtas mw@semihalf.com +M: Russell King linux@armlinux.org.uk +L: netdev@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/net/marvell-pp2.txt +F: drivers/net/ethernet/marvell/mvpp2/ + MARVELL MWIFIEX WIRELESS DRIVER M: Amitkumar Karwar amitkarwar@gmail.com M: Ganapathi Bhat ganapathi.bhat@nxp.com @@@ -10640,7 -10568,6 +10640,7 @@@ M: hariprasad <hkelam@marvell.com L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/marvell/octeontx2/nic/ +F: include/linux/soc/marvell/octeontx2/
MARVELL OCTEONTX2 RVU ADMIN FUNCTION DRIVER M: Sunil Goutham sgoutham@marvell.com @@@ -10652,13 -10579,6 +10652,13 @@@ S: Supporte F: Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst F: drivers/net/ethernet/marvell/octeontx2/af/
+MARVELL PRESTERA ETHERNET SWITCH DRIVER +M: Vadym Kochan vkochan@marvell.com +M: Taras Chornyi tchornyi@marvell.com +S: Supported +W: https://github.com/Marvell-switching/switchdev-prestera +F: drivers/net/ethernet/marvell/prestera/ + MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER M: Nicolas Pitre nico@fluxnic.net S: Odd Fixes @@@ -10928,8 -10848,8 +10928,8 @@@ L: linux-media@vger.kernel.or S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/admin-guide/media/imx7.rst -F: Documentation/devicetree/bindings/media/imx7-csi.txt -F: Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt +F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml +F: Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml F: drivers/staging/media/imx/imx7-media-csi.c F: drivers/staging/media/imx/imx7-mipi-csis.c
@@@ -11188,12 -11108,6 +11188,12 @@@ S: Maintaine F: Documentation/devicetree/bindings/i2c/i2c-mt7621.txt F: drivers/i2c/busses/i2c-mt7621.c
+MEDIATEK MT7621 PHY PCI DRIVER +M: Sergio Paracuellos sergio.paracuellos@gmail.com +S: Maintained +F: Documentation/devicetree/bindings/phy/mediatek,mt7621-pci-phy.yaml +F: drivers/phy/ralink/phy-mt7621-pci.c + MEDIATEK NAND CONTROLLER DRIVER L: linux-mtd@lists.infradead.org S: Orphan @@@ -11269,10 -11183,9 +11269,10 @@@ F: Documentation/devicetree/bindings/in F: drivers/input/touchscreen/melfas_mip4.c
MELLANOX BLUEFIELD I2C DRIVER -M: Khalil Blaiech kblaiech@mellanox.com +M: Khalil Blaiech kblaiech@nvidia.com L: linux-i2c@vger.kernel.org S: Supported +F: Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml F: drivers/i2c/busses/i2c-mlxbf.c
MELLANOX ETHERNET DRIVER (mlx4_en) @@@ -11280,7 -11193,7 +11280,7 @@@ M: Tariq Toukan <tariqt@nvidia.com L: netdev@vger.kernel.org S: Supported W: http://www.mellanox.com -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ F: drivers/net/ethernet/mellanox/mlx4/en_*
MELLANOX ETHERNET DRIVER (mlx5e) @@@ -11288,7 -11201,7 +11288,7 @@@ M: Saeed Mahameed <saeedm@nvidia.com L: netdev@vger.kernel.org S: Supported W: http://www.mellanox.com -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ F: drivers/net/ethernet/mellanox/mlx5/core/en_*
MELLANOX ETHERNET INNOVA DRIVERS @@@ -11296,7 -11209,7 +11296,7 @@@ R: Boris Pismenny <borisp@nvidia.com L: netdev@vger.kernel.org S: Supported W: http://www.mellanox.com -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ F: drivers/net/ethernet/mellanox/mlx5/core/accel/* F: drivers/net/ethernet/mellanox/mlx5/core/en_accel/* F: drivers/net/ethernet/mellanox/mlx5/core/fpga/* @@@ -11308,7 -11221,7 +11308,7 @@@ M: Ido Schimmel <idosch@nvidia.com L: netdev@vger.kernel.org S: Supported W: http://www.mellanox.com -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ F: drivers/net/ethernet/mellanox/mlxsw/ F: tools/testing/selftests/drivers/net/mlxsw/
@@@ -11317,7 -11230,7 +11317,7 @@@ M: mlxsw@nvidia.co L: netdev@vger.kernel.org S: Supported W: http://www.mellanox.com -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ F: drivers/net/ethernet/mellanox/mlxfw/
MELLANOX HARDWARE PLATFORM SUPPORT @@@ -11336,7 -11249,7 +11336,7 @@@ L: netdev@vger.kernel.or L: linux-rdma@vger.kernel.org S: Supported W: http://www.mellanox.com -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ F: drivers/net/ethernet/mellanox/mlx4/ F: include/linux/mlx4/
@@@ -11357,7 -11270,7 +11357,7 @@@ L: netdev@vger.kernel.or L: linux-rdma@vger.kernel.org S: Supported W: http://www.mellanox.com -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ F: Documentation/networking/device_drivers/ethernet/mellanox/ F: drivers/net/ethernet/mellanox/mlx5/core/ F: include/linux/mlx5/ @@@ -11426,6 -11339,7 +11426,6 @@@ L: linux-pm@vger.kernel.or L: linux-tegra@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git S: Maintained -F: drivers/devfreq/tegra20-devfreq.c F: drivers/devfreq/tegra30-devfreq.c
MEMORY MANAGEMENT @@@ -11498,15 -11412,6 +11498,15 @@@ F: Documentation/devicetree/bindings/me F: drivers/media/cec/platform/meson/ao-cec-g12a.c F: drivers/media/cec/platform/meson/ao-cec.c
+MESON GE2D DRIVER FOR AMLOGIC SOCS +M: Neil Armstrong narmstrong@baylibre.com +L: linux-media@vger.kernel.org +L: linux-amlogic@lists.infradead.org +S: Supported +T: git git://linuxtv.org/media_tree.git +F: Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml +F: drivers/media/meson/ge2d/ + MESON NAND CONTROLLER DRIVER FOR AMLOGIC SOCS M: Liang Yang liang.yang@amlogic.com L: linux-mtd@lists.infradead.org @@@ -11623,7 -11528,7 +11623,7 @@@ M: Woojung Huh <woojung.huh@microchip.c M: Microchip Linux Driver Support UNGLinuxDriver@microchip.com L: netdev@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/net/dsa/ksz.txt +F: Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml F: drivers/net/dsa/microchip/* F: include/linux/platform_data/microchip-ksz.h F: net/dsa/tag_ksz.c @@@ -11745,43 -11650,17 +11745,43 @@@ F: drivers/scsi/smartpqi/smartpqi*.[ch F: include/linux/cciss*.h F: include/uapi/linux/cciss*.h
+MICROSOFT SURFACE GPE LID SUPPORT DRIVER +M: Maximilian Luz luzmaximilian@gmail.com +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/surface/surface_gpe.c + +MICROSOFT SURFACE HARDWARE PLATFORM SUPPORT +M: Hans de Goede hdegoede@redhat.com +M: Mark Gross mgross@linux.intel.com +M: Maximilian Luz luzmaximilian@gmail.com +L: platform-driver-x86@vger.kernel.org +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git +F: drivers/platform/surface/ + MICROSOFT SURFACE PRO 3 BUTTON DRIVER M: Chen Yu yu.c.chen@intel.com L: platform-driver-x86@vger.kernel.org S: Supported -F: drivers/platform/x86/surfacepro3_button.c +F: drivers/platform/surface/surfacepro3_button.c
MICROTEK X6 SCANNER M: Oliver Neukum oliver@neukum.org S: Maintained F: drivers/usb/image/microtek.*
+MIPI CCS, SMIA AND SMIA++ IMAGE SENSOR DRIVER +M: Sakari Ailus sakari.ailus@linux.intel.com +L: linux-media@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml +F: Documentation/driver-api/media/drivers/ccs/ +F: drivers/media/i2c/ccs-pll.c +F: drivers/media/i2c/ccs-pll.h +F: drivers/media/i2c/ccs/ +F: include/uapi/linux/smiapp.h + MIPS M: Thomas Bogendoerfer tsbogend@alpha.franken.de L: linux-mips@vger.kernel.org @@@ -11849,7 -11728,7 +11849,7 @@@ F: drivers/*/*/*loongson2 F: drivers/*/*loongson2*
MIPS/LOONGSON64 ARCHITECTURE -M: Huacai Chen chenhc@lemote.com +M: Huacai Chen chenhuacai@kernel.org M: Jiaxun Yang jiaxun.yang@flygoat.com L: linux-mips@vger.kernel.org S: Maintained @@@ -12052,7 -11931,7 +12052,7 @@@ M: Jacopo Mondi <jacopo@jmondi.org L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.txt +F: Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml F: drivers/media/i2c/mt9v111.c
MULTIFUNCTION DEVICES (MFD) @@@ -12271,7 -12150,7 +12271,7 @@@ M: Jakub Kicinski <kuba@kernel.org L: netdev@vger.kernel.org S: Maintained W: http://www.linuxfoundation.org/en/Net -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git F: Documentation/devicetree/bindings/net/ @@@ -12316,7 -12195,7 +12316,7 @@@ M: Jakub Kicinski <kuba@kernel.org L: netdev@vger.kernel.org S: Maintained W: http://www.linuxfoundation.org/en/Net -Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: https://patchwork.kernel.org/project/netdevbpf/list/ B: mailto:netdev@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git @@@ -12396,7 -12275,6 +12396,7 @@@ L: mptcp@lists.01.or S: Maintained W: https://github.com/multipath-tcp/mptcp_net-next/wiki B: https://github.com/multipath-tcp/mptcp_net-next/issues +F: Documentation/networking/mptcp-sysctl.rst F: include/net/mptcp.h F: include/uapi/linux/mptcp.h F: net/mptcp/ @@@ -12687,7 -12565,7 +12687,7 @@@ NXP FXAS21002C DRIVE M: Rui Miguel Silva rmfrfs@gmail.com L: linux-iio@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/iio/gyroscope/nxp,fxas21002c.txt +F: Documentation/devicetree/bindings/iio/gyroscope/nxp,fxas21002c.yaml F: drivers/iio/gyro/fxas21002c.h F: drivers/iio/gyro/fxas21002c_core.c F: drivers/iio/gyro/fxas21002c_i2c.c @@@ -12701,12 -12579,6 +12701,12 @@@ S: Maintaine F: Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml F: drivers/gpu/drm/imx/dcss/
+NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER +M: Jagan Teki jagan@amarulasolutions.com +S: Maintained +F: Documentation/devicetree/bindings/regulator/nxp,pf8x00-regulator.yaml +F: drivers/regulator/pf8x00-regulator.c + NXP PTN5150A CC LOGIC AND EXTCON DRIVER M: Krzysztof Kozlowski krzk@kernel.org L: linux-kernel@vger.kernel.org @@@ -13004,14 -12876,6 +13004,14 @@@ M: Harald Welte <laforge@gnumonks.org S: Maintained F: drivers/char/pcmcia/cm4040_cs.*
+OMNIVISION OV02A10 SENSOR DRIVER +M: Dongchun Zhu dongchun.zhu@mediatek.com +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml +F: drivers/media/i2c/ov02a10.c + OMNIVISION OV13858 SENSOR DRIVER M: Sakari Ailus sakari.ailus@linux.intel.com L: linux-media@vger.kernel.org @@@ -13024,7 -12888,7 +13024,7 @@@ M: Rui Miguel Silva <rmfrfs@gmail.com L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: Documentation/devicetree/bindings/media/i2c/ov2680.txt +F: Documentation/devicetree/bindings/media/i2c/ov2680.yaml F: drivers/media/i2c/ov2680.c
OMNIVISION OV2685 SENSOR DRIVER @@@ -13082,8 -12946,9 +13082,8 @@@ T: git git://linuxtv.org/media_tree.gi F: drivers/media/i2c/ov5695.c
OMNIVISION OV7670 SENSOR DRIVER -M: Jonathan Corbet corbet@lwn.net L: linux-media@vger.kernel.org -S: Maintained +S: Orphan T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/ov7670.txt F: drivers/media/i2c/ov7670.c @@@ -13093,7 -12958,7 +13093,7 @@@ M: Jacopo Mondi <jacopo@jmondi.org L: linux-media@vger.kernel.org S: Odd fixes T: git git://linuxtv.org/media_tree.git -F: Documentation/devicetree/bindings/media/i2c/ov772x.txt +F: Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml F: drivers/media/i2c/ov772x.c F: include/media/i2c/ov772x.h
@@@ -13129,14 -12994,6 +13129,14 @@@ T: git git://linuxtv.org/media_tree.gi F: Documentation/devicetree/bindings/media/i2c/ov9650.txt F: drivers/media/i2c/ov9650.c
+OMNIVISION OV9734 SENSOR DRIVER +M: Tianshu Qiu tian.shu.qiu@intel.com +R: Bingbu Cao bingbu.cao@intel.com +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: drivers/media/i2c/ov9734.c + ONENAND FLASH DRIVER M: Kyungmin Park kyungmin.park@samsung.com L: linux-mtd@lists.infradead.org @@@ -13339,13 -13196,11 +13339,13 @@@ M: Jesper Dangaard Brouer <hawk@kernel. M: Ilias Apalodimas ilias.apalodimas@linaro.org L: netdev@vger.kernel.org S: Supported +F: Documentation/networking/page_pool.rst F: include/net/page_pool.h +F: include/trace/events/page_pool.h F: net/core/page_pool.c
PANASONIC LAPTOP ACPI EXTRAS DRIVER -M: Harald Welte laforge@gnumonks.org +M: Kenneth Chan kenneth.t.chan@gmail.com L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/panasonic-laptop.c @@@ -13569,6 -13424,7 +13569,6 @@@ F: drivers/pci/controller/mobiveil/pcie
PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support) M: Thomas Petazzoni thomas.petazzoni@bootlin.com -M: Jason Cooper jason@lakedaemon.net L: linux-pci@vger.kernel.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained @@@ -13644,8 -13500,6 +13644,8 @@@ M: Kishon Vijay Abraham I <kishon@ti.co M: Lorenzo Pieralisi lorenzo.pieralisi@arm.com L: linux-pci@vger.kernel.org S: Supported +F: Documentation/PCI/endpoint/* +F: Documentation/misc-devices/pci-endpoint-test.rst T: git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/pci-endpoint.git F: drivers/misc/pci_endpoint_test.c F: drivers/pci/endpoint/ @@@ -14069,13 -13923,6 +14069,13 @@@ M: Logan Gunthorpe <logang@deltatee.com S: Maintained F: drivers/dma/plx_dma.c
+PM6764TR DRIVER +M: Charles Hsu hsu.yungteng@gmail.com +L: linux-hwmon@vger.kernel.org +S: Maintained +F: Documentation/hwmon/pm6764tr.rst +F: drivers/hwmon/pmbus/pm6764tr.c + PM-GRAPH UTILITY M: "Todd E Brandt" todd.e.brandt@linux.intel.com L: linux-pm@vger.kernel.org @@@ -14383,6 -14230,7 +14383,6 @@@ F: drivers/media/usb/pwc/ F: include/trace/events/pwc.h
PWM FAN DRIVER -M: Kamil Debski kamil@wypas.org M: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com L: linux-hwmon@vger.kernel.org S: Supported @@@ -14618,7 -14466,6 +14618,7 @@@ W: https://wireless.wiki.kernel.org/en/ F: drivers/net/wireless/ath/ath9k/
QUALCOMM CAMERA SUBSYSTEM DRIVER +M: Robert Foss robert.foss@linaro.org M: Todor Tomov todor.too@gmail.com L: linux-media@vger.kernel.org S: Maintained @@@ -14700,22 -14547,6 +14700,22 @@@ F: Documentation/devicetree/bindings/ma F: drivers/mailbox/qcom-ipcc.c F: include/dt-bindings/mailbox/qcom-ipcc.h
+QUALCOMM IPQ4019 USB PHY DRIVER +M: Robert Marko robert.marko@sartura.hr +M: Luka Perkov luka.perkov@sartura.hr +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/phy/qcom-usb-ipq4019-phy.yaml +F: drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c + +QUALCOMM IPQ4019 VQMMC REGULATOR DRIVER +M: Robert Marko robert.marko@sartura.hr +M: Luka Perkov luka.perkov@sartura.hr +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml +F: drivers/regulator/vqmmc-ipq4019-regulator.c + QUALCOMM RMNET DRIVER M: Subash Abhinov Kasiviswanathan subashab@codeaurora.org M: Sean Tranchetti stranche@codeaurora.org @@@ -15000,7 -14831,7 +15000,7 @@@ T: git git://git.kernel.org/pub/scm/lin F: drivers/net/wireless/realtek/rtlwifi/
REALTEK WIRELESS DRIVER (rtw88) -M: Yan-Hsuan Chuang yhchuang@realtek.com +M: Yan-Hsuan Chuang tony0620emma@gmail.com L: linux-wireless@vger.kernel.org S: Maintained F: drivers/net/wireless/realtek/rtw88/ @@@ -15071,6 -14902,7 +15071,6 @@@ RENESAS ETHERNET DRIVER R: Sergei Shtylyov sergei.shtylyov@gmail.com L: netdev@vger.kernel.org L: linux-renesas-soc@vger.kernel.org -F: Documentation/devicetree/bindings/net/renesas,*.txt F: Documentation/devicetree/bindings/net/renesas,*.yaml F: drivers/net/ethernet/renesas/ F: include/linux/sh_eth.h @@@ -15116,7 -14948,6 +15116,7 @@@ M: Philipp Zabel <p.zabel@pengutronix.d S: Maintained T: git git://git.pengutronix.de/git/pza/linux F: Documentation/devicetree/bindings/reset/ +F: Documentation/driver-api/reset.rst F: drivers/reset/ F: include/dt-bindings/reset/ F: include/linux/reset-controller.h @@@ -15201,13 -15032,10 +15201,13 @@@ ROCKCHIP ISP V1 DRIVE M: Helen Koike helen.koike@collabora.com M: Dafna Hirschfeld dafna.hirschfeld@collabora.com L: linux-media@vger.kernel.org +L: linux-rockchip@lists.infradead.org S: Maintained F: Documentation/admin-guide/media/rkisp1.rst +F: Documentation/devicetree/bindings/media/rockchip-isp1.yaml F: Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst -F: drivers/staging/media/rkisp1/ +F: drivers/media/platform/rockchip/rkisp1 +F: include/uapi/linux/rkisp1-config.h
ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER M: Jacob Chen jacob-chen@iotwrt.com @@@ -15431,6 -15259,7 +15431,6 @@@ F: drivers/iommu/s390-iommu. S390 IUCV NETWORK LAYER M: Julian Wiedmann jwi@linux.ibm.com M: Karsten Graul kgraul@linux.ibm.com -M: Ursula Braun ubraun@linux.ibm.com L: linux-s390@vger.kernel.org S: Supported W: http://www.ibm.com/developerworks/linux/linux390/ @@@ -15441,6 -15270,7 +15441,6 @@@ F: net/iucv S390 NETWORK DRIVERS M: Julian Wiedmann jwi@linux.ibm.com M: Karsten Graul kgraul@linux.ibm.com -M: Ursula Braun ubraun@linux.ibm.com L: linux-s390@vger.kernel.org S: Supported W: http://www.ibm.com/developerworks/linux/linux390/ @@@ -15542,6 -15372,7 +15542,6 @@@ F: security/safesetid
SAMSUNG AUDIO (ASoC) DRIVERS M: Krzysztof Kozlowski krzk@kernel.org -M: Sangbeom Kim sbkim73@samsung.com M: Sylwester Nawrocki s.nawrocki@samsung.com L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Supported @@@ -15569,14 -15400,6 +15569,14 @@@ L: linux-fbdev@vger.kernel.or S: Maintained F: drivers/video/fbdev/s3c-fb.c
+SAMSUNG INTERCONNECT DRIVERS +M: Sylwester Nawrocki s.nawrocki@samsung.com +M: Artur ��wigo�� a.swigon@samsung.com +L: linux-pm@vger.kernel.org +L: linux-samsung-soc@vger.kernel.org +S: Supported +F: drivers/interconnect/samsung/ + SAMSUNG LAPTOP DRIVER M: Corentin Chary corentin.chary@gmail.com L: platform-driver-x86@vger.kernel.org @@@ -15584,6 -15407,7 +15584,6 @@@ S: Maintaine F: drivers/platform/x86/samsung-laptop.c
SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS -M: Sangbeom Kim sbkim73@samsung.com M: Krzysztof Kozlowski krzk@kernel.org M: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com L: linux-kernel@vger.kernel.org @@@ -15617,12 -15441,14 +15617,12 @@@ F: Documentation/devicetree/bindings/ne F: drivers/nfc/s3fwrn5
SAMSUNG S5C73M3 CAMERA DRIVER -M: Kyungmin Park kyungmin.park@samsung.com M: Andrzej Hajda a.hajda@samsung.com L: linux-media@vger.kernel.org S: Supported F: drivers/media/i2c/s5c73m3/*
SAMSUNG S5K5BAF CAMERA DRIVER -M: Kyungmin Park kyungmin.park@samsung.com M: Andrzej Hajda a.hajda@samsung.com L: linux-media@vger.kernel.org S: Supported @@@ -15640,6 -15466,7 +15640,6 @@@ F: Documentation/devicetree/bindings/cr F: drivers/crypto/s5p-sss.c
SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS -M: Kyungmin Park kyungmin.park@samsung.com M: Sylwester Nawrocki s.nawrocki@samsung.com L: linux-media@vger.kernel.org S: Supported @@@ -15662,6 -15489,7 +15662,6 @@@ F: include/linux/clk/samsung. F: include/linux/platform_data/clk-s3c2410.h
SAMSUNG SPI DRIVERS -M: Kukjin Kim kgene@kernel.org M: Krzysztof Kozlowski krzk@kernel.org M: Andi Shyti andi@etezian.org L: linux-spi@vger.kernel.org @@@ -15687,6 -15515,7 +15687,6 @@@ T: git https://github.com/lmajewski/lin F: drivers/thermal/samsung/
SAMSUNG USB2 PHY DRIVER -M: Kamil Debski kamil@wypas.org M: Sylwester Nawrocki s.nawrocki@samsung.com L: linux-kernel@vger.kernel.org S: Supported @@@ -15780,6 -15609,15 +15780,15 @@@ F: Documentation/scsi/st.rs F: drivers/scsi/st.* F: drivers/scsi/st_*.h
+ SCSI TARGET CORE USER DRIVER + M: Bodo Stroesser bostroesser@gmail.com + L: linux-scsi@vger.kernel.org + L: target-devel@vger.kernel.org + S: Supported + F: Documentation/target/tcmu-design.rst + F: drivers/target/target_core_user.c + F: include/uapi/linux/target_core_user.h + SCSI TARGET SUBSYSTEM M: "Martin K. Petersen" martin.petersen@oracle.com L: linux-scsi@vger.kernel.org @@@ -15985,8 -15823,9 +15994,8 @@@ F: drivers/slimbus F: include/linux/slimbus.h
SFC NETWORK DRIVER -M: Solarflare linux maintainers linux-net-drivers@solarflare.com -M: Edward Cree ecree@solarflare.com -M: Martin Habets mhabets@solarflare.com +M: Edward Cree ecree.xilinx@gmail.com +M: Martin Habets habetsm.xilinx@gmail.com L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/sfc/ @@@ -16003,18 -15842,18 +16012,18 @@@ F: include/linux/sfp. K: phylink.h|struct\s+phylink|.phylink|>phylink_|phylink_(autoneg|clear|connect|create|destroy|disconnect|ethtool|helper|mac|mii|of|set|start|stop|test|validate)
SGI GRU DRIVER -M: Dimitri Sivanich sivanich@sgi.com +M: Dimitri Sivanich dimitri.sivanich@hpe.com S: Maintained F: drivers/misc/sgi-gru/
SGI XP/XPC/XPNET DRIVER -M: Cliff Whickman cpw@sgi.com M: Robin Holt robinmholt@gmail.com +M: Steve Wahl steve.wahl@hpe.com +R: Mike Travis mike.travis@hpe.com S: Maintained F: drivers/misc/sgi-xp/
SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS -M: Ursula Braun ubraun@linux.ibm.com M: Karsten Graul kgraul@linux.ibm.com L: linux-s390@vger.kernel.org S: Supported @@@ -16295,6 -16134,16 +16304,6 @@@ S: Maintaine F: drivers/firmware/smccc/ F: include/linux/arm-smccc.h
-SMIA AND SMIA++ IMAGE SENSOR DRIVER -M: Sakari Ailus sakari.ailus@linux.intel.com -L: linux-media@vger.kernel.org -S: Maintained -F: Documentation/devicetree/bindings/media/i2c/nokia,smia.txt -F: drivers/media/i2c/smiapp-pll.c -F: drivers/media/i2c/smiapp-pll.h -F: drivers/media/i2c/smiapp/ -F: include/uapi/linux/smiapp.h - SMM665 HARDWARE MONITOR DRIVER M: Guenter Roeck linux@roeck-us.net L: linux-hwmon@vger.kernel.org @@@ -16457,7 -16306,7 +16466,7 @@@ M: Ricardo Ribalda <ribalda@kernel.org L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: Documentation/devicetree/bindings/media/i2c/sony,imx214.txt +F: Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml F: drivers/media/i2c/imx214.c
SONY IMX219 SENSOR DRIVER @@@ -16693,10 -16542,8 +16702,10 @@@ F: Documentation/networking/device_driv F: drivers/net/ethernet/toshiba/spider_net*
SPMI SUBSYSTEM -R: Stephen Boyd sboyd@kernel.org -L: linux-arm-msm@vger.kernel.org +M: Stephen Boyd sboyd@kernel.org +L: linux-kernel@vger.kernel.org +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sboyd/spmi.git F: Documentation/devicetree/bindings/spmi/ F: drivers/spmi/ F: include/dt-bindings/spmi/spmi.h @@@ -17556,12 -17403,6 +17565,12 @@@ W: http://thinkwiki.org/wiki/Ibm-acp T: git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git F: drivers/platform/x86/thinkpad_acpi.c
+THUNDERBOLT DMA TRAFFIC TEST DRIVER +M: Isaac Hazan isaac.hazan@intel.com +L: linux-usb@vger.kernel.org +S: Maintained +F: drivers/thunderbolt/dma_test.c + THUNDERBOLT DRIVER M: Andreas Noever andreas.noever@gmail.com M: Michael Jamet michael.jamet@intel.com @@@ -18274,7 -18115,7 +18283,7 @@@ M: Yu Chen <chenyu56@huawei.com M: Binghui Wang wangbinghui@hisilicon.com L: linux-usb@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt +F: Documentation/devicetree/bindings/phy/hisilicon,hi3660-usb3.yaml F: drivers/phy/hisilicon/phy-hi3660-usb3.c
USB ISP116X DRIVER @@@ -18359,14 -18200,6 +18368,14 @@@ L: linux-usb@vger.kernel.or S: Supported F: drivers/usb/class/usblp.c
+USB RAW GADGET DRIVER +R: Andrey Konovalov andreyknvl@gmail.com +L: linux-usb@vger.kernel.org +S: Maintained +F: Documentation/usb/raw-gadget.rst +F: drivers/usb/gadget/legacy/raw_gadget.c +F: include/uapi/linux/usb/raw_gadget.h + USB QMI WWAN NETWORK DRIVER M: Bj��rn Mork bjorn@mork.no L: netdev@vger.kernel.org @@@ -18561,12 -18394,6 +18570,12 @@@ F: include/uapi/linux/uuid. F: lib/test_uuid.c F: lib/uuid.c
+UV SYSFS DRIVER +M: Justin Ernst justin.ernst@hpe.com +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/uv_sysfs.c + UVESAFB DRIVER M: Michal Januszewski spock@gentoo.org L: linux-fbdev@vger.kernel.org @@@ -19089,6 -18916,18 +19098,6 @@@ S: Supporte W: https://wireless.wiki.kernel.org/en/users/Drivers/wil6210 F: drivers/net/wireless/ath/wil6210/
-WIMAX STACK -M: Inaky Perez-Gonzalez inaky.perez-gonzalez@intel.com -M: linux-wimax@intel.com -L: wimax@linuxwimax.org (subscribers-only) -S: Supported -W: http://linuxwimax.org -F: Documentation/admin-guide/wimax/wimax.rst -F: include/linux/wimax/debug.h -F: include/net/wimax.h -F: include/uapi/linux/wimax.h -F: net/wimax/ - WINBOND CIR DRIVER M: David H��rdeman david@hardeman.nu S: Maintained @@@ -19186,18 -19025,12 +19195,18 @@@ L: linux-kernel@vger.kernel.or S: Maintained N: axp[128]
-X.25 NETWORK LAYER -M: Andrew Hendry andrew.hendry@gmail.com +X.25 STACK +M: Martin Schiller ms@dev.tdt.de L: linux-x25@vger.kernel.org -S: Odd Fixes +S: Maintained +F: Documentation/networking/lapb-module.rst F: Documentation/networking/x25* +F: drivers/net/wan/hdlc_x25.c +F: drivers/net/wan/lapbether.c +F: include/*/lapb.h F: include/net/x25* +F: include/uapi/linux/x25.h +F: net/lapb/ F: net/x25/
X86 ARCHITECTURE (32-BIT AND 64-BIT) @@@ -19261,7 -19094,6 +19270,7 @@@ F: arch/x86/platfor
X86 PLATFORM UV HPE SUPERDOME FLEX M: Steve Wahl steve.wahl@hpe.com +R: Mike Travis mike.travis@hpe.com R: Dimitri Sivanich dimitri.sivanich@hpe.com R: Russ Anderson russ.anderson@hpe.com S: Supported @@@ -19312,17 -19144,12 +19321,17 @@@ L: netdev@vger.kernel.or L: bpf@vger.kernel.org S: Supported F: include/net/xdp.h +F: include/net/xdp_priv.h F: include/trace/events/xdp.h F: kernel/bpf/cpumap.c F: kernel/bpf/devmap.c F: net/core/xdp.c -N: xdp -K: xdp +F: samples/bpf/xdp* +F: tools/testing/selftests/bpf/*xdp* +F: tools/testing/selftests/bpf/*/*xdp* +F: drivers/net/ethernet/*/*/*/*/*xdp* +F: drivers/net/ethernet/*/*/*xdp* +K: (?:\b|_)xdp(?:\b|_)
XDP SOCKETS (AF_XDP) M: Bj��rn T��pel bjorn.topel@intel.com @@@ -19331,12 -19158,9 +19340,12 @@@ R: Jonathan Lemon <jonathan.lemon@gmail L: netdev@vger.kernel.org L: bpf@vger.kernel.org S: Maintained +F: Documentation/networking/af_xdp.rst F: include/net/xdp_sock* F: include/net/xsk_buff_pool.h F: include/uapi/linux/if_xdp.h +F: include/uapi/linux/xdp_diag.h +F: include/net/netns/xdp.h F: net/xdp/ F: samples/bpf/xdpsock* F: tools/lib/bpf/xsk* @@@ -19604,13 -19428,6 +19613,13 @@@ T: git git://git.kernel.org/pub/scm/lin F: Documentation/filesystems/zonefs.rst F: fs/zonefs/
+ZPOOL COMPRESSED PAGE STORAGE API +M: Dan Streetman ddstreet@ieee.org +L: linux-mm@kvack.org +S: Maintained +F: include/linux/zpool.h +F: mm/zpool.c + ZR36067 VIDEO FOR LINUX DRIVER M: Corentin Labbe clabbe@baylibre.com L: mjpeg-users@lists.sourceforge.net @@@ -19621,6 -19438,13 +19630,6 @@@ Q: https://patchwork.linuxtv.org/projec F: Documentation/driver-api/media/drivers/zoran.rst F: drivers/staging/media/zoran/
-ZPOOL COMPRESSED PAGE STORAGE API -M: Dan Streetman ddstreet@ieee.org -L: linux-mm@kvack.org -S: Maintained -F: include/linux/zpool.h -F: mm/zpool.c - ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER M: Minchan Kim minchan@kernel.org M: Nitin Gupta ngupta@vflare.org diff --combined block/blk-mq.c index 14a44699e9b6,1b25ec2fe9be..b09ce00cc6af --- a/block/blk-mq.c +++ b/block/blk-mq.c @@@ -95,7 -95,7 +95,7 @@@ static void blk_mq_hctx_clear_pending(s }
struct mq_inflight { - struct hd_struct *part; + struct block_device *part; unsigned int inflight[2]; };
@@@ -105,15 -105,13 +105,15 @@@ static bool blk_mq_check_inflight(struc { struct mq_inflight *mi = priv;
- if (rq->part == mi->part && blk_mq_rq_state(rq) == MQ_RQ_IN_FLIGHT) + if ((!mi->part->bd_partno || rq->part == mi->part) && + blk_mq_rq_state(rq) == MQ_RQ_IN_FLIGHT) mi->inflight[rq_data_dir(rq)]++;
return true; }
-unsigned int blk_mq_in_flight(struct request_queue *q, struct hd_struct *part) +unsigned int blk_mq_in_flight(struct request_queue *q, + struct block_device *part) { struct mq_inflight mi = { .part = part };
@@@ -122,8 -120,8 +122,8 @@@ return mi.inflight[0] + mi.inflight[1]; }
-void blk_mq_in_flight_rw(struct request_queue *q, struct hd_struct *part, - unsigned int inflight[2]) +void blk_mq_in_flight_rw(struct request_queue *q, struct block_device *part, + unsigned int inflight[2]) { struct mq_inflight mi = { .part = part };
@@@ -673,7 -671,9 +673,7 @@@ bool blk_mq_complete_request_remote(str return false;
if (blk_mq_complete_need_ipi(rq)) { - rq->csd.func = __blk_mq_complete_request_remote; - rq->csd.info = rq; - rq->csd.flags = 0; + INIT_CSD(&rq->csd, __blk_mq_complete_request_remote, rq); smp_call_function_single_async(rq->mq_ctx->cpu, &rq->csd); } else { if (rq->q->nr_hw_queues > 1) @@@ -731,7 -731,7 +731,7 @@@ void blk_mq_start_request(struct reques { struct request_queue *q = rq->q;
- trace_block_rq_issue(q, rq); + trace_block_rq_issue(rq);
if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) { rq->io_start_time_ns = ktime_get_ns(); @@@ -758,7 -758,7 +758,7 @@@ static void __blk_mq_requeue_request(st
blk_mq_put_driver_tag(rq);
- trace_block_rq_requeue(q, rq); + trace_block_rq_requeue(rq); rq_qos_requeue(q, rq);
if (blk_mq_request_started(rq)) { @@@ -1404,7 -1404,7 +1404,7 @@@ bool blk_mq_dispatch_rq_list(struct blk break; default: errors++; - blk_mq_end_request(rq, BLK_STS_IOERR); + blk_mq_end_request(rq, ret); } } while (!list_empty(list)); out: @@@ -1592,7 -1592,7 +1592,7 @@@ select_cpu * __blk_mq_delay_run_hw_queue - Run (or schedule to run) a hardware queue. * @hctx: Pointer to the hardware queue to run. * @async: If we want to run the queue asynchronously. - * @msecs: Microseconds of delay to wait before running the queue. + * @msecs: Milliseconds of delay to wait before running the queue. * * If !@async, try to run the queue now. Else, run the queue asynchronously and * with a delay of @msecs. @@@ -1621,7 -1621,7 +1621,7 @@@ static void __blk_mq_delay_run_hw_queue /** * blk_mq_delay_run_hw_queue - Run a hardware queue asynchronously. * @hctx: Pointer to the hardware queue to run. - * @msecs: Microseconds of delay to wait before running the queue. + * @msecs: Milliseconds of delay to wait before running the queue. * * Run a hardware queue asynchronously with a delay of @msecs. */ @@@ -1685,7 -1685,7 +1685,7 @@@ EXPORT_SYMBOL(blk_mq_run_hw_queues) /** * blk_mq_delay_run_hw_queues - Run all hardware queues asynchronously. * @q: Pointer to the request queue to run. - * @msecs: Microseconds of delay to wait before running the queues. + * @msecs: Milliseconds of delay to wait before running the queues. */ void blk_mq_delay_run_hw_queues(struct request_queue *q, unsigned long msecs) { @@@ -1819,7 -1819,7 +1819,7 @@@ static inline void __blk_mq_insert_req_
lockdep_assert_held(&ctx->lock);
- trace_block_rq_insert(hctx->queue, rq); + trace_block_rq_insert(rq);
if (at_head) list_add(&rq->queuelist, &ctx->rq_lists[type]); @@@ -1876,7 -1876,7 +1876,7 @@@ void blk_mq_insert_requests(struct blk_ */ list_for_each_entry(rq, list, queuelist) { BUG_ON(rq->mq_ctx != ctx); - trace_block_rq_insert(hctx->queue, rq); + trace_block_rq_insert(rq); }
spin_lock(&ctx->lock); @@@ -2157,7 -2157,6 +2157,7 @@@ blk_qc_t blk_mq_submit_bio(struct bio * unsigned int nr_segs; blk_qc_t cookie; blk_status_t ret; + bool hipri;
blk_queue_bounce(q, &bio); __blk_queue_split(&bio, &nr_segs); @@@ -2174,8 -2173,6 +2174,8 @@@
rq_qos_throttle(q, bio);
+ hipri = bio->bi_opf & REQ_HIPRI; + data.cmd_flags = bio->bi_opf; rq = __blk_mq_alloc_request(&data); if (unlikely(!rq)) { @@@ -2185,7 -2182,7 +2185,7 @@@ goto queue_exit; }
- trace_block_getrq(q, bio, bio->bi_opf); + trace_block_getrq(bio);
rq_qos_track(q, rq, bio);
@@@ -2268,8 -2265,6 +2268,8 @@@ blk_mq_sched_insert_request(rq, false, true, true); }
+ if (!hipri) + return BLK_QC_T_NONE; return cookie; queue_exit: blk_queue_exit(q); @@@ -3380,12 -3375,6 +3380,12 @@@ static int blk_mq_realloc_tag_set_tags( return 0; }
+static int blk_mq_alloc_tag_set_tags(struct blk_mq_tag_set *set, + int new_nr_hw_queues) +{ + return blk_mq_realloc_tag_set_tags(set, 0, new_nr_hw_queues); +} + /* * Alloc a tag set to be associated with one or more request queues. * May fail with EINVAL for various error conditions. May adjust the @@@ -3439,7 -3428,7 +3439,7 @@@ int blk_mq_alloc_tag_set(struct blk_mq_ if (set->nr_maps == 1 && set->nr_hw_queues > nr_cpu_ids) set->nr_hw_queues = nr_cpu_ids;
- if (blk_mq_realloc_tag_set_tags(set, 0, set->nr_hw_queues) < 0) + if (blk_mq_alloc_tag_set_tags(set, set->nr_hw_queues) < 0) return -ENOMEM;
ret = -ENOMEM; @@@ -3874,10 -3863,9 +3874,10 @@@ int blk_poll(struct request_queue *q, b * the state. Like for the other success return cases, the * caller is responsible for checking if the IO completed. If * the IO isn't complete, we'll get called again and will go - * straight to the busy poll loop. + * straight to the busy poll loop. If specified not to spin, + * we also should not sleep. */ - if (blk_mq_poll_hybrid(q, hctx, cookie)) + if (spin && blk_mq_poll_hybrid(q, hctx, cookie)) return 1;
hctx->poll_considered++; diff --combined drivers/infiniband/ulp/srpt/ib_srpt.c index 53a8becac827,8377113c85ba..a17c56cd8312 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@@ -622,11 -622,10 +622,11 @@@ static int srpt_refresh_port(struct srp /** * srpt_unregister_mad_agent - unregister MAD callback functions * @sdev: SRPT HCA pointer. + * @port_cnt: number of ports with registered MAD * * Note: It is safe to call this function more than once for the same device. */ -static void srpt_unregister_mad_agent(struct srpt_device *sdev) +static void srpt_unregister_mad_agent(struct srpt_device *sdev, int port_cnt) { struct ib_port_modify port_modify = { .clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP, @@@ -634,7 -633,7 +634,7 @@@ struct srpt_port *sport; int i;
- for (i = 1; i <= sdev->device->phys_port_cnt; i++) { + for (i = 1; i <= port_cnt; i++) { sport = &sdev->port[i - 1]; WARN_ON(sport->port != i); if (sport->mad_agent) { @@@ -2085,7 -2084,7 +2085,7 @@@ static void srpt_release_channel_work(s se_sess = ch->sess; BUG_ON(!se_sess);
- target_sess_cmd_list_set_waiting(se_sess); + target_stop_session(se_sess); target_wait_for_sess_cmds(se_sess);
target_remove_session(se_sess); @@@ -3186,8 -3185,7 +3186,8 @@@ static int srpt_add_one(struct ib_devic if (ret) { pr_err("MAD registration failed for %s-%d.\n", dev_name(&sdev->device->dev), i); - goto err_event; + i--; + goto err_port; } }
@@@ -3199,8 -3197,7 +3199,8 @@@ pr_debug("added %s.\n", dev_name(&device->dev)); return 0;
-err_event: +err_port: + srpt_unregister_mad_agent(sdev, i); ib_unregister_event_handler(&sdev->event_handler); err_cm: if (sdev->cm_id) @@@ -3224,7 -3221,7 +3224,7 @@@ static void srpt_remove_one(struct ib_d struct srpt_device *sdev = client_data; int i;
- srpt_unregister_mad_agent(sdev); + srpt_unregister_mad_agent(sdev, sdev->device->phys_port_cnt);
ib_unregister_event_handler(&sdev->event_handler);
diff --combined drivers/message/fusion/mptscsih.c index e7f0d4ae0f96,f441f433ad4d..ce2e5b21978e --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@@ -52,7 -52,7 +52,7 @@@ #include <linux/kdev_t.h> #include <linux/blkdev.h> #include <linux/delay.h> /* for mdelay */ - #include <linux/interrupt.h> /* needed for in_interrupt() proto */ + #include <linux/interrupt.h> #include <linux/reboot.h> /* notifier code */ #include <linux/workqueue.h>
@@@ -1176,10 -1176,8 +1176,10 @@@ mptscsih_remove(struct pci_dev *pdev MPT_SCSI_HOST *hd; int sz1;
- if((hd = shost_priv(host)) == NULL) - return; + if (host == NULL) + hd = NULL; + else + hd = shost_priv(host);
mptscsih_shutdown(pdev);
@@@ -1195,15 -1193,14 +1195,15 @@@ "Free'd ScsiLookup (%d) memory\n", ioc->name, sz1));
- kfree(hd->info_kbuf); + if (hd) + kfree(hd->info_kbuf);
/* NULL the Scsi_Host pointer */ ioc->sh = NULL;
- scsi_host_put(host); - + if (host) + scsi_host_put(host); mpt_detach(pdev);
} diff --combined drivers/s390/scsi/zfcp_def.h index 5069b555c6c1,f656d74a5f94..26c89c232ef2 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@@ -70,6 -70,7 +70,6 @@@ #define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 -#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040 #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 #define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400 @@@ -200,6 -201,7 +200,7 @@@ struct zfcp_adapter struct zfcp_fc_events events; unsigned long next_port_scan; struct zfcp_diag_adapter *diagnostics; + struct work_struct version_change_lost_work; };
struct zfcp_port { diff --combined drivers/s390/scsi/zfcp_ext.h index fdac6350c579,8b50f580584c..58879213f225 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@@ -20,8 -20,6 +20,6 @@@ extern struct zfcp_port *zfcp_get_port_ extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, u32); - extern void zfcp_sg_free_table(struct scatterlist *, int); - extern int zfcp_sg_setup_table(struct scatterlist *, int); extern void zfcp_adapter_release(struct kref *); extern void zfcp_adapter_unregister(struct zfcp_adapter *);
@@@ -49,6 -47,7 +47,6 @@@ extern void zfcp_dbf_hba_fsf_fces(char u32 fc_security_new); extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); -extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); diff --combined drivers/s390/scsi/zfcp_fsf.c index 37d450f46952,7593a9667b3e..485028324eae --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@@ -242,6 -242,19 +242,19 @@@ static void zfcp_fsf_status_read_link_d } }
+ static void + zfcp_fsf_status_read_version_change(struct zfcp_adapter *adapter, + struct fsf_status_read_buffer *sr_buf) + { + if (sr_buf->status_subtype == FSF_STATUS_READ_SUB_LIC_CHANGE) { + u32 version = sr_buf->payload.version_change.current_version; + + WRITE_ONCE(adapter->fsf_lic_version, version); + snprintf(fc_host_firmware_version(adapter->scsi_host), + FC_VERSION_STRING_SIZE, "%#08x", version); + } + } + static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; @@@ -296,10 -309,16 +309,16 @@@ case FSF_STATUS_READ_NOTIFICATION_LOST: if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS) zfcp_fc_conditional_port_scan(adapter); + if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_VERSION_CHANGE) + queue_work(adapter->work_queue, + &adapter->version_change_lost_work); break; case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: adapter->adapter_features = sr_buf->payload.word[0]; break; + case FSF_STATUS_READ_VERSION_CHANGE: + zfcp_fsf_status_read_version_change(adapter, sr_buf); + break; }
mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data); @@@ -2359,7 -2378,8 +2378,7 @@@ static void zfcp_fsf_req_trace(struct z } }
- blk_add_driver_data(scsi->request->q, scsi->request, &blktrc, - sizeof(blktrc)); + blk_add_driver_data(scsi->request, &blktrc, sizeof(blktrc)); }
/** diff --combined drivers/scsi/be2iscsi/be_main.c index 5c3513a4b450,50e464224d47..90fcddb76f46 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@@ -164,7 -164,7 +164,7 @@@ DEVICE_ATTR(beiscsi_active_session_coun beiscsi_active_session_disp, NULL); DEVICE_ATTR(beiscsi_free_session_count, S_IRUGO, beiscsi_free_session_disp, NULL); - struct device_attribute *beiscsi_attrs[] = { + static struct device_attribute *beiscsi_attrs[] = { &dev_attr_beiscsi_log_enable, &dev_attr_beiscsi_drvr_ver, &dev_attr_beiscsi_adapter_family, @@@ -3020,6 -3020,7 +3020,6 @@@ static int beiscsi_create_eqs(struct be goto create_eq_error; }
- mem->dma = paddr; mem->va = eq_vaddress; ret = be_fill_queue(eq, phba->params.num_eq_entries, sizeof(struct be_eq_entry), eq_vaddress); @@@ -3029,7 -3030,6 +3029,7 @@@ goto create_eq_error; }
+ mem->dma = paddr; ret = beiscsi_cmd_eq_create(&phba->ctrl, eq, BEISCSI_EQ_DELAY_DEF); if (ret) { @@@ -3086,6 -3086,7 +3086,6 @@@ static int beiscsi_create_cqs(struct be goto create_cq_error; }
- mem->dma = paddr; ret = be_fill_queue(cq, phba->params.num_cq_entries, sizeof(struct sol_cqe), cq_vaddress); if (ret) { @@@ -3095,7 -3096,6 +3095,7 @@@ goto create_cq_error; }
+ mem->dma = paddr; ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false, false, 0); if (ret) { diff --combined drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 08fb7d5d08b3,52bd0db643b0..16bb6d2f98de --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@@ -16,8 -16,6 +16,8 @@@
#include "bnx2fc.h"
+#include <linux/ethtool.h> + static struct list_head adapter_list; static struct list_head if_list; static u32 adapter_count; @@@ -2088,7 -2086,7 +2088,7 @@@ static int __bnx2fc_disable(struct fcoe { struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr);
- if (interface->enabled == true) { + if (interface->enabled) { if (!ctlr->lp) { pr_err(PFX "__bnx2fc_disable: lport not found\n"); return -ENODEV; @@@ -2186,7 -2184,7 +2186,7 @@@ static int __bnx2fc_enable(struct fcoe_ struct cnic_fc_npiv_tbl *npiv_tbl; struct fc_lport *lport;
- if (interface->enabled == false) { + if (!interface->enabled) { if (!ctlr->lp) { pr_err(PFX "__bnx2fc_enable: lport not found\n"); return -ENODEV; @@@ -2277,7 -2275,7 +2277,7 @@@ static int bnx2fc_ctlr_enabled(struct f case FCOE_CTLR_UNUSED: default: return -ENOTSUPP; - }; + } }
enum bnx2fc_create_link_state { diff --combined drivers/scsi/device_handler/scsi_dh_alua.c index 308bda2e9c00,92b592e9ebcb..ea436a14087f --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@@ -408,12 -408,20 +408,20 @@@ static char print_alua_state(unsigned c static int alua_check_sense(struct scsi_device *sdev, struct scsi_sense_hdr *sense_hdr) { + struct alua_dh_data *h = sdev->handler_data; + struct alua_port_group *pg; + switch (sense_hdr->sense_key) { case NOT_READY: if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a) { /* * LUN Not Accessible - ALUA state transition */ + rcu_read_lock(); + pg = rcu_dereference(h->pg); + if (pg) + pg->state = SCSI_ACCESS_STATE_TRANSITIONING; + rcu_read_unlock(); alua_check(sdev, false); return NEEDS_RETRY; } @@@ -658,8 -666,8 +666,8 @@@ static int alua_rtpg(struct scsi_devic rcu_read_lock(); list_for_each_entry_rcu(h, &tmp_pg->dh_list, node) { - /* h->sdev should always be valid */ - BUG_ON(!h->sdev); + if (!h->sdev) + continue; h->sdev->access_state = desc[0]; } rcu_read_unlock(); @@@ -705,8 -713,7 +713,8 @@@ pg->expiry = 0; rcu_read_lock(); list_for_each_entry_rcu(h, &pg->dh_list, node) { - BUG_ON(!h->sdev); + if (!h->sdev) + continue; h->sdev->access_state = (pg->state & SCSI_ACCESS_STATE_MASK); if (pg->pref) @@@ -1092,7 -1099,7 +1100,7 @@@ static blk_status_t alua_prep_fn(struc case SCSI_ACCESS_STATE_LBA: return BLK_STS_OK; case SCSI_ACCESS_STATE_TRANSITIONING: - return BLK_STS_RESOURCE; + return BLK_STS_AGAIN; default: req->rq_flags |= RQF_QUIET; return BLK_STS_IOERR; @@@ -1148,6 -1155,7 +1156,6 @@@ static void alua_bus_detach(struct scsi spin_lock(&h->pg_lock); pg = rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock)); rcu_assign_pointer(h->pg, NULL); - h->sdev = NULL; spin_unlock(&h->pg_lock); if (pg) { spin_lock_irq(&pg->lock); @@@ -1156,7 -1164,6 +1164,7 @@@ kref_put(&pg->kref, release_port_group); } sdev->handler_data = NULL; + synchronize_rcu(); kfree(h); }
diff --combined drivers/scsi/hisi_sas/hisi_sas_main.c index 274ccf18ce2d,71ecfba996e4..b6d4419c32f2 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@@ -445,19 -445,13 +445,19 @@@ static int hisi_sas_task_prep(struct sa } }
- if (scmd) { + if (scmd && hisi_hba->shost->nr_hw_queues) { unsigned int dq_index; u32 blk_tag;
blk_tag = blk_mq_unique_tag(scmd->request); dq_index = blk_mq_unique_tag_to_hwq(blk_tag); *dq_pointer = dq = &hisi_hba->dq[dq_index]; + } else if (hisi_hba->shost->nr_hw_queues) { + struct Scsi_Host *shost = hisi_hba->shost; + struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; + int queue = qmap->mq_map[raw_smp_processor_id()]; + + *dq_pointer = dq = &hisi_hba->dq[queue]; } else { *dq_pointer = dq = sas_dev->dq; } @@@ -591,13 -585,7 +591,7 @@@ static int hisi_sas_task_exec(struct sa dev = hisi_hba->dev;
if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) { - /* - * For IOs from upper layer, it may already disable preempt - * in the IO path, if disable preempt again in down(), - * function schedule() will report schedule_bug(), so check - * preemptible() before goto down(). - */ - if (!preemptible()) + if (!gfpflags_allow_blocking(gfp_flags)) return -EINVAL;
down(&hisi_hba->sem); @@@ -2696,1382 -2684,42 +2690,42 @@@ int hisi_sas_probe(struct platform_devi err_out_register_ha: scsi_remove_host(shost); err_out_ha: - hisi_sas_debugfs_exit(hisi_hba); hisi_sas_free(hisi_hba); scsi_host_put(shost); return rc; } EXPORT_SYMBOL_GPL(hisi_sas_probe);
- struct dentry *hisi_sas_debugfs_dir; - - static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba) - { - int queue_entry_size = hisi_hba->hw->complete_hdr_size; - int dump_index = hisi_hba->debugfs_dump_index; - int i; - - for (i = 0; i < hisi_hba->queue_count; i++) - memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr, - hisi_hba->complete_hdr[i], - HISI_SAS_QUEUE_SLOTS * queue_entry_size); - } - - static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba) - { - int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr); - int dump_index = hisi_hba->debugfs_dump_index; - int i; - - for (i = 0; i < hisi_hba->queue_count; i++) { - struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr; - int j; - - debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr; - cmd_hdr = hisi_hba->cmd_hdr[i]; - - for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++) - memcpy(&debugfs_cmd_hdr[j], &cmd_hdr[j], - queue_entry_size); - } - } - - static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) - { - int dump_index = hisi_hba->debugfs_dump_index; - const struct hisi_sas_debugfs_reg *port = - hisi_hba->hw->debugfs_reg_port; - int i, phy_cnt; - u32 offset; - u32 *databuf; - - for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { - databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data; - for (i = 0; i < port->count; i++, databuf++) { - offset = port->base_off + 4 * i; - *databuf = port->read_port_reg(hisi_hba, phy_cnt, - offset); - } - } - } - - static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) - { - int dump_index = hisi_hba->debugfs_dump_index; - u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const struct hisi_sas_debugfs_reg *global = - hw->debugfs_reg_array[DEBUGFS_GLOBAL]; - int i; - - for (i = 0; i < global->count; i++, databuf++) - *databuf = global->read_global_reg(hisi_hba, 4 * i); - } - - static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) - { - int dump_index = hisi_hba->debugfs_dump_index; - u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const struct hisi_sas_debugfs_reg *axi = - hw->debugfs_reg_array[DEBUGFS_AXI]; - int i; - - for (i = 0; i < axi->count; i++, databuf++) - *databuf = axi->read_global_reg(hisi_hba, - 4 * i + axi->base_off); - } - - static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) - { - int dump_index = hisi_hba->debugfs_dump_index; - u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const struct hisi_sas_debugfs_reg *ras = - hw->debugfs_reg_array[DEBUGFS_RAS]; - int i; - - for (i = 0; i < ras->count; i++, databuf++) - *databuf = ras->read_global_reg(hisi_hba, - 4 * i + ras->base_off); - } - - static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) - { - int dump_index = hisi_hba->debugfs_dump_index; - void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache; - void *databuf = hisi_hba->debugfs_itct[dump_index].itct; - struct hisi_sas_itct *itct; - int i; - - hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_ITCT_CACHE, - cachebuf); - - itct = hisi_hba->itct; - - for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { - memcpy(databuf, itct, sizeof(struct hisi_sas_itct)); - databuf += sizeof(struct hisi_sas_itct); - } - } - - static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) - { - int dump_index = hisi_hba->debugfs_dump_index; - int max_command_entries = HISI_SAS_MAX_COMMANDS; - void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache; - void *databuf = hisi_hba->debugfs_iost[dump_index].iost; - struct hisi_sas_iost *iost; - int i; - - hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_IOST_CACHE, - cachebuf); - - iost = hisi_hba->iost; - - for (i = 0; i < max_command_entries; i++, iost++) { - memcpy(databuf, iost, sizeof(struct hisi_sas_iost)); - databuf += sizeof(struct hisi_sas_iost); - } - } - - static const char * - hisi_sas_debugfs_to_reg_name(int off, int base_off, - const struct hisi_sas_debugfs_reg_lu *lu) - { - for (; lu->name; lu++) { - if (off == lu->off - base_off) - return lu->name; - } - - return NULL; - } - - static void hisi_sas_debugfs_print_reg(u32 *regs_val, const void *ptr, - struct seq_file *s) - { - const struct hisi_sas_debugfs_reg *reg = ptr; - int i; - - for (i = 0; i < reg->count; i++) { - int off = i * 4; - const char *name; - - name = hisi_sas_debugfs_to_reg_name(off, reg->base_off, - reg->lu); - - if (name) - seq_printf(s, "0x%08x 0x%08x %s\n", off, - regs_val[i], name); - else - seq_printf(s, "0x%08x 0x%08x\n", off, - regs_val[i]); - } - } - - static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p) - { - struct hisi_sas_debugfs_regs *global = s->private; - struct hisi_hba *hisi_hba = global->hisi_hba; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL]; - - hisi_sas_debugfs_print_reg(global->data, - reg_global, s); - - return 0; - } - - static int hisi_sas_debugfs_global_open(struct inode *inode, struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_global_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_global_fops = { - .open = hisi_sas_debugfs_global_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p) - { - struct hisi_sas_debugfs_regs *axi = s->private; - struct hisi_hba *hisi_hba = axi->hisi_hba; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI]; - - hisi_sas_debugfs_print_reg(axi->data, - reg_axi, s); - - return 0; - } - - static int hisi_sas_debugfs_axi_open(struct inode *inode, struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_axi_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_axi_fops = { - .open = hisi_sas_debugfs_axi_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p) - { - struct hisi_sas_debugfs_regs *ras = s->private; - struct hisi_hba *hisi_hba = ras->hisi_hba; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS]; - - hisi_sas_debugfs_print_reg(ras->data, - reg_ras, s); - - return 0; - } - - static int hisi_sas_debugfs_ras_open(struct inode *inode, struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_ras_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_ras_fops = { - .open = hisi_sas_debugfs_ras_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p) - { - struct hisi_sas_debugfs_port *port = s->private; - struct hisi_sas_phy *phy = port->phy; - struct hisi_hba *hisi_hba = phy->hisi_hba; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port; - - hisi_sas_debugfs_print_reg(port->data, reg_port, s); - - return 0; - } - - static int hisi_sas_debugfs_port_open(struct inode *inode, struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_port_show, inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_port_fops = { - .open = hisi_sas_debugfs_port_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static void hisi_sas_show_row_64(struct seq_file *s, int index, - int sz, __le64 *ptr) - { - int i; - - /* completion header size not fixed per HW version */ - seq_printf(s, "index %04d:\n\t", index); - for (i = 1; i <= sz / 8; i++, ptr++) { - seq_printf(s, " 0x%016llx", le64_to_cpu(*ptr)); - if (!(i % 2)) - seq_puts(s, "\n\t"); - } - - seq_puts(s, "\n"); - } - - static void hisi_sas_show_row_32(struct seq_file *s, int index, - int sz, __le32 *ptr) - { - int i; - - /* completion header size not fixed per HW version */ - seq_printf(s, "index %04d:\n\t", index); - for (i = 1; i <= sz / 4; i++, ptr++) { - seq_printf(s, " 0x%08x", le32_to_cpu(*ptr)); - if (!(i % 4)) - seq_puts(s, "\n\t"); - } - seq_puts(s, "\n"); - } - - static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, - struct hisi_sas_debugfs_cq *debugfs_cq) - { - struct hisi_sas_cq *cq = debugfs_cq->cq; - struct hisi_hba *hisi_hba = cq->hisi_hba; - __le32 *complete_hdr = debugfs_cq->complete_hdr + - (hisi_hba->hw->complete_hdr_size * slot); - - hisi_sas_show_row_32(s, slot, - hisi_hba->hw->complete_hdr_size, - complete_hdr); - } - - static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p) - { - struct hisi_sas_debugfs_cq *debugfs_cq = s->private; - int slot; - - for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { - hisi_sas_cq_show_slot(s, slot, debugfs_cq); - } - return 0; - } - - static int hisi_sas_debugfs_cq_open(struct inode *inode, struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_cq_show, inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_cq_fops = { - .open = hisi_sas_debugfs_cq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) - { - struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr; - void *cmd_queue = debugfs_dq->hdr; - __le32 *cmd_hdr = cmd_queue + - sizeof(struct hisi_sas_cmd_hdr) * slot; - - hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), cmd_hdr); - } - - static int hisi_sas_debugfs_dq_show(struct seq_file *s, void *p) - { - int slot; - - for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { - hisi_sas_dq_show_slot(s, slot, s->private); - } - return 0; - } - - static int hisi_sas_debugfs_dq_open(struct inode *inode, struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_dq_show, inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_dq_fops = { - .open = hisi_sas_debugfs_dq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) - { - struct hisi_sas_debugfs_iost *debugfs_iost = s->private; - struct hisi_sas_iost *iost = debugfs_iost->iost; - int i, max_command_entries = HISI_SAS_MAX_COMMANDS; - - for (i = 0; i < max_command_entries; i++, iost++) { - __le64 *data = &iost->qw0; - - hisi_sas_show_row_64(s, i, sizeof(*iost), data); - } - - return 0; - } - - static int hisi_sas_debugfs_iost_open(struct inode *inode, struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_iost_show, inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_iost_fops = { - .open = hisi_sas_debugfs_iost_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p) - { - struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private; - struct hisi_sas_iost_itct_cache *iost_cache = debugfs_iost_cache->cache; - u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; - int i, tab_idx; - __le64 *iost; - - for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { - /* - * Data struct of IOST cache: - * Data[1]: BIT0~15: Table index - * Bit16: Valid mask - * Data[2]~[9]: IOST table - */ - tab_idx = (iost_cache->data[1] & 0xffff); - iost = (__le64 *)iost_cache; - - hisi_sas_show_row_64(s, tab_idx, cache_size, iost); - } - - return 0; - } - - static int hisi_sas_debugfs_iost_cache_open(struct inode *inode, - struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_iost_cache_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_iost_cache_fops = { - .open = hisi_sas_debugfs_iost_cache_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) - { - int i; - struct hisi_sas_debugfs_itct *debugfs_itct = s->private; - struct hisi_sas_itct *itct = debugfs_itct->itct; - - for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { - __le64 *data = &itct->qw0; - - hisi_sas_show_row_64(s, i, sizeof(*itct), data); - } - - return 0; - } - - static int hisi_sas_debugfs_itct_open(struct inode *inode, struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_itct_show, inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_itct_fops = { - .open = hisi_sas_debugfs_itct_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p) + int hisi_sas_remove(struct platform_device *pdev) { - struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private; - struct hisi_sas_iost_itct_cache *itct_cache = debugfs_itct_cache->cache; - u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; - int i, tab_idx; - __le64 *itct; + struct sas_ha_struct *sha = platform_get_drvdata(pdev); + struct hisi_hba *hisi_hba = sha->lldd_ha; + struct Scsi_Host *shost = sha->core.shost;
- for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { - /* - * Data struct of ITCT cache: - * Data[1]: BIT0~15: Table index - * Bit16: Valid mask - * Data[2]~[9]: ITCT table - */ - tab_idx = itct_cache->data[1] & 0xffff; - itct = (__le64 *)itct_cache; + if (timer_pending(&hisi_hba->timer)) + del_timer(&hisi_hba->timer);
- hisi_sas_show_row_64(s, tab_idx, cache_size, itct); - } + sas_unregister_ha(sha); + sas_remove_host(sha->core.shost);
+ hisi_sas_free(hisi_hba); + scsi_host_put(shost); return 0; } + EXPORT_SYMBOL_GPL(hisi_sas_remove);
- static int hisi_sas_debugfs_itct_cache_open(struct inode *inode, - struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_itct_cache_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_itct_cache_fops = { - .open = hisi_sas_debugfs_itct_cache_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) - { - u64 *debugfs_timestamp; - int dump_index = hisi_hba->debugfs_dump_index; - struct dentry *dump_dentry; - struct dentry *dentry; - char name[256]; - int p; - int c; - int d; - - snprintf(name, 256, "%d", dump_index); - - dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry); - - debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index]; - - debugfs_create_u64("timestamp", 0400, dump_dentry, - debugfs_timestamp); - - debugfs_create_file("global", 0400, dump_dentry, - &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL], - &hisi_sas_debugfs_global_fops); - - /* Create port dir and files */ - dentry = debugfs_create_dir("port", dump_dentry); - for (p = 0; p < hisi_hba->n_phy; p++) { - snprintf(name, 256, "%d", p); - - debugfs_create_file(name, 0400, dentry, - &hisi_hba->debugfs_port_reg[dump_index][p], - &hisi_sas_debugfs_port_fops); - } - - /* Create CQ dir and files */ - dentry = debugfs_create_dir("cq", dump_dentry); - for (c = 0; c < hisi_hba->queue_count; c++) { - snprintf(name, 256, "%d", c); - - debugfs_create_file(name, 0400, dentry, - &hisi_hba->debugfs_cq[dump_index][c], - &hisi_sas_debugfs_cq_fops); - } - - /* Create DQ dir and files */ - dentry = debugfs_create_dir("dq", dump_dentry); - for (d = 0; d < hisi_hba->queue_count; d++) { - snprintf(name, 256, "%d", d); - - debugfs_create_file(name, 0400, dentry, - &hisi_hba->debugfs_dq[dump_index][d], - &hisi_sas_debugfs_dq_fops); - } - - debugfs_create_file("iost", 0400, dump_dentry, - &hisi_hba->debugfs_iost[dump_index], - &hisi_sas_debugfs_iost_fops); - - debugfs_create_file("iost_cache", 0400, dump_dentry, - &hisi_hba->debugfs_iost_cache[dump_index], - &hisi_sas_debugfs_iost_cache_fops); - - debugfs_create_file("itct", 0400, dump_dentry, - &hisi_hba->debugfs_itct[dump_index], - &hisi_sas_debugfs_itct_fops); - - debugfs_create_file("itct_cache", 0400, dump_dentry, - &hisi_hba->debugfs_itct_cache[dump_index], - &hisi_sas_debugfs_itct_cache_fops); - - debugfs_create_file("axi", 0400, dump_dentry, - &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI], - &hisi_sas_debugfs_axi_fops); - - debugfs_create_file("ras", 0400, dump_dentry, - &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS], - &hisi_sas_debugfs_ras_fops); - - return; - } - - static void hisi_sas_debugfs_snapshot_regs(struct hisi_hba *hisi_hba) - { - hisi_hba->hw->snapshot_prepare(hisi_hba); - - hisi_sas_debugfs_snapshot_global_reg(hisi_hba); - hisi_sas_debugfs_snapshot_port_reg(hisi_hba); - hisi_sas_debugfs_snapshot_axi_reg(hisi_hba); - hisi_sas_debugfs_snapshot_ras_reg(hisi_hba); - hisi_sas_debugfs_snapshot_cq_reg(hisi_hba); - hisi_sas_debugfs_snapshot_dq_reg(hisi_hba); - hisi_sas_debugfs_snapshot_itct_reg(hisi_hba); - hisi_sas_debugfs_snapshot_iost_reg(hisi_hba); - - hisi_sas_debugfs_create_files(hisi_hba); - - hisi_hba->hw->snapshot_restore(hisi_hba); - } + bool hisi_sas_debugfs_enable; + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_enable); + module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444); + MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)");
- static ssize_t hisi_sas_debugfs_trigger_dump_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) - { - struct hisi_hba *hisi_hba = file->f_inode->i_private; - char buf[8]; + u32 hisi_sas_debugfs_dump_count = 1; + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count); + module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444); + MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow");
- if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count) - return -EFAULT; - - if (count > 8) - return -EFAULT; - - if (copy_from_user(buf, user_buf, count)) - return -EFAULT; - - if (buf[0] != '1') - return -EFAULT; - - queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); - - return count; - } - - static const struct file_operations hisi_sas_debugfs_trigger_dump_fops = { - .write = &hisi_sas_debugfs_trigger_dump_write, - .owner = THIS_MODULE, - }; - - enum { - HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL = 0, - HISI_SAS_BIST_LOOPBACK_MODE_SERDES, - HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, - }; - - static const struct { - int value; - char *name; - } hisi_sas_debugfs_loop_linkrate[] = { - { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, - { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, - { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, - { SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit" }, - }; - - static int hisi_sas_debugfs_bist_linkrate_show(struct seq_file *s, void *p) - { - struct hisi_hba *hisi_hba = s->private; - int i; - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { - int match = (hisi_hba->debugfs_bist_linkrate == - hisi_sas_debugfs_loop_linkrate[i].value); - - seq_printf(s, "%s%s%s ", match ? "[" : "", - hisi_sas_debugfs_loop_linkrate[i].name, - match ? "]" : ""); - } - seq_puts(s, "\n"); - - return 0; - } - - static ssize_t hisi_sas_debugfs_bist_linkrate_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) - { - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - char kbuf[16] = {}, *pkbuf; - bool found = false; - int i; - - if (hisi_hba->debugfs_bist_enable) - return -EPERM; - - if (count >= sizeof(kbuf)) - return -EOVERFLOW; - - if (copy_from_user(kbuf, buf, count)) - return -EINVAL; - - pkbuf = strstrip(kbuf); - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { - if (!strncmp(hisi_sas_debugfs_loop_linkrate[i].name, - pkbuf, 16)) { - hisi_hba->debugfs_bist_linkrate = - hisi_sas_debugfs_loop_linkrate[i].value; - found = true; - break; - } - } - - if (!found) - return -EINVAL; - - return count; - } - - static int hisi_sas_debugfs_bist_linkrate_open(struct inode *inode, - struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_bist_linkrate_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_bist_linkrate_ops = { - .open = hisi_sas_debugfs_bist_linkrate_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_linkrate_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static const struct { - int value; - char *name; - } hisi_sas_debugfs_loop_code_mode[] = { - { HISI_SAS_BIST_CODE_MODE_PRBS7, "PRBS7" }, - { HISI_SAS_BIST_CODE_MODE_PRBS23, "PRBS23" }, - { HISI_SAS_BIST_CODE_MODE_PRBS31, "PRBS31" }, - { HISI_SAS_BIST_CODE_MODE_JTPAT, "JTPAT" }, - { HISI_SAS_BIST_CODE_MODE_CJTPAT, "CJTPAT" }, - { HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, "SCRAMBED_0" }, - { HISI_SAS_BIST_CODE_MODE_TRAIN, "TRAIN" }, - { HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, "TRAIN_DONE" }, - { HISI_SAS_BIST_CODE_MODE_HFTP, "HFTP" }, - { HISI_SAS_BIST_CODE_MODE_MFTP, "MFTP" }, - { HISI_SAS_BIST_CODE_MODE_LFTP, "LFTP" }, - { HISI_SAS_BIST_CODE_MODE_FIXED_DATA, "FIXED_DATA" }, - }; - - static int hisi_sas_debugfs_bist_code_mode_show(struct seq_file *s, void *p) - { - struct hisi_hba *hisi_hba = s->private; - int i; - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { - int match = (hisi_hba->debugfs_bist_code_mode == - hisi_sas_debugfs_loop_code_mode[i].value); - - seq_printf(s, "%s%s%s ", match ? "[" : "", - hisi_sas_debugfs_loop_code_mode[i].name, - match ? "]" : ""); - } - seq_puts(s, "\n"); - - return 0; - } - - static ssize_t hisi_sas_debugfs_bist_code_mode_write(struct file *filp, - const char __user *buf, - size_t count, - loff_t *ppos) - { - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - char kbuf[16] = {}, *pkbuf; - bool found = false; - int i; - - if (hisi_hba->debugfs_bist_enable) - return -EPERM; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(kbuf, buf, count)) - return -EOVERFLOW; - - pkbuf = strstrip(kbuf); - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { - if (!strncmp(hisi_sas_debugfs_loop_code_mode[i].name, - pkbuf, 16)) { - hisi_hba->debugfs_bist_code_mode = - hisi_sas_debugfs_loop_code_mode[i].value; - found = true; - break; - } - } - - if (!found) - return -EINVAL; - - return count; - } - - static int hisi_sas_debugfs_bist_code_mode_open(struct inode *inode, - struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_bist_code_mode_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_bist_code_mode_ops = { - .open = hisi_sas_debugfs_bist_code_mode_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_code_mode_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static ssize_t hisi_sas_debugfs_bist_phy_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) - { - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - unsigned int phy_no; - int val; - - if (hisi_hba->debugfs_bist_enable) - return -EPERM; - - val = kstrtouint_from_user(buf, count, 0, &phy_no); - if (val) - return val; - - if (phy_no >= hisi_hba->n_phy) - return -EINVAL; - - hisi_hba->debugfs_bist_phy_no = phy_no; - - return count; - } - - static int hisi_sas_debugfs_bist_phy_show(struct seq_file *s, void *p) - { - struct hisi_hba *hisi_hba = s->private; - - seq_printf(s, "%d\n", hisi_hba->debugfs_bist_phy_no); - - return 0; - } - - static int hisi_sas_debugfs_bist_phy_open(struct inode *inode, - struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_bist_phy_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_bist_phy_ops = { - .open = hisi_sas_debugfs_bist_phy_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_phy_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static const struct { - int value; - char *name; - } hisi_sas_debugfs_loop_modes[] = { - { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" }, - { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" }, - { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" }, - }; - - static int hisi_sas_debugfs_bist_mode_show(struct seq_file *s, void *p) - { - struct hisi_hba *hisi_hba = s->private; - int i; - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { - int match = (hisi_hba->debugfs_bist_mode == - hisi_sas_debugfs_loop_modes[i].value); - - seq_printf(s, "%s%s%s ", match ? "[" : "", - hisi_sas_debugfs_loop_modes[i].name, - match ? "]" : ""); - } - seq_puts(s, "\n"); - - return 0; - } - - static ssize_t hisi_sas_debugfs_bist_mode_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) - { - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - char kbuf[16] = {}, *pkbuf; - bool found = false; - int i; - - if (hisi_hba->debugfs_bist_enable) - return -EPERM; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(kbuf, buf, count)) - return -EOVERFLOW; - - pkbuf = strstrip(kbuf); - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { - if (!strncmp(hisi_sas_debugfs_loop_modes[i].name, pkbuf, 16)) { - hisi_hba->debugfs_bist_mode = - hisi_sas_debugfs_loop_modes[i].value; - found = true; - break; - } - } - - if (!found) - return -EINVAL; - - return count; - } - - static int hisi_sas_debugfs_bist_mode_open(struct inode *inode, - struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_bist_mode_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_bist_mode_ops = { - .open = hisi_sas_debugfs_bist_mode_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_mode_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static ssize_t hisi_sas_debugfs_bist_enable_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) - { - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - unsigned int enable; - int val; - - val = kstrtouint_from_user(buf, count, 0, &enable); - if (val) - return val; - - if (enable > 1) - return -EINVAL; - - if (enable == hisi_hba->debugfs_bist_enable) - return count; - - if (!hisi_hba->hw->set_bist) - return -EPERM; - - val = hisi_hba->hw->set_bist(hisi_hba, enable); - if (val < 0) - return val; - - hisi_hba->debugfs_bist_enable = enable; - - return count; - } - - static int hisi_sas_debugfs_bist_enable_show(struct seq_file *s, void *p) - { - struct hisi_hba *hisi_hba = s->private; - - seq_printf(s, "%d\n", hisi_hba->debugfs_bist_enable); - - return 0; - } - - static int hisi_sas_debugfs_bist_enable_open(struct inode *inode, - struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_bist_enable_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_bist_enable_ops = { - .open = hisi_sas_debugfs_bist_enable_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_enable_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static const struct { - char *name; - } hisi_sas_debugfs_ffe_name[FFE_CFG_MAX] = { - { "SAS_1_5_GBPS" }, - { "SAS_3_0_GBPS" }, - { "SAS_6_0_GBPS" }, - { "SAS_12_0_GBPS" }, - { "FFE_RESV" }, - { "SATA_1_5_GBPS" }, - { "SATA_3_0_GBPS" }, - { "SATA_6_0_GBPS" }, - }; - - static ssize_t hisi_sas_debugfs_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) - { - struct seq_file *m = filp->private_data; - u32 *val = m->private; - int res; - - res = kstrtouint_from_user(buf, count, 0, val); - if (res) - return res; - - return count; - } - - static int hisi_sas_debugfs_show(struct seq_file *s, void *p) - { - u32 *val = s->private; - - seq_printf(s, "0x%x\n", *val); - - return 0; - } - - static int hisi_sas_debugfs_open(struct inode *inode, struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_ops = { - .open = hisi_sas_debugfs_open, - .read = seq_read, - .write = hisi_sas_debugfs_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) - { - struct seq_file *s = filp->private_data; - struct hisi_sas_phy *phy = s->private; - unsigned int set_val; - int res; - - res = kstrtouint_from_user(buf, count, 0, &set_val); - if (res) - return res; - - if (set_val > 0) - return -EINVAL; - - atomic_set(&phy->down_cnt, 0); - - return count; - } - - static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p) - { - struct hisi_sas_phy *phy = s->private; - - seq_printf(s, "%d\n", atomic_read(&phy->down_cnt)); - - return 0; - } - - static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode, - struct file *filp) - { - return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show, - inode->i_private); - } - - static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = { - .open = hisi_sas_debugfs_phy_down_cnt_open, - .read = seq_read, - .write = hisi_sas_debugfs_phy_down_cnt_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }; - - void hisi_sas_debugfs_work_handler(struct work_struct *work) - { - struct hisi_hba *hisi_hba = - container_of(work, struct hisi_hba, debugfs_work); - int debugfs_dump_index = hisi_hba->debugfs_dump_index; - struct device *dev = hisi_hba->dev; - u64 timestamp = local_clock(); - - if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { - dev_warn(dev, "dump count exceeded!\n"); - return; - } - - do_div(timestamp, NSEC_PER_MSEC); - hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; - - hisi_sas_debugfs_snapshot_regs(hisi_hba); - hisi_hba->debugfs_dump_index++; - } - EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); - - static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba, int dump_index) - { - struct device *dev = hisi_hba->dev; - int i; - - devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache); - devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache); - devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost); - devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct); - - for (i = 0; i < hisi_hba->queue_count; i++) - devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr); - - for (i = 0; i < hisi_hba->queue_count; i++) - devm_kfree(dev, - hisi_hba->debugfs_cq[dump_index][i].complete_hdr); - - for (i = 0; i < DEBUGFS_REGS_NUM; i++) - devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data); - - for (i = 0; i < hisi_hba->n_phy; i++) - devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data); - } - - static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index) - { - const struct hisi_sas_hw *hw = hisi_hba->hw; - struct device *dev = hisi_hba->dev; - int p, c, d, r, i; - size_t sz; - - for (r = 0; r < DEBUGFS_REGS_NUM; r++) { - struct hisi_sas_debugfs_regs *regs = - &hisi_hba->debugfs_regs[dump_index][r]; - - sz = hw->debugfs_reg_array[r]->count * 4; - regs->data = devm_kmalloc(dev, sz, GFP_KERNEL); - if (!regs->data) - goto fail; - regs->hisi_hba = hisi_hba; - } - - sz = hw->debugfs_reg_port->count * 4; - for (p = 0; p < hisi_hba->n_phy; p++) { - struct hisi_sas_debugfs_port *port = - &hisi_hba->debugfs_port_reg[dump_index][p]; - - port->data = devm_kmalloc(dev, sz, GFP_KERNEL); - if (!port->data) - goto fail; - port->phy = &hisi_hba->phy[p]; - } - - sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; - for (c = 0; c < hisi_hba->queue_count; c++) { - struct hisi_sas_debugfs_cq *cq = - &hisi_hba->debugfs_cq[dump_index][c]; - - cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL); - if (!cq->complete_hdr) - goto fail; - cq->cq = &hisi_hba->cq[c]; - } - - sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; - for (d = 0; d < hisi_hba->queue_count; d++) { - struct hisi_sas_debugfs_dq *dq = - &hisi_hba->debugfs_dq[dump_index][d]; - - dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL); - if (!dq->hdr) - goto fail; - dq->dq = &hisi_hba->dq[d]; - } - - sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); - - hisi_hba->debugfs_iost[dump_index].iost = - devm_kmalloc(dev, sz, GFP_KERNEL); - if (!hisi_hba->debugfs_iost[dump_index].iost) - goto fail; - - sz = HISI_SAS_IOST_ITCT_CACHE_NUM * - sizeof(struct hisi_sas_iost_itct_cache); - - hisi_hba->debugfs_iost_cache[dump_index].cache = - devm_kmalloc(dev, sz, GFP_KERNEL); - if (!hisi_hba->debugfs_iost_cache[dump_index].cache) - goto fail; - - sz = HISI_SAS_IOST_ITCT_CACHE_NUM * - sizeof(struct hisi_sas_iost_itct_cache); - - hisi_hba->debugfs_itct_cache[dump_index].cache = - devm_kmalloc(dev, sz, GFP_KERNEL); - if (!hisi_hba->debugfs_itct_cache[dump_index].cache) - goto fail; - - /* New memory allocation must be locate before itct */ - sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); - - hisi_hba->debugfs_itct[dump_index].itct = - devm_kmalloc(dev, sz, GFP_KERNEL); - if (!hisi_hba->debugfs_itct[dump_index].itct) - goto fail; - - return 0; - fail: - for (i = 0; i < hisi_sas_debugfs_dump_count; i++) - hisi_sas_debugfs_release(hisi_hba, i); - return -ENOMEM; - } - - static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba) - { - struct dentry *dir = debugfs_create_dir("phy_down_cnt", - hisi_hba->debugfs_dir); - char name[16]; - int phy_no; - - for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { - snprintf(name, 16, "%d", phy_no); - debugfs_create_file(name, 0600, dir, - &hisi_hba->phy[phy_no], - &hisi_sas_debugfs_phy_down_cnt_ops); - } - } - - static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba) - { - struct dentry *ports_dentry; - int phy_no; - - hisi_hba->debugfs_bist_dentry = - debugfs_create_dir("bist", hisi_hba->debugfs_dir); - debugfs_create_file("link_rate", 0600, - hisi_hba->debugfs_bist_dentry, hisi_hba, - &hisi_sas_debugfs_bist_linkrate_ops); - - debugfs_create_file("code_mode", 0600, - hisi_hba->debugfs_bist_dentry, hisi_hba, - &hisi_sas_debugfs_bist_code_mode_ops); - - debugfs_create_file("fixed_code", 0600, - hisi_hba->debugfs_bist_dentry, - &hisi_hba->debugfs_bist_fixed_code[0], - &hisi_sas_debugfs_ops); - - debugfs_create_file("fixed_code_1", 0600, - hisi_hba->debugfs_bist_dentry, - &hisi_hba->debugfs_bist_fixed_code[1], - &hisi_sas_debugfs_ops); - - debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, - hisi_hba, &hisi_sas_debugfs_bist_phy_ops); - - debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry, - &hisi_hba->debugfs_bist_cnt); - - debugfs_create_file("loopback_mode", 0600, - hisi_hba->debugfs_bist_dentry, - hisi_hba, &hisi_sas_debugfs_bist_mode_ops); - - debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry, - hisi_hba, &hisi_sas_debugfs_bist_enable_ops); - - ports_dentry = debugfs_create_dir("port", hisi_hba->debugfs_bist_dentry); - - for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { - struct dentry *port_dentry; - struct dentry *ffe_dentry; - char name[256]; - int i; - - snprintf(name, 256, "%d", phy_no); - port_dentry = debugfs_create_dir(name, ports_dentry); - ffe_dentry = debugfs_create_dir("ffe", port_dentry); - for (i = 0; i < FFE_CFG_MAX; i++) { - if (i == FFE_RESV) - continue; - debugfs_create_file(hisi_sas_debugfs_ffe_name[i].name, - 0600, ffe_dentry, - &hisi_hba->debugfs_bist_ffe[phy_no][i], - &hisi_sas_debugfs_ops); - } - } - - hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS; - } - - void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) - { - struct device *dev = hisi_hba->dev; - int i; - - hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), - hisi_sas_debugfs_dir); - debugfs_create_file("trigger_dump", 0200, - hisi_hba->debugfs_dir, - hisi_hba, - &hisi_sas_debugfs_trigger_dump_fops); - - /* create bist structures */ - hisi_sas_debugfs_bist_init(hisi_hba); - - hisi_hba->debugfs_dump_dentry = - debugfs_create_dir("dump", hisi_hba->debugfs_dir); - - hisi_sas_debugfs_phy_down_cnt_init(hisi_hba); - - for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { - if (hisi_sas_debugfs_alloc(hisi_hba, i)) { - debugfs_remove_recursive(hisi_hba->debugfs_dir); - dev_dbg(dev, "failed to init debugfs!\n"); - break; - } - } - } - EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init); - - void hisi_sas_debugfs_exit(struct hisi_hba *hisi_hba) - { - debugfs_remove_recursive(hisi_hba->debugfs_dir); - } - EXPORT_SYMBOL_GPL(hisi_sas_debugfs_exit); - - int hisi_sas_remove(struct platform_device *pdev) - { - struct sas_ha_struct *sha = platform_get_drvdata(pdev); - struct hisi_hba *hisi_hba = sha->lldd_ha; - struct Scsi_Host *shost = sha->core.shost; - - if (timer_pending(&hisi_hba->timer)) - del_timer(&hisi_hba->timer); - - sas_unregister_ha(sha); - sas_remove_host(sha->core.shost); - - hisi_sas_free(hisi_hba); - scsi_host_put(shost); - return 0; - } - EXPORT_SYMBOL_GPL(hisi_sas_remove); - - bool hisi_sas_debugfs_enable; - EXPORT_SYMBOL_GPL(hisi_sas_debugfs_enable); - module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444); - MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)"); - - u32 hisi_sas_debugfs_dump_count = 1; - EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count); - module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444); - MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow"); + struct dentry *hisi_sas_debugfs_dir; + EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dir);
static __init int hisi_sas_init(void) { diff --combined drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 960de375ce69,88f203f96280..7c12804b4e1d --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@@ -522,6 -522,8 +522,8 @@@ module_param(auto_affine_msi_experiment MODULE_PARM_DESC(auto_affine_msi_experimental, "Enable auto-affinity of MSI IRQs as experimental:\n" "default is off");
+ static void debugfs_work_handler_v3_hw(struct work_struct *work); + static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) { void __iomem *regs = hisi_hba->regs + off; @@@ -2409,8 -2411,7 +2411,7 @@@ static int interrupt_init_v3_hw(struct DRV_NAME " phy", hisi_hba); if (rc) { dev_err(dev, "could not request phy interrupt, rc=%d\n", rc); - rc = -ENOENT; - goto free_irq_vectors; + return -ENOENT; }
rc = devm_request_irq(dev, pci_irq_vector(pdev, 2), @@@ -2418,8 -2419,7 +2419,7 @@@ DRV_NAME " channel", hisi_hba); if (rc) { dev_err(dev, "could not request chnl interrupt, rc=%d\n", rc); - rc = -ENOENT; - goto free_irq_vectors; + return -ENOENT; }
rc = devm_request_irq(dev, pci_irq_vector(pdev, 11), @@@ -2427,8 -2427,7 +2427,7 @@@ DRV_NAME " fatal", hisi_hba); if (rc) { dev_err(dev, "could not request fatal interrupt, rc=%d\n", rc); - rc = -ENOENT; - goto free_irq_vectors; + return -ENOENT; }
if (hisi_sas_intr_conv) @@@ -2449,21 -2448,11 +2448,16 @@@ if (rc) { dev_err(dev, "could not request cq%d interrupt, rc=%d\n", i, rc); - rc = -ENOENT; - goto free_irq_vectors; + return -ENOENT; } + cq->irq_mask = pci_irq_get_affinity(pdev, i + BASE_VECTORS_V3_HW); + if (!cq->irq_mask) { + dev_err(dev, "could not get cq%d irq affinity!\n", i); + return -ENOENT; + } }
return 0; - - free_irq_vectors: - pci_free_irq_vectors(pdev); - return rc; }
static int hisi_sas_v3_init(struct hisi_hba *hisi_hba) @@@ -2766,6 -2755,19 +2760,19 @@@ static struct device_attribute *host_at NULL };
+ #define HISI_SAS_DEBUGFS_REG(x) {#x, x} + + struct hisi_sas_debugfs_reg_lu { + char *name; + int off; + }; + + struct hisi_sas_debugfs_reg { + const struct hisi_sas_debugfs_reg_lu *lu; + int count; + int base_off; + }; + static const struct hisi_sas_debugfs_reg_lu debugfs_port_reg_lu[] = { HISI_SAS_DEBUGFS_REG(PHY_CFG), HISI_SAS_DEBUGFS_REG(HARD_PHY_LINKRATE), @@@ -2821,7 -2823,6 +2828,6 @@@ static const struct hisi_sas_debugfs_re .lu = debugfs_port_reg_lu, .count = 0x100, .base_off = PORT_BASE, - .read_port_reg = hisi_sas_phy_read32, };
static const struct hisi_sas_debugfs_reg_lu debugfs_global_reg_lu[] = { @@@ -2894,7 -2895,6 +2900,6 @@@ static const struct hisi_sas_debugfs_reg debugfs_global_reg = { .lu = debugfs_global_reg_lu, .count = 0x800, - .read_global_reg = hisi_sas_read32, };
static const struct hisi_sas_debugfs_reg_lu debugfs_axi_reg_lu[] = { @@@ -2909,7 -2909,6 +2914,6 @@@ static const struct hisi_sas_debugfs_re .lu = debugfs_axi_reg_lu, .count = 0x61, .base_off = AXI_MASTER_CFG_BASE, - .read_global_reg = hisi_sas_read32, };
static const struct hisi_sas_debugfs_reg_lu debugfs_ras_reg_lu[] = { @@@ -2927,7 -2926,6 +2931,6 @@@ static const struct hisi_sas_debugfs_re .lu = debugfs_ras_reg_lu, .count = 0x10, .base_off = RAS_BASE, - .read_global_reg = hisi_sas_read32, };
static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) @@@ -3147,7 -3145,6 +3150,6 @@@ static struct scsi_host_template sht_v3 };
static const struct hisi_sas_hw hisi_sas_v3_hw = { - .hw_init = hisi_sas_v3_init, .setup_itct = setup_itct_v3_hw, .get_wideport_bitmap = get_wideport_bitmap_v3_hw, .complete_hdr_size = sizeof(struct hisi_sas_complete_v3_hdr), @@@ -3170,14 -3167,6 +3172,6 @@@ .get_events = phy_get_events_v3_hw, .write_gpio = write_gpio_v3_hw, .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v3_hw, - .debugfs_reg_array[DEBUGFS_GLOBAL] = &debugfs_global_reg, - .debugfs_reg_array[DEBUGFS_AXI] = &debugfs_axi_reg, - .debugfs_reg_array[DEBUGFS_RAS] = &debugfs_ras_reg, - .debugfs_reg_port = &debugfs_port_reg, - .snapshot_prepare = debugfs_snapshot_prepare_v3_hw, - .snapshot_restore = debugfs_snapshot_restore_v3_hw, - .read_iost_itct_cache = read_iost_itct_cache_v3_hw, - .set_bist = debugfs_set_bist_v3_hw, };
static struct Scsi_Host * @@@ -3195,7 -3184,7 +3189,7 @@@ hisi_sas_shost_alloc_pci(struct pci_de hisi_hba = shost_priv(shost);
INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler); - INIT_WORK(&hisi_hba->debugfs_work, hisi_sas_debugfs_work_handler); + INIT_WORK(&hisi_hba->debugfs_work, debugfs_work_handler_v3_hw); hisi_hba->hw = &hisi_sas_v3_hw; hisi_hba->pci_dev = pdev; hisi_hba->dev = dev; @@@ -3223,6 -3212,1196 +3217,1196 @@@ err_out return NULL; }
+ static void debugfs_snapshot_cq_reg_v3_hw(struct hisi_hba *hisi_hba) + { + int queue_entry_size = hisi_hba->hw->complete_hdr_size; + int dump_index = hisi_hba->debugfs_dump_index; + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) + memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr, + hisi_hba->complete_hdr[i], + HISI_SAS_QUEUE_SLOTS * queue_entry_size); + } + + static void debugfs_snapshot_dq_reg_v3_hw(struct hisi_hba *hisi_hba) + { + int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr); + int dump_index = hisi_hba->debugfs_dump_index; + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) { + struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr; + int j; + + debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr; + cmd_hdr = hisi_hba->cmd_hdr[i]; + + for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++) + memcpy(&debugfs_cmd_hdr[j], &cmd_hdr[j], + queue_entry_size); + } + } + + static void debugfs_snapshot_port_reg_v3_hw(struct hisi_hba *hisi_hba) + { + int dump_index = hisi_hba->debugfs_dump_index; + const struct hisi_sas_debugfs_reg *port = &debugfs_port_reg; + int i, phy_cnt; + u32 offset; + u32 *databuf; + + for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { + databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data; + for (i = 0; i < port->count; i++, databuf++) { + offset = port->base_off + 4 * i; + *databuf = hisi_sas_phy_read32(hisi_hba, phy_cnt, + offset); + } + } + } + + static void debugfs_snapshot_global_reg_v3_hw(struct hisi_hba *hisi_hba) + { + int dump_index = hisi_hba->debugfs_dump_index; + u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data; + int i; + + for (i = 0; i < debugfs_axi_reg.count; i++, databuf++) + *databuf = hisi_sas_read32(hisi_hba, 4 * i); + } + + static void debugfs_snapshot_axi_reg_v3_hw(struct hisi_hba *hisi_hba) + { + int dump_index = hisi_hba->debugfs_dump_index; + u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data; + const struct hisi_sas_debugfs_reg *axi = &debugfs_axi_reg; + int i; + + for (i = 0; i < axi->count; i++, databuf++) + *databuf = hisi_sas_read32(hisi_hba, 4 * i + axi->base_off); + } + + static void debugfs_snapshot_ras_reg_v3_hw(struct hisi_hba *hisi_hba) + { + int dump_index = hisi_hba->debugfs_dump_index; + u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data; + const struct hisi_sas_debugfs_reg *ras = &debugfs_ras_reg; + int i; + + for (i = 0; i < ras->count; i++, databuf++) + *databuf = hisi_sas_read32(hisi_hba, 4 * i + ras->base_off); + } + + static void debugfs_snapshot_itct_reg_v3_hw(struct hisi_hba *hisi_hba) + { + int dump_index = hisi_hba->debugfs_dump_index; + void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache; + void *databuf = hisi_hba->debugfs_itct[dump_index].itct; + struct hisi_sas_itct *itct; + int i; + + read_iost_itct_cache_v3_hw(hisi_hba, HISI_SAS_ITCT_CACHE, cachebuf); + + itct = hisi_hba->itct; + + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { + memcpy(databuf, itct, sizeof(struct hisi_sas_itct)); + databuf += sizeof(struct hisi_sas_itct); + } + } + + static void debugfs_snapshot_iost_reg_v3_hw(struct hisi_hba *hisi_hba) + { + int dump_index = hisi_hba->debugfs_dump_index; + int max_command_entries = HISI_SAS_MAX_COMMANDS; + void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache; + void *databuf = hisi_hba->debugfs_iost[dump_index].iost; + struct hisi_sas_iost *iost; + int i; + + read_iost_itct_cache_v3_hw(hisi_hba, HISI_SAS_IOST_CACHE, cachebuf); + + iost = hisi_hba->iost; + + for (i = 0; i < max_command_entries; i++, iost++) { + memcpy(databuf, iost, sizeof(struct hisi_sas_iost)); + databuf += sizeof(struct hisi_sas_iost); + } + } + + static const char * + debugfs_to_reg_name_v3_hw(int off, int base_off, + const struct hisi_sas_debugfs_reg_lu *lu) + { + for (; lu->name; lu++) { + if (off == lu->off - base_off) + return lu->name; + } + + return NULL; + } + + static void debugfs_print_reg_v3_hw(u32 *regs_val, struct seq_file *s, + const struct hisi_sas_debugfs_reg *reg) + { + int i; + + for (i = 0; i < reg->count; i++) { + int off = i * 4; + const char *name; + + name = debugfs_to_reg_name_v3_hw(off, reg->base_off, + reg->lu); + + if (name) + seq_printf(s, "0x%08x 0x%08x %s\n", off, + regs_val[i], name); + else + seq_printf(s, "0x%08x 0x%08x\n", off, + regs_val[i]); + } + } + + static int debugfs_global_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_regs *global = s->private; + + debugfs_print_reg_v3_hw(global->data, s, + &debugfs_global_reg); + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_global_v3_hw); + + static int debugfs_axi_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_regs *axi = s->private; + + debugfs_print_reg_v3_hw(axi->data, s, + &debugfs_axi_reg); + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_axi_v3_hw); + + static int debugfs_ras_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_regs *ras = s->private; + + debugfs_print_reg_v3_hw(ras->data, s, + &debugfs_ras_reg); + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_ras_v3_hw); + + static int debugfs_port_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_port *port = s->private; + const struct hisi_sas_debugfs_reg *reg_port = &debugfs_port_reg; + + debugfs_print_reg_v3_hw(port->data, s, reg_port); + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_port_v3_hw); + + static void debugfs_show_row_64_v3_hw(struct seq_file *s, int index, + int sz, __le64 *ptr) + { + int i; + + /* completion header size not fixed per HW version */ + seq_printf(s, "index %04d:\n\t", index); + for (i = 1; i <= sz / 8; i++, ptr++) { + seq_printf(s, " 0x%016llx", le64_to_cpu(*ptr)); + if (!(i % 2)) + seq_puts(s, "\n\t"); + } + + seq_puts(s, "\n"); + } + + static void debugfs_show_row_32_v3_hw(struct seq_file *s, int index, + int sz, __le32 *ptr) + { + int i; + + /* completion header size not fixed per HW version */ + seq_printf(s, "index %04d:\n\t", index); + for (i = 1; i <= sz / 4; i++, ptr++) { + seq_printf(s, " 0x%08x", le32_to_cpu(*ptr)); + if (!(i % 4)) + seq_puts(s, "\n\t"); + } + seq_puts(s, "\n"); + } + + static void debugfs_cq_show_slot_v3_hw(struct seq_file *s, int slot, + struct hisi_sas_debugfs_cq *debugfs_cq) + { + struct hisi_sas_cq *cq = debugfs_cq->cq; + struct hisi_hba *hisi_hba = cq->hisi_hba; + __le32 *complete_hdr = debugfs_cq->complete_hdr + + (hisi_hba->hw->complete_hdr_size * slot); + + debugfs_show_row_32_v3_hw(s, slot, + hisi_hba->hw->complete_hdr_size, + complete_hdr); + } + + static int debugfs_cq_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_cq *debugfs_cq = s->private; + int slot; + + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) + debugfs_cq_show_slot_v3_hw(s, slot, debugfs_cq); + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_cq_v3_hw); + + static void debugfs_dq_show_slot_v3_hw(struct seq_file *s, int slot, + void *dq_ptr) + { + struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr; + void *cmd_queue = debugfs_dq->hdr; + __le32 *cmd_hdr = cmd_queue + + sizeof(struct hisi_sas_cmd_hdr) * slot; + + debugfs_show_row_32_v3_hw(s, slot, sizeof(struct hisi_sas_cmd_hdr), + cmd_hdr); + } + + static int debugfs_dq_v3_hw_show(struct seq_file *s, void *p) + { + int slot; + + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) + debugfs_dq_show_slot_v3_hw(s, slot, s->private); + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_dq_v3_hw); + + static int debugfs_iost_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_iost *debugfs_iost = s->private; + struct hisi_sas_iost *iost = debugfs_iost->iost; + int i, max_command_entries = HISI_SAS_MAX_COMMANDS; + + for (i = 0; i < max_command_entries; i++, iost++) { + __le64 *data = &iost->qw0; + + debugfs_show_row_64_v3_hw(s, i, sizeof(*iost), data); + } + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_iost_v3_hw); + + static int debugfs_iost_cache_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private; + struct hisi_sas_iost_itct_cache *iost_cache = + debugfs_iost_cache->cache; + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; + int i, tab_idx; + __le64 *iost; + + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { + /* + * Data struct of IOST cache: + * Data[1]: BIT0~15: Table index + * Bit16: Valid mask + * Data[2]~[9]: IOST table + */ + tab_idx = (iost_cache->data[1] & 0xffff); + iost = (__le64 *)iost_cache; + + debugfs_show_row_64_v3_hw(s, tab_idx, cache_size, iost); + } + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_iost_cache_v3_hw); + + static int debugfs_itct_v3_hw_show(struct seq_file *s, void *p) + { + int i; + struct hisi_sas_debugfs_itct *debugfs_itct = s->private; + struct hisi_sas_itct *itct = debugfs_itct->itct; + + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { + __le64 *data = &itct->qw0; + + debugfs_show_row_64_v3_hw(s, i, sizeof(*itct), data); + } + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_itct_v3_hw); + + static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private; + struct hisi_sas_iost_itct_cache *itct_cache = + debugfs_itct_cache->cache; + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; + int i, tab_idx; + __le64 *itct; + + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { + /* + * Data struct of ITCT cache: + * Data[1]: BIT0~15: Table index + * Bit16: Valid mask + * Data[2]~[9]: ITCT table + */ + tab_idx = itct_cache->data[1] & 0xffff; + itct = (__le64 *)itct_cache; + + debugfs_show_row_64_v3_hw(s, tab_idx, cache_size, itct); + } + + return 0; + } + DEFINE_SHOW_ATTRIBUTE(debugfs_itct_cache_v3_hw); + + static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) + { + u64 *debugfs_timestamp; + int dump_index = hisi_hba->debugfs_dump_index; + struct dentry *dump_dentry; + struct dentry *dentry; + char name[256]; + int p; + int c; + int d; + + snprintf(name, 256, "%d", dump_index); + + dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry); + + debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index]; + + debugfs_create_u64("timestamp", 0400, dump_dentry, + debugfs_timestamp); + + debugfs_create_file("global", 0400, dump_dentry, + &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL], + &debugfs_global_v3_hw_fops); + + /* Create port dir and files */ + dentry = debugfs_create_dir("port", dump_dentry); + for (p = 0; p < hisi_hba->n_phy; p++) { + snprintf(name, 256, "%d", p); + + debugfs_create_file(name, 0400, dentry, + &hisi_hba->debugfs_port_reg[dump_index][p], + &debugfs_port_v3_hw_fops); + } + + /* Create CQ dir and files */ + dentry = debugfs_create_dir("cq", dump_dentry); + for (c = 0; c < hisi_hba->queue_count; c++) { + snprintf(name, 256, "%d", c); + + debugfs_create_file(name, 0400, dentry, + &hisi_hba->debugfs_cq[dump_index][c], + &debugfs_cq_v3_hw_fops); + } + + /* Create DQ dir and files */ + dentry = debugfs_create_dir("dq", dump_dentry); + for (d = 0; d < hisi_hba->queue_count; d++) { + snprintf(name, 256, "%d", d); + + debugfs_create_file(name, 0400, dentry, + &hisi_hba->debugfs_dq[dump_index][d], + &debugfs_dq_v3_hw_fops); + } + + debugfs_create_file("iost", 0400, dump_dentry, + &hisi_hba->debugfs_iost[dump_index], + &debugfs_iost_v3_hw_fops); + + debugfs_create_file("iost_cache", 0400, dump_dentry, + &hisi_hba->debugfs_iost_cache[dump_index], + &debugfs_iost_cache_v3_hw_fops); + + debugfs_create_file("itct", 0400, dump_dentry, + &hisi_hba->debugfs_itct[dump_index], + &debugfs_itct_v3_hw_fops); + + debugfs_create_file("itct_cache", 0400, dump_dentry, + &hisi_hba->debugfs_itct_cache[dump_index], + &debugfs_itct_cache_v3_hw_fops); + + debugfs_create_file("axi", 0400, dump_dentry, + &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI], + &debugfs_axi_v3_hw_fops); + + debugfs_create_file("ras", 0400, dump_dentry, + &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS], + &debugfs_ras_v3_hw_fops); + } + + static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba) + { + debugfs_snapshot_prepare_v3_hw(hisi_hba); + + debugfs_snapshot_global_reg_v3_hw(hisi_hba); + debugfs_snapshot_port_reg_v3_hw(hisi_hba); + debugfs_snapshot_axi_reg_v3_hw(hisi_hba); + debugfs_snapshot_ras_reg_v3_hw(hisi_hba); + debugfs_snapshot_cq_reg_v3_hw(hisi_hba); + debugfs_snapshot_dq_reg_v3_hw(hisi_hba); + debugfs_snapshot_itct_reg_v3_hw(hisi_hba); + debugfs_snapshot_iost_reg_v3_hw(hisi_hba); + + debugfs_create_files_v3_hw(hisi_hba); + + debugfs_snapshot_restore_v3_hw(hisi_hba); + } + + static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) + { + struct hisi_hba *hisi_hba = file->f_inode->i_private; + char buf[8]; + + if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count) + return -EFAULT; + + if (count > 8) + return -EFAULT; + + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + + if (buf[0] != '1') + return -EFAULT; + + queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); + + return count; + } + + static const struct file_operations debugfs_trigger_dump_v3_hw_fops = { + .write = &debugfs_trigger_dump_v3_hw_write, + .owner = THIS_MODULE, + }; + + enum { + HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL = 0, + HISI_SAS_BIST_LOOPBACK_MODE_SERDES, + HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, + }; + + static const struct { + int value; + char *name; + } debugfs_loop_linkrate_v3_hw[] = { + { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, + { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, + { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, + { SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit" }, + }; + + static int debugfs_bist_linkrate_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_hba *hisi_hba = s->private; + int i; + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_linkrate_v3_hw); i++) { + int match = (hisi_hba->debugfs_bist_linkrate == + debugfs_loop_linkrate_v3_hw[i].value); + + seq_printf(s, "%s%s%s ", match ? "[" : "", + debugfs_loop_linkrate_v3_hw[i].name, + match ? "]" : ""); + } + seq_puts(s, "\n"); + + return 0; + } + + static ssize_t debugfs_bist_linkrate_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) + { + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + char kbuf[16] = {}, *pkbuf; + bool found = false; + int i; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + if (count >= sizeof(kbuf)) + return -EOVERFLOW; + + if (copy_from_user(kbuf, buf, count)) + return -EINVAL; + + pkbuf = strstrip(kbuf); + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_linkrate_v3_hw); i++) { + if (!strncmp(debugfs_loop_linkrate_v3_hw[i].name, + pkbuf, 16)) { + hisi_hba->debugfs_bist_linkrate = + debugfs_loop_linkrate_v3_hw[i].value; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return count; + } + + static int debugfs_bist_linkrate_v3_hw_open(struct inode *inode, + struct file *filp) + { + return single_open(filp, debugfs_bist_linkrate_v3_hw_show, + inode->i_private); + } + + static const struct file_operations debugfs_bist_linkrate_v3_hw_fops = { + .open = debugfs_bist_linkrate_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_linkrate_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, + }; + + static const struct { + int value; + char *name; + } debugfs_loop_code_mode_v3_hw[] = { + { HISI_SAS_BIST_CODE_MODE_PRBS7, "PRBS7" }, + { HISI_SAS_BIST_CODE_MODE_PRBS23, "PRBS23" }, + { HISI_SAS_BIST_CODE_MODE_PRBS31, "PRBS31" }, + { HISI_SAS_BIST_CODE_MODE_JTPAT, "JTPAT" }, + { HISI_SAS_BIST_CODE_MODE_CJTPAT, "CJTPAT" }, + { HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, "SCRAMBED_0" }, + { HISI_SAS_BIST_CODE_MODE_TRAIN, "TRAIN" }, + { HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, "TRAIN_DONE" }, + { HISI_SAS_BIST_CODE_MODE_HFTP, "HFTP" }, + { HISI_SAS_BIST_CODE_MODE_MFTP, "MFTP" }, + { HISI_SAS_BIST_CODE_MODE_LFTP, "LFTP" }, + { HISI_SAS_BIST_CODE_MODE_FIXED_DATA, "FIXED_DATA" }, + }; + + static int debugfs_bist_code_mode_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_hba *hisi_hba = s->private; + int i; + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_code_mode_v3_hw); i++) { + int match = (hisi_hba->debugfs_bist_code_mode == + debugfs_loop_code_mode_v3_hw[i].value); + + seq_printf(s, "%s%s%s ", match ? "[" : "", + debugfs_loop_code_mode_v3_hw[i].name, + match ? "]" : ""); + } + seq_puts(s, "\n"); + + return 0; + } + + static ssize_t debugfs_bist_code_mode_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, + loff_t *ppos) + { + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + char kbuf[16] = {}, *pkbuf; + bool found = false; + int i; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + if (count >= sizeof(kbuf)) + return -EINVAL; + + if (copy_from_user(kbuf, buf, count)) + return -EOVERFLOW; + + pkbuf = strstrip(kbuf); + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_code_mode_v3_hw); i++) { + if (!strncmp(debugfs_loop_code_mode_v3_hw[i].name, + pkbuf, 16)) { + hisi_hba->debugfs_bist_code_mode = + debugfs_loop_code_mode_v3_hw[i].value; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return count; + } + + static int debugfs_bist_code_mode_v3_hw_open(struct inode *inode, + struct file *filp) + { + return single_open(filp, debugfs_bist_code_mode_v3_hw_show, + inode->i_private); + } + + static const struct file_operations debugfs_bist_code_mode_v3_hw_fops = { + .open = debugfs_bist_code_mode_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_code_mode_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, + }; + + static ssize_t debugfs_bist_phy_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) + { + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + unsigned int phy_no; + int val; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + val = kstrtouint_from_user(buf, count, 0, &phy_no); + if (val) + return val; + + if (phy_no >= hisi_hba->n_phy) + return -EINVAL; + + hisi_hba->debugfs_bist_phy_no = phy_no; + + return count; + } + + static int debugfs_bist_phy_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_hba *hisi_hba = s->private; + + seq_printf(s, "%d\n", hisi_hba->debugfs_bist_phy_no); + + return 0; + } + + static int debugfs_bist_phy_v3_hw_open(struct inode *inode, + struct file *filp) + { + return single_open(filp, debugfs_bist_phy_v3_hw_show, + inode->i_private); + } + + static const struct file_operations debugfs_bist_phy_v3_hw_fops = { + .open = debugfs_bist_phy_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_phy_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, + }; + + static const struct { + int value; + char *name; + } debugfs_loop_modes_v3_hw[] = { + { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" }, + { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" }, + { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" }, + }; + + static int debugfs_bist_mode_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_hba *hisi_hba = s->private; + int i; + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_modes_v3_hw); i++) { + int match = (hisi_hba->debugfs_bist_mode == + debugfs_loop_modes_v3_hw[i].value); + + seq_printf(s, "%s%s%s ", match ? "[" : "", + debugfs_loop_modes_v3_hw[i].name, + match ? "]" : ""); + } + seq_puts(s, "\n"); + + return 0; + } + + static ssize_t debugfs_bist_mode_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) + { + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + char kbuf[16] = {}, *pkbuf; + bool found = false; + int i; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + if (count >= sizeof(kbuf)) + return -EINVAL; + + if (copy_from_user(kbuf, buf, count)) + return -EOVERFLOW; + + pkbuf = strstrip(kbuf); + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_modes_v3_hw); i++) { + if (!strncmp(debugfs_loop_modes_v3_hw[i].name, pkbuf, 16)) { + hisi_hba->debugfs_bist_mode = + debugfs_loop_modes_v3_hw[i].value; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return count; + } + + static int debugfs_bist_mode_v3_hw_open(struct inode *inode, + struct file *filp) + { + return single_open(filp, debugfs_bist_mode_v3_hw_show, + inode->i_private); + } + + static const struct file_operations debugfs_bist_mode_v3_hw_fops = { + .open = debugfs_bist_mode_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_mode_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, + }; + + static ssize_t debugfs_bist_enable_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) + { + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + unsigned int enable; + int val; + + val = kstrtouint_from_user(buf, count, 0, &enable); + if (val) + return val; + + if (enable > 1) + return -EINVAL; + + if (enable == hisi_hba->debugfs_bist_enable) + return count; + + val = debugfs_set_bist_v3_hw(hisi_hba, enable); + if (val < 0) + return val; + + hisi_hba->debugfs_bist_enable = enable; + + return count; + } + + static int debugfs_bist_enable_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_hba *hisi_hba = s->private; + + seq_printf(s, "%d\n", hisi_hba->debugfs_bist_enable); + + return 0; + } + + static int debugfs_bist_enable_v3_hw_open(struct inode *inode, + struct file *filp) + { + return single_open(filp, debugfs_bist_enable_v3_hw_show, + inode->i_private); + } + + static const struct file_operations debugfs_bist_enable_v3_hw_fops = { + .open = debugfs_bist_enable_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_enable_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, + }; + + static const struct { + char *name; + } debugfs_ffe_name_v3_hw[FFE_CFG_MAX] = { + { "SAS_1_5_GBPS" }, + { "SAS_3_0_GBPS" }, + { "SAS_6_0_GBPS" }, + { "SAS_12_0_GBPS" }, + { "FFE_RESV" }, + { "SATA_1_5_GBPS" }, + { "SATA_3_0_GBPS" }, + { "SATA_6_0_GBPS" }, + }; + + static ssize_t debugfs_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) + { + struct seq_file *m = filp->private_data; + u32 *val = m->private; + int res; + + res = kstrtouint_from_user(buf, count, 0, val); + if (res) + return res; + + return count; + } + + static int debugfs_v3_hw_show(struct seq_file *s, void *p) + { + u32 *val = s->private; + + seq_printf(s, "0x%x\n", *val); + + return 0; + } + + static int debugfs_v3_hw_open(struct inode *inode, struct file *filp) + { + return single_open(filp, debugfs_v3_hw_show, + inode->i_private); + } + + static const struct file_operations debugfs_v3_hw_fops = { + .open = debugfs_v3_hw_open, + .read = seq_read, + .write = debugfs_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, + }; + + static ssize_t debugfs_phy_down_cnt_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) + { + struct seq_file *s = filp->private_data; + struct hisi_sas_phy *phy = s->private; + unsigned int set_val; + int res; + + res = kstrtouint_from_user(buf, count, 0, &set_val); + if (res) + return res; + + if (set_val > 0) + return -EINVAL; + + atomic_set(&phy->down_cnt, 0); + + return count; + } + + static int debugfs_phy_down_cnt_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_phy *phy = s->private; + + seq_printf(s, "%d\n", atomic_read(&phy->down_cnt)); + + return 0; + } + + static int debugfs_phy_down_cnt_v3_hw_open(struct inode *inode, + struct file *filp) + { + return single_open(filp, debugfs_phy_down_cnt_v3_hw_show, + inode->i_private); + } + + static const struct file_operations debugfs_phy_down_cnt_v3_hw_fops = { + .open = debugfs_phy_down_cnt_v3_hw_open, + .read = seq_read, + .write = debugfs_phy_down_cnt_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, + }; + + static void debugfs_work_handler_v3_hw(struct work_struct *work) + { + struct hisi_hba *hisi_hba = + container_of(work, struct hisi_hba, debugfs_work); + int debugfs_dump_index = hisi_hba->debugfs_dump_index; + struct device *dev = hisi_hba->dev; + u64 timestamp = local_clock(); + + if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { + dev_warn(dev, "dump count exceeded!\n"); + return; + } + + do_div(timestamp, NSEC_PER_MSEC); + hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; + + debugfs_snapshot_regs_v3_hw(hisi_hba); + hisi_hba->debugfs_dump_index++; + } + + static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index) + { + struct device *dev = hisi_hba->dev; + int i; + + devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache); + devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache); + devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost); + devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct); + + for (i = 0; i < hisi_hba->queue_count; i++) + devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr); + + for (i = 0; i < hisi_hba->queue_count; i++) + devm_kfree(dev, + hisi_hba->debugfs_cq[dump_index][i].complete_hdr); + + for (i = 0; i < DEBUGFS_REGS_NUM; i++) + devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data); + + for (i = 0; i < hisi_hba->n_phy; i++) + devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data); + } + + static const struct hisi_sas_debugfs_reg *debugfs_reg_array_v3_hw[DEBUGFS_REGS_NUM] = { + [DEBUGFS_GLOBAL] = &debugfs_global_reg, + [DEBUGFS_AXI] = &debugfs_axi_reg, + [DEBUGFS_RAS] = &debugfs_ras_reg, + }; + + static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index) + { + const struct hisi_sas_hw *hw = hisi_hba->hw; + struct device *dev = hisi_hba->dev; + int p, c, d, r, i; + size_t sz; + + for (r = 0; r < DEBUGFS_REGS_NUM; r++) { + struct hisi_sas_debugfs_regs *regs = + &hisi_hba->debugfs_regs[dump_index][r]; + + sz = debugfs_reg_array_v3_hw[r]->count * 4; + regs->data = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!regs->data) + goto fail; + regs->hisi_hba = hisi_hba; + } + + sz = debugfs_port_reg.count * 4; + for (p = 0; p < hisi_hba->n_phy; p++) { + struct hisi_sas_debugfs_port *port = + &hisi_hba->debugfs_port_reg[dump_index][p]; + + port->data = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!port->data) + goto fail; + port->phy = &hisi_hba->phy[p]; + } + + sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; + for (c = 0; c < hisi_hba->queue_count; c++) { + struct hisi_sas_debugfs_cq *cq = + &hisi_hba->debugfs_cq[dump_index][c]; + + cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!cq->complete_hdr) + goto fail; + cq->cq = &hisi_hba->cq[c]; + } + + sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; + for (d = 0; d < hisi_hba->queue_count; d++) { + struct hisi_sas_debugfs_dq *dq = + &hisi_hba->debugfs_dq[dump_index][d]; + + dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!dq->hdr) + goto fail; + dq->dq = &hisi_hba->dq[d]; + } + + sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); + + hisi_hba->debugfs_iost[dump_index].iost = + devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_iost[dump_index].iost) + goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + + hisi_hba->debugfs_iost_cache[dump_index].cache = + devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_iost_cache[dump_index].cache) + goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + + hisi_hba->debugfs_itct_cache[dump_index].cache = + devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_itct_cache[dump_index].cache) + goto fail; + + /* New memory allocation must be locate before itct */ + sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); + + hisi_hba->debugfs_itct[dump_index].itct = + devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_itct[dump_index].itct) + goto fail; + + return 0; + fail: + for (i = 0; i < hisi_sas_debugfs_dump_count; i++) + debugfs_release_v3_hw(hisi_hba, i); + return -ENOMEM; + } + + static void debugfs_phy_down_cnt_init_v3_hw(struct hisi_hba *hisi_hba) + { + struct dentry *dir = debugfs_create_dir("phy_down_cnt", + hisi_hba->debugfs_dir); + char name[16]; + int phy_no; + + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { + snprintf(name, 16, "%d", phy_no); + debugfs_create_file(name, 0600, dir, + &hisi_hba->phy[phy_no], + &debugfs_phy_down_cnt_v3_hw_fops); + } + } + + static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba) + { + struct dentry *ports_dentry; + int phy_no; + + hisi_hba->debugfs_bist_dentry = + debugfs_create_dir("bist", hisi_hba->debugfs_dir); + debugfs_create_file("link_rate", 0600, + hisi_hba->debugfs_bist_dentry, hisi_hba, + &debugfs_bist_linkrate_v3_hw_fops); + + debugfs_create_file("code_mode", 0600, + hisi_hba->debugfs_bist_dentry, hisi_hba, + &debugfs_bist_code_mode_v3_hw_fops); + + debugfs_create_file("fixed_code", 0600, + hisi_hba->debugfs_bist_dentry, + &hisi_hba->debugfs_bist_fixed_code[0], + &debugfs_v3_hw_fops); + + debugfs_create_file("fixed_code_1", 0600, + hisi_hba->debugfs_bist_dentry, + &hisi_hba->debugfs_bist_fixed_code[1], + &debugfs_v3_hw_fops); + + debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, + hisi_hba, &debugfs_bist_phy_v3_hw_fops); + + debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry, + &hisi_hba->debugfs_bist_cnt); + + debugfs_create_file("loopback_mode", 0600, + hisi_hba->debugfs_bist_dentry, + hisi_hba, &debugfs_bist_mode_v3_hw_fops); + + debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry, + hisi_hba, &debugfs_bist_enable_v3_hw_fops); + + ports_dentry = debugfs_create_dir("port", hisi_hba->debugfs_bist_dentry); + + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { + struct dentry *port_dentry; + struct dentry *ffe_dentry; + char name[256]; + int i; + + snprintf(name, 256, "%d", phy_no); + port_dentry = debugfs_create_dir(name, ports_dentry); + ffe_dentry = debugfs_create_dir("ffe", port_dentry); + for (i = 0; i < FFE_CFG_MAX; i++) { + if (i == FFE_RESV) + continue; + debugfs_create_file(debugfs_ffe_name_v3_hw[i].name, + 0600, ffe_dentry, + &hisi_hba->debugfs_bist_ffe[phy_no][i], + &debugfs_v3_hw_fops); + } + } + + hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS; + } + + static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; + int i; + + hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), + hisi_sas_debugfs_dir); + debugfs_create_file("trigger_dump", 0200, + hisi_hba->debugfs_dir, + hisi_hba, + &debugfs_trigger_dump_v3_hw_fops); + + /* create bist structures */ + debugfs_bist_init_v3_hw(hisi_hba); + + hisi_hba->debugfs_dump_dentry = + debugfs_create_dir("dump", hisi_hba->debugfs_dir); + + debugfs_phy_down_cnt_init_v3_hw(hisi_hba); + + for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { + if (debugfs_alloc_v3_hw(hisi_hba, i)) { + debugfs_remove_recursive(hisi_hba->debugfs_dir); + dev_dbg(dev, "failed to init debugfs!\n"); + break; + } + } + } + + static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba) + { + debugfs_remove_recursive(hisi_hba->debugfs_dir); + } + static int hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@@ -3313,21 -4492,21 +4497,21 @@@ }
if (hisi_sas_debugfs_enable) - hisi_sas_debugfs_init(hisi_hba); + debugfs_init_v3_hw(hisi_hba);
rc = interrupt_preinit_v3_hw(hisi_hba); if (rc) - goto err_out_ha; + goto err_out_debugfs; dev_err(dev, "%d hw queues\n", shost->nr_hw_queues); rc = scsi_add_host(shost, dev); if (rc) - goto err_out_ha; + goto err_out_free_irq_vectors;
rc = sas_register_ha(sha); if (rc) goto err_out_register_ha;
- rc = hisi_hba->hw->hw_init(hisi_hba); + rc = hisi_sas_v3_init(hisi_hba); if (rc) goto err_out_register_ha;
@@@ -3348,8 -4527,12 +4532,12 @@@
err_out_register_ha: scsi_remove_host(shost); + err_out_free_irq_vectors: + pci_free_irq_vectors(pdev); + err_out_debugfs: + debugfs_exit_v3_hw(hisi_hba); err_out_ha: - hisi_sas_debugfs_exit(hisi_hba); + hisi_sas_free(hisi_hba); scsi_host_put(shost); err_out_regions: pci_release_regions(pdev); @@@ -3394,7 -4577,7 +4582,7 @@@ static void hisi_sas_v3_remove(struct p pci_release_regions(pdev); pci_disable_device(pdev); hisi_sas_free(hisi_hba); - hisi_sas_debugfs_exit(hisi_hba); + debugfs_exit_v3_hw(hisi_hba); scsi_host_put(shost); }
@@@ -3445,7 -4628,6 +4633,6 @@@ static int _suspend_v3_hw(struct devic struct hisi_hba *hisi_hba = sha->lldd_ha; struct device *dev = hisi_hba->dev; struct Scsi_Host *shost = hisi_hba->shost; - pci_power_t device_state; int rc;
if (!pdev->pm_cap) { @@@ -3471,12 -4653,7 +4658,7 @@@
hisi_sas_init_mem(hisi_hba);
- device_state = pci_choose_state(pdev, PMSG_SUSPEND); - dev_warn(dev, "entering operating state [D%d]\n", - device_state); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, device_state); + dev_warn(dev, "entering suspend state\n");
hisi_sas_release_tasks(hisi_hba);
@@@ -3496,16 -4673,7 +4678,7 @@@ static int _resume_v3_hw(struct device
dev_warn(dev, "resuming from operating state [D%d]\n", device_state); - pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); - pci_restore_state(pdev); - rc = pci_enable_device(pdev); - if (rc) { - dev_err(dev, "enable device failed during resume (%d)\n", rc); - return rc; - }
- pci_set_master(pdev); scsi_unblock_requests(shost); clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
@@@ -3513,17 -4681,16 +4686,16 @@@ rc = hw_init_v3_hw(hisi_hba); if (rc) { scsi_remove_host(shost); - pci_disable_device(pdev); return rc; } - hisi_hba->hw->phys_init(hisi_hba); + phys_init_v3_hw(hisi_hba); sas_resume_ha(sha); clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
return 0; }
- static int suspend_v3_hw(struct device *device) + static int __maybe_unused suspend_v3_hw(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct sas_ha_struct *sha = pci_get_drvdata(pdev); @@@ -3539,7 -4706,7 +4711,7 @@@ return rc; }
- static int resume_v3_hw(struct device *device) + static int __maybe_unused resume_v3_hw(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct sas_ha_struct *sha = pci_get_drvdata(pdev); @@@ -3562,21 -4729,10 +4734,10 @@@ static const struct pci_error_handlers .reset_done = hisi_sas_reset_done_v3_hw, };
- static int runtime_suspend_v3_hw(struct device *dev) - { - return suspend_v3_hw(dev); - } - - static int runtime_resume_v3_hw(struct device *dev) - { - return resume_v3_hw(dev); - } - - static const struct dev_pm_ops hisi_sas_v3_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(suspend_v3_hw, resume_v3_hw) - SET_RUNTIME_PM_OPS(runtime_suspend_v3_hw, - runtime_resume_v3_hw, NULL) - }; + static UNIVERSAL_DEV_PM_OPS(hisi_sas_v3_pm_ops, + suspend_v3_hw, + resume_v3_hw, + NULL);
static struct pci_driver sas_v3_pci_driver = { .name = DRV_NAME, diff --combined drivers/scsi/hpsa.c index 8df70c92911d,353ba9268391..f4d3747cfa0b --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@@ -3881,8 -3881,6 +3881,6 @@@ static unsigned char hpsa_volume_offlin u8 sense_key, asc, ascq; int sense_len; int rc, ldstat = 0; - u16 cmd_status; - u8 scsi_status; #define ASC_LUN_NOT_READY 0x04 #define ASCQ_LUN_NOT_READY_FORMAT_IN_PROGRESS 0x04 #define ASCQ_LUN_NOT_READY_INITIALIZING_CMD_REQ 0x02 @@@ -3902,8 -3900,6 +3900,6 @@@ else sense_len = c->err_info->SenseLen; decode_sense_data(sense, sense_len, &sense_key, &asc, &ascq); - cmd_status = c->err_info->CommandStatus; - scsi_status = c->err_info->ScsiStatus; cmd_free(h, c);
/* Determine the reason for not ready state */ @@@ -4351,7 -4347,7 +4347,7 @@@ static void hpsa_update_scsi_devices(st u32 ndev_allocated = 0; struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice; int ncurrent = 0; - int i, n_ext_target_devs, ndevs_to_allocate; + int i, ndevs_to_allocate; int raid_ctlr_position; bool physical_device; DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS); @@@ -4416,7 -4412,6 +4412,6 @@@ raid_ctlr_position = nphysicals + nlogicals;
/* adjust our table of devices */ - n_ext_target_devs = 0; for (i = 0; i < nphysicals + nlogicals + 1; i++) { u8 *lunaddrbytes, is_OBDR = 0; int rc = 0; @@@ -4580,7 -4575,7 +4575,7 @@@ static int hpsa_scatter_gather(struct c struct scsi_cmnd *cmd) { struct scatterlist *sg; - int use_sg, i, sg_limit, chained, last_sg; + int use_sg, i, sg_limit, chained; struct SGDescriptor *curr_sg;
BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); @@@ -4602,7 -4597,6 +4597,6 @@@ curr_sg = cp->SG; chained = use_sg > h->max_cmd_sg_entries; sg_limit = chained ? h->max_cmd_sg_entries - 1 : use_sg; - last_sg = scsi_sg_count(cmd) - 1; scsi_for_each_sg(cmd, sg, sg_limit, i) { hpsa_set_sg_descriptor(curr_sg, sg); curr_sg++; @@@ -7442,7 -7436,6 +7436,6 @@@ static int find_PCI_BAR_index(struct pc dev_warn(&pdev->dev, "base address is invalid\n"); return -1; - break; } } if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0) @@@ -8636,7 -8629,7 +8629,7 @@@ static struct ctlr_info *hpda_alloc_ctl
static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int dac, rc; + int rc; struct ctlr_info *h; int try_soft_reset = 0; unsigned long flags; @@@ -8712,13 -8705,9 +8705,9 @@@ reinit_after_soft_reset
/* configure PCI DMA stuff */ rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (rc == 0) { - dac = 1; - } else { + if (rc != 0) { rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc == 0) { - dac = 0; - } else { + if (rc != 0) { dev_err(&pdev->dev, "no suitable DMA available\n"); goto clean3; /* shost, pci, lu, aer/h */ } @@@ -8855,7 -8844,7 +8844,7 @@@ /* hook into SCSI subsystem */ rc = hpsa_scsi_add_host(h); if (rc) - goto clean7; /* perf, sg, cmd, irq, shost, pci, lu, aer/h */ + goto clean8; /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */
/* Monitor the controller for firmware lockups */ h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; @@@ -8870,8 -8859,6 +8859,8 @@@ HPSA_EVENT_MONITOR_INTERVAL); return 0;
+clean8: /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */ + kfree(h->lastlogicals); clean7: /* perf, sg, cmd, irq, shost, pci, lu, aer/h */ hpsa_free_performant_mode(h); h->access.set_intr_mask(h, HPSA_INTR_OFF); @@@ -9092,25 -9079,27 +9081,27 @@@ static void hpsa_remove_one(struct pci_ hpda_free_ctlr_info(h); /* init_one 1 */ }
- static int hpsa_suspend(__attribute__((unused)) struct pci_dev *pdev, - __attribute__((unused)) pm_message_t state) + static int __maybe_unused hpsa_suspend( + __attribute__((unused)) struct device *dev) { return -ENOSYS; }
- static int hpsa_resume(__attribute__((unused)) struct pci_dev *pdev) + static int __maybe_unused hpsa_resume + (__attribute__((unused)) struct device *dev) { return -ENOSYS; }
+ static SIMPLE_DEV_PM_OPS(hpsa_pm_ops, hpsa_suspend, hpsa_resume); + static struct pci_driver hpsa_pci_driver = { .name = HPSA, .probe = hpsa_init_one, .remove = hpsa_remove_one, .id_table = hpsa_pci_device_id, /* id_table */ .shutdown = hpsa_shutdown, - .suspend = hpsa_suspend, - .resume = hpsa_resume, + .driver.pm = &hpsa_pm_ops, };
/* Fill in bucket_map[], given nsgs (the max number of @@@ -9299,10 -9288,9 +9290,9 @@@ static int hpsa_enter_performant_mode(s } else if (trans_support & CFGTBL_Trans_io_accel2) { u64 cfg_offset, cfg_base_addr_index; u32 bft2_offset, cfg_base_addr; - int rc;
- rc = hpsa_find_cfg_addrs(h->pdev, h->vaddr, &cfg_base_addr, - &cfg_base_addr_index, &cfg_offset); + hpsa_find_cfg_addrs(h->pdev, h->vaddr, &cfg_base_addr, + &cfg_base_addr_index, &cfg_offset); BUILD_BUG_ON(offsetof(struct io_accel2_cmd, sg) != 64); bft2[15] = h->ioaccel_maxsg + HPSA_IOACCEL2_HEADER_SZ; calc_bucket_map(bft2, ARRAY_SIZE(bft2), h->ioaccel_maxsg, diff --combined drivers/scsi/libiscsi.c index f9314f1393fb,8a4552f09dfe..4e668aafbcca --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@@ -533,8 -533,8 +533,8 @@@ static void iscsi_complete_task(struct if (conn->task == task) conn->task = NULL;
- if (conn->ping_task == task) - conn->ping_task = NULL; + if (READ_ONCE(conn->ping_task) == task) + WRITE_ONCE(conn->ping_task, NULL);
/* release get from queueing */ __iscsi_put_task(task); @@@ -738,9 -738,6 +738,9 @@@ __iscsi_conn_send_pdu(struct iscsi_con task->conn->session->age); }
+ if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK)) + WRITE_ONCE(conn->ping_task, task); + if (!ihost->workq) { if (iscsi_prep_mgmt_task(conn, task)) goto free_task; @@@ -780,7 -777,7 +780,7 @@@ int iscsi_conn_send_pdu(struct iscsi_cl EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
/** - * iscsi_cmd_rsp - SCSI Command Response processing + * iscsi_scsi_cmd_rsp - SCSI Command Response processing * @conn: iscsi connection * @hdr: iscsi header * @task: scsi command task @@@ -944,11 -941,8 +944,11 @@@ static int iscsi_send_nopout(struct isc struct iscsi_nopout hdr; struct iscsi_task *task;
- if (!rhdr && conn->ping_task) - return -EINVAL; + if (!rhdr) { + if (READ_ONCE(conn->ping_task)) + return -EINVAL; + WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK); + }
memset(&hdr, 0, sizeof(struct iscsi_nopout)); hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; @@@ -963,12 -957,11 +963,12 @@@
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); if (!task) { + if (!rhdr) + WRITE_ONCE(conn->ping_task, NULL); iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); return -EIO; } else if (!rhdr) { /* only track our nops */ - conn->ping_task = task; conn->last_ping = jiffies; }
@@@ -991,7 -984,7 +991,7 @@@ static int iscsi_nop_out_rsp(struct isc struct iscsi_conn *conn = task->conn; int rc = 0;
- if (conn->ping_task != task) { + if (READ_ONCE(conn->ping_task) != task) { /* * If this is not in response to one of our * nops then it must be from userspace. @@@ -1930,7 -1923,7 +1930,7 @@@ static void iscsi_start_tx(struct iscsi */ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) { - if (conn->ping_task && + if (READ_ONCE(conn->ping_task) && time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + (conn->ping_timeout * HZ), jiffies)) return 1; @@@ -2065,7 -2058,7 +2065,7 @@@ enum blk_eh_timer_return iscsi_eh_cmd_t * Checking the transport already or nop from a cmd timeout still * running */ - if (conn->ping_task) { + if (READ_ONCE(conn->ping_task)) { task->have_checked_conn = true; rc = BLK_EH_RESET_TIMER; goto done; diff --combined drivers/scsi/megaraid/megaraid_sas_base.c index e158d3d62056,af192096a82b..6e4bf05c6d77 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@@ -37,6 -37,7 +37,6 @@@ #include <linux/poll.h> #include <linux/vmalloc.h> #include <linux/irq_poll.h> -#include <linux/blk-mq-pci.h>
#include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@@ -113,6 -114,10 +113,6 @@@ unsigned int enable_sdev_max_qd module_param(enable_sdev_max_qd, int, 0444); MODULE_PARM_DESC(enable_sdev_max_qd, "Enable sdev max qd as can_queue. Default: 0");
-int host_tagset_enable = 1; -module_param(host_tagset_enable, int, 0444); -MODULE_PARM_DESC(host_tagset_enable, "Shared host tagset enable/disable Default: enable(1)"); - MODULE_LICENSE("GPL"); MODULE_VERSION(MEGASAS_VERSION); MODULE_AUTHOR("megaraidlinux.pdl@broadcom.com"); @@@ -3119,6 -3124,19 +3119,6 @@@ megasas_bios_param(struct scsi_device * return 0; }
-static int megasas_map_queues(struct Scsi_Host *shost) -{ - struct megasas_instance *instance; - - instance = (struct megasas_instance *)shost->hostdata; - - if (shost->nr_hw_queues == 1) - return 0; - - return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT], - instance->pdev, instance->low_latency_index_start); -} - static void megasas_aen_polling(struct work_struct *work);
/** @@@ -3427,6 -3445,7 +3427,6 @@@ static struct scsi_host_template megasa .eh_timed_out = megasas_reset_timer, .shost_attrs = megaraid_host_attrs, .bios_param = megasas_bios_param, - .map_queues = megasas_map_queues, .change_queue_depth = scsi_change_queue_depth, .max_segment_size = 0xffffffff, }; @@@ -6808,6 -6827,26 +6808,6 @@@ static int megasas_io_attach(struct meg host->max_lun = MEGASAS_MAX_LUN; host->max_cmd_len = 16;
- /* Use shared host tagset only for fusion adaptors - * if there are managed interrupts (smp affinity enabled case). - * Single msix_vectors in kdump, so shared host tag is also disabled. - */ - - host->host_tagset = 0; - host->nr_hw_queues = 1; - - if ((instance->adapter_type != MFI_SERIES) && - (instance->msix_vectors > instance->low_latency_index_start) && - host_tagset_enable && - instance->smp_affinity_enable) { - host->host_tagset = 1; - host->nr_hw_queues = instance->msix_vectors - - instance->low_latency_index_start; - } - - dev_info(&instance->pdev->dev, - "Max firmware commands: %d shared with nr_hw_queues = %d\n", - instance->max_fw_cmds, host->nr_hw_queues); /* * Notify the mid-layer about the new controller */ @@@ -7554,25 -7593,23 +7554,23 @@@ static void megasas_shutdown_controller megasas_return_cmd(instance, cmd); }
- #ifdef CONFIG_PM /** * megasas_suspend - driver suspend entry point - * @pdev: PCI device structure - * @state: PCI power state to suspend routine + * @dev: Device structure */ - static int - megasas_suspend(struct pci_dev *pdev, pm_message_t state) + static int __maybe_unused + megasas_suspend(struct device *dev) { struct megasas_instance *instance;
- instance = pci_get_drvdata(pdev); + instance = dev_get_drvdata(dev);
if (!instance) return 0;
instance->unload = 1;
- dev_info(&pdev->dev, "%s is called\n", __func__); + dev_info(dev, "%s is called\n", __func__);
/* Shutdown SR-IOV heartbeat timer */ if (instance->requestorId && !instance->skip_heartbeat_timer_del) @@@ -7602,48 -7639,29 +7600,29 @@@ if (instance->msix_vectors) pci_free_irq_vectors(instance->pdev);
- pci_save_state(pdev); - pci_disable_device(pdev); - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; }
/** * megasas_resume- driver resume entry point - * @pdev: PCI device structure + * @dev: Device structure */ - static int - megasas_resume(struct pci_dev *pdev) + static int __maybe_unused + megasas_resume(struct device *dev) { int rval; struct Scsi_Host *host; struct megasas_instance *instance; u32 status_reg;
- instance = pci_get_drvdata(pdev); + instance = dev_get_drvdata(dev);
if (!instance) return 0;
host = instance->host; - pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); - pci_restore_state(pdev); - - dev_info(&pdev->dev, "%s is called\n", __func__); - /* - * PCI prepping: enable device set bus mastering and dma mask - */ - rval = pci_enable_device_mem(pdev);
- if (rval) { - dev_err(&pdev->dev, "Enable device failed\n"); - return rval; - } - - pci_set_master(pdev); + dev_info(dev, "%s is called\n", __func__);
/* * We expect the FW state to be READY @@@ -7769,14 -7787,8 +7748,8 @@@ fail_reenable_msix fail_set_dma_mask: fail_ready_state:
- pci_disable_device(pdev); - return -ENODEV; } - #else - #define megasas_suspend NULL - #define megasas_resume NULL - #endif
static inline int megasas_wait_for_adapter_operational(struct megasas_instance *instance) @@@ -7946,7 -7958,7 +7919,7 @@@ skip_firing_dcmds
/** * megasas_shutdown - Shutdown entry point - * @pdev: Generic device structure + * @pdev: PCI device structure */ static void megasas_shutdown(struct pci_dev *pdev) { @@@ -8095,7 -8107,7 +8068,7 @@@ megasas_mgmt_fw_ioctl(struct megasas_in int error = 0, i; void *sense = NULL; dma_addr_t sense_handle; - unsigned long *sense_ptr; + void *sense_ptr; u32 opcode = 0; int ret = DCMD_SUCCESS;
@@@ -8218,6 -8230,13 +8191,13 @@@ }
if (ioc->sense_len) { + /* make sure the pointer is part of the frame */ + if (ioc->sense_off > + (sizeof(union megasas_frame) - sizeof(__le64))) { + error = -EINVAL; + goto out; + } + sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len, &sense_handle, GFP_KERNEL); if (!sense) { @@@ -8225,12 -8244,11 +8205,11 @@@ goto out; }
- sense_ptr = - (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); + sense_ptr = (void *)cmd->frame + ioc->sense_off; if (instance->consistent_mask_64bit) - *sense_ptr = cpu_to_le64(sense_handle); + put_unaligned_le64(sense_handle, sense_ptr); else - *sense_ptr = cpu_to_le32(sense_handle); + put_unaligned_le32(sense_handle, sense_ptr); }
/* @@@ -8274,16 -8292,19 +8253,19 @@@ * copy out the sense */ if (ioc->sense_len) { + void __user *uptr; /* * sense_ptr points to the location that has the user * sense buffer address */ - sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw + - ioc->sense_off); + sense_ptr = (void *)ioc->frame.raw + ioc->sense_off; + if (in_compat_syscall()) + uptr = compat_ptr(get_unaligned((compat_uptr_t *) + sense_ptr)); + else + uptr = get_unaligned((void __user **)sense_ptr);
- if (copy_to_user((void __user *)((unsigned long) - get_unaligned((unsigned long *)sense_ptr)), - sense, ioc->sense_len)) { + if (copy_to_user(uptr, sense, ioc->sense_len)) { dev_err(&instance->pdev->dev, "Failed to copy out to user " "sense data\n"); error = -EFAULT; @@@ -8326,6 -8347,38 +8308,38 @@@ out return error; }
+ static struct megasas_iocpacket * + megasas_compat_iocpacket_get_user(void __user *arg) + { + struct megasas_iocpacket *ioc; + struct compat_megasas_iocpacket __user *cioc = arg; + size_t size; + int err = -EFAULT; + int i; + + ioc = kzalloc(sizeof(*ioc), GFP_KERNEL); + if (!ioc) + return ERR_PTR(-ENOMEM); + size = offsetof(struct megasas_iocpacket, frame) + sizeof(ioc->frame); + if (copy_from_user(ioc, arg, size)) + goto out; + + for (i = 0; i < MAX_IOCTL_SGE; i++) { + compat_uptr_t iov_base; + + if (get_user(iov_base, &cioc->sgl[i].iov_base) || + get_user(ioc->sgl[i].iov_len, &cioc->sgl[i].iov_len)) + goto out; + + ioc->sgl[i].iov_base = compat_ptr(iov_base); + } + + return ioc; + out: + kfree(ioc); + return ERR_PTR(err); + } + static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) { struct megasas_iocpacket __user *user_ioc = @@@ -8334,7 -8387,11 +8348,11 @@@ struct megasas_instance *instance; int error;
- ioc = memdup_user(user_ioc, sizeof(*ioc)); + if (in_compat_syscall()) + ioc = megasas_compat_iocpacket_get_user(user_ioc); + else + ioc = memdup_user(user_ioc, sizeof(struct megasas_iocpacket)); + if (IS_ERR(ioc)) return PTR_ERR(ioc);
@@@ -8439,78 -8496,13 +8457,13 @@@ megasas_mgmt_ioctl(struct file *file, u }
#ifdef CONFIG_COMPAT - static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) - { - struct compat_megasas_iocpacket __user *cioc = - (struct compat_megasas_iocpacket __user *)arg; - struct megasas_iocpacket __user *ioc = - compat_alloc_user_space(sizeof(struct megasas_iocpacket)); - int i; - int error = 0; - compat_uptr_t ptr; - u32 local_sense_off; - u32 local_sense_len; - u32 user_sense_off; - - if (clear_user(ioc, sizeof(*ioc))) - return -EFAULT; - - if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) || - copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) || - copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) || - copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) || - copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) || - copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) - return -EFAULT; - - /* - * The sense_ptr is used in megasas_mgmt_fw_ioctl only when - * sense_len is not null, so prepare the 64bit value under - * the same condition. - */ - if (get_user(local_sense_off, &ioc->sense_off) || - get_user(local_sense_len, &ioc->sense_len) || - get_user(user_sense_off, &cioc->sense_off)) - return -EFAULT; - - if (local_sense_off != user_sense_off) - return -EINVAL; - - if (local_sense_len) { - void __user **sense_ioc_ptr = - (void __user **)((u8 *)((unsigned long)&ioc->frame.raw) + local_sense_off); - compat_uptr_t *sense_cioc_ptr = - (compat_uptr_t *)(((unsigned long)&cioc->frame.raw) + user_sense_off); - if (get_user(ptr, sense_cioc_ptr) || - put_user(compat_ptr(ptr), sense_ioc_ptr)) - return -EFAULT; - } - - for (i = 0; i < MAX_IOCTL_SGE; i++) { - if (get_user(ptr, &cioc->sgl[i].iov_base) || - put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || - copy_in_user(&ioc->sgl[i].iov_len, - &cioc->sgl[i].iov_len, sizeof(compat_size_t))) - return -EFAULT; - } - - error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc); - - if (copy_in_user(&cioc->frame.hdr.cmd_status, - &ioc->frame.hdr.cmd_status, sizeof(u8))) { - printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n"); - return -EFAULT; - } - return error; - } - static long megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case MEGASAS_IOC_FIRMWARE32: - return megasas_mgmt_compat_ioctl_fw(file, arg); + return megasas_mgmt_ioctl_fw(file, arg); case MEGASAS_IOC_GET_AEN: return megasas_mgmt_ioctl_aen(file, arg); } @@@ -8534,6 -8526,8 +8487,8 @@@ static const struct file_operations meg .llseek = noop_llseek, };
+ static SIMPLE_DEV_PM_OPS(megasas_pm_ops, megasas_suspend, megasas_resume); + /* * PCI hotplug support registration structure */ @@@ -8543,8 -8537,7 +8498,7 @@@ static struct pci_driver megasas_pci_dr .id_table = megasas_pci_table, .probe = megasas_probe_one, .remove = megasas_detach_one, - .suspend = megasas_suspend, - .resume = megasas_resume, + .driver.pm = &megasas_pm_ops, .shutdown = megasas_shutdown, };
diff --combined drivers/scsi/mpt3sas/mpt3sas_base.c index bb940cbcbb5d,b129f3734ed0..969baf4cd3f5 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@@ -596,6 -596,71 +596,71 @@@ static int mpt3sas_remove_dead_ioc_func return 0; }
+ /** + * _base_sync_drv_fw_timestamp - Sync Drive-Fw TimeStamp. + * @ioc: Per Adapter Object + * + * Return nothing. + */ + static void _base_sync_drv_fw_timestamp(struct MPT3SAS_ADAPTER *ioc) + { + Mpi26IoUnitControlRequest_t *mpi_request; + Mpi26IoUnitControlReply_t *mpi_reply; + u16 smid; + ktime_t current_time; + u64 TimeStamp = 0; + u8 issue_reset = 0; + + mutex_lock(&ioc->scsih_cmds.mutex); + if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) { + ioc_err(ioc, "scsih_cmd in use %s\n", __func__); + goto out; + } + ioc->scsih_cmds.status = MPT3_CMD_PENDING; + smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx); + if (!smid) { + ioc_err(ioc, "Failed obtaining a smid %s\n", __func__); + ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; + goto out; + } + mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); + ioc->scsih_cmds.smid = smid; + memset(mpi_request, 0, sizeof(Mpi26IoUnitControlRequest_t)); + mpi_request->Function = MPI2_FUNCTION_IO_UNIT_CONTROL; + mpi_request->Operation = MPI26_CTRL_OP_SET_IOC_PARAMETER; + mpi_request->IOCParameter = MPI26_SET_IOC_PARAMETER_SYNC_TIMESTAMP; + current_time = ktime_get_real(); + TimeStamp = ktime_to_ms(current_time); + mpi_request->Reserved7 = cpu_to_le32(TimeStamp & 0xFFFFFFFF); + mpi_request->IOCParameterValue = cpu_to_le32(TimeStamp >> 32); + init_completion(&ioc->scsih_cmds.done); + ioc->put_smid_default(ioc, smid); + dinitprintk(ioc, ioc_info(ioc, + "Io Unit Control Sync TimeStamp (sending), @time %lld ms\n", + TimeStamp)); + wait_for_completion_timeout(&ioc->scsih_cmds.done, + MPT3SAS_TIMESYNC_TIMEOUT_SECONDS*HZ); + if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { + mpt3sas_check_cmd_timeout(ioc, + ioc->scsih_cmds.status, mpi_request, + sizeof(Mpi2SasIoUnitControlRequest_t)/4, issue_reset); + goto issue_host_reset; + } + if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) { + mpi_reply = ioc->scsih_cmds.reply; + dinitprintk(ioc, ioc_info(ioc, + "Io Unit Control sync timestamp (complete): ioc_status(0x%04x), loginfo(0x%08x)\n", + le16_to_cpu(mpi_reply->IOCStatus), + le32_to_cpu(mpi_reply->IOCLogInfo))); + } + issue_host_reset: + if (issue_reset) + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); + ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; + out: + mutex_unlock(&ioc->scsih_cmds.mutex); + } + /** * _base_fault_reset_work - workq handling ioc fault conditions * @work: input argument, used to derive ioc @@@ -720,7 -785,11 +785,11 @@@ _base_fault_reset_work(struct work_stru return; /* don't rearm timer */ } ioc->ioc_coredump_loop = 0; - + if (ioc->time_sync_interval && + ++ioc->timestamp_update_count >= ioc->time_sync_interval) { + ioc->timestamp_update_count = 0; + _base_sync_drv_fw_timestamp(ioc); + } spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); rearm_timer: if (ioc->fault_reset_work_q) @@@ -744,6 -813,7 +813,7 @@@ mpt3sas_base_start_watchdog(struct MPT3 if (ioc->fault_reset_work_q) return;
+ ioc->timestamp_update_count = 0; /* initialize fault polling */
INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); @@@ -905,6 -975,20 +975,20 @@@ _base_sas_ioc_info(struct MPT3SAS_ADAPT
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) return; + /* + * Older Firmware version doesn't support driver trigger pages. + * So, skip displaying 'config invalid type' type + * of error message. + */ + if (request_hdr->Function == MPI2_FUNCTION_CONFIG) { + Mpi2ConfigRequest_t *rqst = (Mpi2ConfigRequest_t *)request_hdr; + + if ((rqst->ExtPageType == + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER) && + !(ioc->logging_level & MPT_DEBUG_CONFIG)) { + return; + } + }
switch (ioc_status) {
@@@ -1740,13 -1824,6 +1824,13 @@@ _base_irqpoll(struct irq_poll *irqpoll reply_q->irq_poll_scheduled = false; reply_q->irq_line_enable = true; enable_irq(reply_q->os_irq); + /* + * Go for one more round of processing the + * reply descriptor post queue incase if HBA + * Firmware has posted some reply descriptors + * while reenabling the IRQ. + */ + _base_process_reply_queue(reply_q); }
return num_entries; @@@ -4720,6 -4797,311 +4804,311 @@@ _base_update_ioc_page1_inlinewith_perf_ } }
+ /** + * _base_get_event_diag_triggers - get event diag trigger values from + * persistent pages + * @ioc : per adapter object + * + * Return nothing. + */ + static void + _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc) + { + Mpi26DriverTriggerPage2_t trigger_pg2; + struct SL_WH_EVENT_TRIGGER_T *event_tg; + MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY *mpi_event_tg; + Mpi2ConfigReply_t mpi_reply; + int r = 0, i = 0; + u16 count = 0; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, + &trigger_pg2); + if (r) + return; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dinitprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return; + } + + if (le16_to_cpu(trigger_pg2.NumMPIEventTrigger)) { + count = le16_to_cpu(trigger_pg2.NumMPIEventTrigger); + count = min_t(u16, NUM_VALID_ENTRIES, count); + ioc->diag_trigger_event.ValidEntries = count; + + event_tg = &ioc->diag_trigger_event.EventTriggerEntry[0]; + mpi_event_tg = &trigger_pg2.MPIEventTriggers[0]; + for (i = 0; i < count; i++) { + event_tg->EventValue = le16_to_cpu( + mpi_event_tg->MPIEventCode); + event_tg->LogEntryQualifier = le16_to_cpu( + mpi_event_tg->MPIEventCodeSpecific); + event_tg++; + mpi_event_tg++; + } + } + } + + /** + * _base_get_scsi_diag_triggers - get scsi diag trigger values from + * persistent pages + * @ioc : per adapter object + * + * Return nothing. + */ + static void + _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) + { + Mpi26DriverTriggerPage3_t trigger_pg3; + struct SL_WH_SCSI_TRIGGER_T *scsi_tg; + MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY *mpi_scsi_tg; + Mpi2ConfigReply_t mpi_reply; + int r = 0, i = 0; + u16 count = 0; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, + &trigger_pg3); + if (r) + return; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dinitprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return; + } + + if (le16_to_cpu(trigger_pg3.NumSCSISenseTrigger)) { + count = le16_to_cpu(trigger_pg3.NumSCSISenseTrigger); + count = min_t(u16, NUM_VALID_ENTRIES, count); + ioc->diag_trigger_scsi.ValidEntries = count; + + scsi_tg = &ioc->diag_trigger_scsi.SCSITriggerEntry[0]; + mpi_scsi_tg = &trigger_pg3.SCSISenseTriggers[0]; + for (i = 0; i < count; i++) { + scsi_tg->ASCQ = mpi_scsi_tg->ASCQ; + scsi_tg->ASC = mpi_scsi_tg->ASC; + scsi_tg->SenseKey = mpi_scsi_tg->SenseKey; + + scsi_tg++; + mpi_scsi_tg++; + } + } + } + + /** + * _base_get_mpi_diag_triggers - get mpi diag trigger values from + * persistent pages + * @ioc : per adapter object + * + * Return nothing. + */ + static void + _base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) + { + Mpi26DriverTriggerPage4_t trigger_pg4; + struct SL_WH_MPI_TRIGGER_T *status_tg; + MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY *mpi_status_tg; + Mpi2ConfigReply_t mpi_reply; + int r = 0, i = 0; + u16 count = 0; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, + &trigger_pg4); + if (r) + return; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dinitprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return; + } + + if (le16_to_cpu(trigger_pg4.NumIOCStatusLogInfoTrigger)) { + count = le16_to_cpu(trigger_pg4.NumIOCStatusLogInfoTrigger); + count = min_t(u16, NUM_VALID_ENTRIES, count); + ioc->diag_trigger_mpi.ValidEntries = count; + + status_tg = &ioc->diag_trigger_mpi.MPITriggerEntry[0]; + mpi_status_tg = &trigger_pg4.IOCStatusLoginfoTriggers[0]; + + for (i = 0; i < count; i++) { + status_tg->IOCStatus = le16_to_cpu( + mpi_status_tg->IOCStatus); + status_tg->IocLogInfo = le32_to_cpu( + mpi_status_tg->LogInfo); + + status_tg++; + mpi_status_tg++; + } + } + } + + /** + * _base_get_master_diag_triggers - get master diag trigger values from + * persistent pages + * @ioc : per adapter object + * + * Return nothing. + */ + static void + _base_get_master_diag_triggers(struct MPT3SAS_ADAPTER *ioc) + { + Mpi26DriverTriggerPage1_t trigger_pg1; + Mpi2ConfigReply_t mpi_reply; + int r; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, + &trigger_pg1); + if (r) + return; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dinitprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return; + } + + if (le16_to_cpu(trigger_pg1.NumMasterTrigger)) + ioc->diag_trigger_master.MasterData |= + le32_to_cpu( + trigger_pg1.MasterTriggers[0].MasterTriggerFlags); + } + + /** + * _base_check_for_trigger_pages_support - checks whether HBA FW supports + * driver trigger pages or not + * @ioc : per adapter object + * + * Returns trigger flags mask if HBA FW supports driver trigger pages, + * otherwise returns EFAULT. + */ + static int + _base_check_for_trigger_pages_support(struct MPT3SAS_ADAPTER *ioc) + { + Mpi26DriverTriggerPage0_t trigger_pg0; + int r = 0; + Mpi2ConfigReply_t mpi_reply; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, + &trigger_pg0); + if (r) + return -EFAULT; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) + return -EFAULT; + + return le16_to_cpu(trigger_pg0.TriggerFlags); + } + + /** + * _base_get_diag_triggers - Retrieve diag trigger values from + * persistent pages. + * @ioc : per adapter object + * + * Return nothing. + */ + static void + _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) + { + u16 trigger_flags; + + /* + * Default setting of master trigger. + */ + ioc->diag_trigger_master.MasterData = + (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET); + + trigger_flags = _base_check_for_trigger_pages_support(ioc); + if (trigger_flags < 0) + return; + + ioc->supports_trigger_pages = 1; + + /* + * Retrieve master diag trigger values from driver trigger pg1 + * if master trigger bit enabled in TriggerFlags. + */ + if ((u16)trigger_flags & + MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID) + _base_get_master_diag_triggers(ioc); + + /* + * Retrieve event diag trigger values from driver trigger pg2 + * if event trigger bit enabled in TriggerFlags. + */ + if ((u16)trigger_flags & + MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID) + _base_get_event_diag_triggers(ioc); + + /* + * Retrieve scsi diag trigger values from driver trigger pg3 + * if scsi trigger bit enabled in TriggerFlags. + */ + if ((u16)trigger_flags & + MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID) + _base_get_scsi_diag_triggers(ioc); + /* + * Retrieve mpi error diag trigger values from driver trigger pg4 + * if loginfo trigger bit enabled in TriggerFlags. + */ + if ((u16)trigger_flags & + MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID) + _base_get_mpi_diag_triggers(ioc); + } + + /** + * _base_update_diag_trigger_pages - Update the driver trigger pages after + * online FW update, incase updated FW supports driver + * trigger pages. + * @ioc : per adapter object + * + * Return nothing. + */ + static void + _base_update_diag_trigger_pages(struct MPT3SAS_ADAPTER *ioc) + { + + if (ioc->diag_trigger_master.MasterData) + mpt3sas_config_update_driver_trigger_pg1(ioc, + &ioc->diag_trigger_master, 1); + + if (ioc->diag_trigger_event.ValidEntries) + mpt3sas_config_update_driver_trigger_pg2(ioc, + &ioc->diag_trigger_event, 1); + + if (ioc->diag_trigger_scsi.ValidEntries) + mpt3sas_config_update_driver_trigger_pg3(ioc, + &ioc->diag_trigger_scsi, 1); + + if (ioc->diag_trigger_mpi.ValidEntries) + mpt3sas_config_update_driver_trigger_pg4(ioc, + &ioc->diag_trigger_mpi, 1); + } + /** * _base_static_config_pages - static start of day config pages * @ioc: per adapter object @@@ -4729,7 -5111,7 +5118,7 @@@ _base_static_config_pages(struct MPT3SA { Mpi2ConfigReply_t mpi_reply; u32 iounit_pg1_flags; - + int tg_flags = 0; ioc->nvme_abort_timeout = 30; mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); if (ioc->ir_firmware) @@@ -4761,7 -5143,24 +5150,24 @@@ else ioc->nvme_abort_timeout = ioc->manu_pg11.NVMeAbortTO; } - + ioc->time_sync_interval = + ioc->manu_pg11.TimeSyncInterval & MPT3SAS_TIMESYNC_MASK; + if (ioc->time_sync_interval) { + if (ioc->manu_pg11.TimeSyncInterval & MPT3SAS_TIMESYNC_UNIT_MASK) + ioc->time_sync_interval = + ioc->time_sync_interval * SECONDS_PER_HOUR; + else + ioc->time_sync_interval = + ioc->time_sync_interval * SECONDS_PER_MIN; + dinitprintk(ioc, ioc_info(ioc, + "Driver-FW TimeSync interval is %d seconds. ManuPg11 TimeSync Unit is in %s\n", + ioc->time_sync_interval, (ioc->manu_pg11.TimeSyncInterval & + MPT3SAS_TIMESYNC_UNIT_MASK) ? "Hour" : "Minute")); + } else { + if (ioc->is_gen35_ioc) + ioc_warn(ioc, + "TimeSync Interval in Manuf page-11 is not enabled. Periodic Time-Sync will be disabled\n"); + } mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); @@@ -4789,6 -5188,29 +5195,29 @@@ ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors; if (ioc->is_aero_ioc) _base_update_ioc_page1_inlinewith_perf_mode(ioc); + if (ioc->is_gen35_ioc) { + if (ioc->is_driver_loading) + _base_get_diag_triggers(ioc); + else { + /* + * In case of online HBA FW update operation, + * check whether updated FW supports the driver trigger + * pages or not. + * - If previous FW has not supported driver trigger + * pages and newer FW supports them then update these + * pages with current diag trigger values. + * - If previous FW has supported driver trigger pages + * and new FW doesn't support them then disable + * support_trigger_pages flag. + */ + tg_flags = _base_check_for_trigger_pages_support(ioc); + if (!ioc->supports_trigger_pages && tg_flags != -EFAULT) + _base_update_diag_trigger_pages(ioc); + else if (ioc->supports_trigger_pages && + tg_flags == -EFAULT) + ioc->supports_trigger_pages = 0; + } + } }
/** @@@ -6459,7 -6881,7 +6888,7 @@@ _base_send_ioc_init(struct MPT3SAS_ADAP
r = _base_handshake_req_reply_wait(ioc, sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request, - sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10); + sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 30);
if (r != 0) { ioc_err(ioc, "%s: handshake failed (r=%d)\n", __func__, r); @@@ -6473,6 -6895,8 +6902,8 @@@ r = -EIO; }
+ /* Reset TimeSync Counter*/ + ioc->timestamp_update_count = 0; return r; }
diff --combined drivers/scsi/mpt3sas/mpt3sas_ctl.c index edd26a2570fa,b21aa55768ae..c8a0ce18f2c5 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@@ -664,7 -664,7 +664,7 @@@ _ctl_do_mpt_command(struct MPT3SAS_ADAP Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL; struct _pcie_device *pcie_device = NULL; u16 smid; - u8 timeout; + unsigned long timeout; u8 issue_reset; u32 sz, sz_arg; void *psge; @@@ -902,8 -902,10 +902,10 @@@ (Mpi2SmpPassthroughRequest_t *)mpi_request; u8 *data;
- /* ioc determines which port to use */ - smp_request->PhysicalPort = 0xFF; + if (!ioc->multipath_on_hba) { + /* ioc determines which port to use */ + smp_request->PhysicalPort = 0xFF; + } if (smp_request->PassthroughFlags & MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE) data = (u8 *)&smp_request->SGL; diff --combined drivers/scsi/qla2xxx/qla_tmpl.c index bd8623ee156a,a6bb1c0e2245..26c13a953b97 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@@ -928,7 -928,8 +928,8 @@@ qla27xx_template_checksum(void *p, ulon static inline int qla27xx_verify_template_checksum(struct qla27xx_fwdt_template *tmp) { - return qla27xx_template_checksum(tmp, tmp->template_size) == 0; + return qla27xx_template_checksum(tmp, + le32_to_cpu(tmp->template_size)) == 0; }
static inline int @@@ -944,7 -945,7 +945,7 @@@ qla27xx_execute_fwdt_template(struct sc ulong len = 0;
if (qla27xx_fwdt_template_valid(tmp)) { - len = tmp->template_size; + len = le32_to_cpu(tmp->template_size); tmp = memcpy(buf, tmp, len); ql27xx_edit_template(vha, tmp); qla27xx_walk_template(vha, tmp, buf, &len); @@@ -960,7 -961,7 +961,7 @@@ qla27xx_fwdt_calculate_dump_size(struc ulong len = 0;
if (qla27xx_fwdt_template_valid(tmp)) { - len = tmp->template_size; + len = le32_to_cpu(tmp->template_size); qla27xx_walk_template(vha, tmp, NULL, &len); }
@@@ -972,7 -973,7 +973,7 @@@ qla27xx_fwdt_template_size(void *p { struct qla27xx_fwdt_template *tmp = p;
- return tmp->template_size; + return le32_to_cpu(tmp->template_size); }
int @@@ -1001,8 -1002,10 +1002,8 @@@ qla27xx_mpi_fwdump(scsi_qla_host_t *vha { ulong flags = 0;
-#ifndef __CHECKER__ if (!hardware_locked) spin_lock_irqsave(&vha->hw->hardware_lock, flags); -#endif if (!vha->hw->mpi_fw_dump) { ql_log(ql_log_warn, vha, 0x02f3, "-> mpi_fwdump no buffer\n"); } else { @@@ -1048,8 -1051,10 +1049,8 @@@ }
bailout: -#ifndef __CHECKER__ if (!hardware_locked) spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); -#endif }
void diff --combined drivers/scsi/scsi_lib.c index 03c6d0620bfd,b7ac14571415..4848ae3c7b56 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@@ -766,6 -766,9 +766,9 @@@ static void scsi_io_completion_action(s case 0x24: /* depopulation in progress */ action = ACTION_DELAYED_RETRY; break; + case 0x0a: /* ALUA state transition */ + blk_stat = BLK_STS_AGAIN; + fallthrough; default: action = ACTION_FAIL; break; @@@ -1455,7 -1458,7 +1458,7 @@@ static void scsi_softirq_done(struct re }
/** - * scsi_dispatch_command - Dispatch a command to the low-level driver. + * scsi_dispatch_cmd - Dispatch a command to the low-level driver. * @cmd: command block we are dispatching. * * Return: nonzero return request was rejected and device's queue needs to be @@@ -1703,9 -1706,15 +1706,14 @@@ out_put_budget break; case BLK_STS_RESOURCE: case BLK_STS_ZONE_RESOURCE: - if (atomic_read(&sdev->device_busy) || - scsi_device_blocked(sdev)) + if (scsi_device_blocked(sdev)) ret = BLK_STS_DEV_RESOURCE; break; + case BLK_STS_AGAIN: + scsi_req(req)->result = DID_BUS_BUSY << 16; + if (req->rq_flags & RQF_DONTPREP) + scsi_mq_uninit_cmd(cmd); + break; default: if (unlikely(!scsi_device_online(sdev))) scsi_req(req)->result = DID_NO_CONNECT << 16; @@@ -2334,7 -2343,7 +2342,7 @@@ scsi_device_set_state(struct scsi_devic EXPORT_SYMBOL(scsi_device_set_state);
/** - * sdev_evt_emit - emit a single SCSI device uevent + * scsi_evt_emit - emit a single SCSI device uevent * @sdev: associated SCSI device * @evt: event to emit * @@@ -2382,7 -2391,7 +2390,7 @@@ static void scsi_evt_emit(struct scsi_d }
/** - * sdev_evt_thread - send a uevent for each scsi event + * scsi_evt_thread - send a uevent for each scsi event * @work: work struct for scsi_device * * Dispatch queued events to their associated scsi_device kobjects @@@ -2948,6 -2957,78 +2956,78 @@@ void sdev_enable_disk_events(struct scs } EXPORT_SYMBOL(sdev_enable_disk_events);
+ static unsigned char designator_prio(const unsigned char *d) + { + if (d[1] & 0x30) + /* not associated with LUN */ + return 0; + + if (d[3] == 0) + /* invalid length */ + return 0; + + /* + * Order of preference for lun descriptor: + * - SCSI name string + * - NAA IEEE Registered Extended + * - EUI-64 based 16-byte + * - EUI-64 based 12-byte + * - NAA IEEE Registered + * - NAA IEEE Extended + * - EUI-64 based 8-byte + * - SCSI name string (truncated) + * - T10 Vendor ID + * as longer descriptors reduce the likelyhood + * of identification clashes. + */ + + switch (d[1] & 0xf) { + case 8: + /* SCSI name string, variable-length UTF-8 */ + return 9; + case 3: + switch (d[4] >> 4) { + case 6: + /* NAA registered extended */ + return 8; + case 5: + /* NAA registered */ + return 5; + case 4: + /* NAA extended */ + return 4; + case 3: + /* NAA locally assigned */ + return 1; + default: + break; + } + break; + case 2: + switch (d[3]) { + case 16: + /* EUI64-based, 16 byte */ + return 7; + case 12: + /* EUI64-based, 12 byte */ + return 6; + case 8: + /* EUI64-based, 8 byte */ + return 3; + default: + break; + } + break; + case 1: + /* T10 vendor ID */ + return 1; + default: + break; + } + + return 0; + } + /** * scsi_vpd_lun_id - return a unique device identification * @sdev: SCSI device @@@ -2964,7 -3045,7 +3044,7 @@@ */ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) { - u8 cur_id_type = 0xff; + u8 cur_id_prio = 0; u8 cur_id_size = 0; const unsigned char *d, *cur_id_str; const struct scsi_vpd *vpd_pg83; @@@ -2977,20 -3058,6 +3057,6 @@@ return -ENXIO; }
- /* - * Look for the correct descriptor. - * Order of preference for lun descriptor: - * - SCSI name string - * - NAA IEEE Registered Extended - * - EUI-64 based 16-byte - * - EUI-64 based 12-byte - * - NAA IEEE Registered - * - NAA IEEE Extended - * - T10 Vendor ID - * as longer descriptors reduce the likelyhood - * of identification clashes. - */ - /* The id string must be at least 20 bytes + terminating NULL byte */ if (id_len < 21) { rcu_read_unlock(); @@@ -2998,39 -3065,32 +3064,32 @@@ }
memset(id, 0, id_len); - d = vpd_pg83->data + 4; - while (d < vpd_pg83->data + vpd_pg83->len) { - /* Skip designators not referring to the LUN */ - if ((d[1] & 0x30) != 0x00) - goto next_desig; + for (d = vpd_pg83->data + 4; + d < vpd_pg83->data + vpd_pg83->len; + d += d[3] + 4) { + u8 prio = designator_prio(d); + + if (prio == 0 || cur_id_prio > prio) + continue;
switch (d[1] & 0xf) { case 0x1: /* T10 Vendor ID */ if (cur_id_size > d[3]) break; - /* Prefer anything */ - if (cur_id_type > 0x01 && cur_id_type != 0xff) - break; + cur_id_prio = prio; cur_id_size = d[3]; if (cur_id_size + 4 > id_len) cur_id_size = id_len - 4; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; id_size = snprintf(id, id_len, "t10.%*pE", cur_id_size, cur_id_str); break; case 0x2: /* EUI-64 */ - if (cur_id_size > d[3]) - break; - /* Prefer NAA IEEE Registered Extended */ - if (cur_id_type == 0x3 && - cur_id_size == d[3]) - break; + cur_id_prio = prio; cur_id_size = d[3]; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; switch (cur_id_size) { case 8: id_size = snprintf(id, id_len, @@@ -3048,17 -3108,14 +3107,14 @@@ cur_id_str); break; default: - cur_id_size = 0; break; } break; case 0x3: /* NAA */ - if (cur_id_size > d[3]) - break; + cur_id_prio = prio; cur_id_size = d[3]; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; switch (cur_id_size) { case 8: id_size = snprintf(id, id_len, @@@ -3071,32 -3128,29 +3127,29 @@@ cur_id_str); break; default: - cur_id_size = 0; break; } break; case 0x8: /* SCSI name string */ - if (cur_id_size + 4 > d[3]) + if (cur_id_size > d[3]) break; /* Prefer others for truncated descriptor */ - if (cur_id_size && d[3] > id_len) - break; + if (d[3] > id_len) { + prio = 2; + if (cur_id_prio > prio) + break; + } + cur_id_prio = prio; cur_id_size = id_size = d[3]; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; if (cur_id_size >= id_len) cur_id_size = id_len - 1; memcpy(id, cur_id_str, cur_id_size); - /* Decrease priority for truncated descriptor */ - if (cur_id_size != id_size) - cur_id_size = 6; break; default: break; } - next_desig: - d += d[3] + 4; } rcu_read_unlock();
diff --combined drivers/scsi/ufs/ufshcd.c index 0c148fcd24de,c1c401b2b69d..9902b7e3aa4a --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@@ -163,6 -163,11 +163,11 @@@ struct ufs_pm_lvl_states ufs_pm_lvl_sta {UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE}, {UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE}, {UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE}, + /* + * For DeepSleep, the link is first put in hibern8 and then off. + * Leaving the link in hibern8 is not supported. + */ + {UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE}, };
static inline enum ufs_dev_pwr_mode @@@ -221,8 -226,6 +226,6 @@@ static int ufshcd_eh_host_reset_handler static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); static void ufshcd_hba_exit(struct ufs_hba *hba); static int ufshcd_probe_hba(struct ufs_hba *hba, bool async); - static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, - bool skip_ref_clk); static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on); static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba); @@@ -245,6 -248,8 +248,8 @@@ static int ufshcd_wb_buf_flush_disable( static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable); static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set); static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable); + static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba); + static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba);
static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) { @@@ -348,7 -353,7 +353,7 @@@ static void ufshcd_add_command_trace(st unsigned int tag, const char *str) { sector_t lba = -1; - u8 opcode = 0; + u8 opcode = 0, group_id = 0; u32 intr, doorbell; struct ufshcd_lrb *lrbp = &hba->lrb[tag]; struct scsi_cmnd *cmd = lrbp->cmd; @@@ -374,13 -379,20 +379,20 @@@ lba = cmd->request->bio->bi_iter.bi_sector; transfer_len = be32_to_cpu( lrbp->ucd_req_ptr->sc.exp_data_transfer_len); + if (opcode == WRITE_10) + group_id = lrbp->cmd->cmnd[6]; + } else if (opcode == UNMAP) { + if (cmd->request) { + lba = scsi_get_lba(cmd); + transfer_len = blk_rq_bytes(cmd->request); + } } }
intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS); doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); trace_ufshcd_command(dev_name(hba->dev), str, tag, - doorbell, transfer_len, intr, lba, opcode); + doorbell, transfer_len, intr, lba, opcode, group_id); }
static void ufshcd_print_clk_freqs(struct ufs_hba *hba) @@@ -399,20 -411,25 +411,25 @@@ } }
- static void ufshcd_print_err_hist(struct ufs_hba *hba, - struct ufs_err_reg_hist *err_hist, - char *err_name) + static void ufshcd_print_evt(struct ufs_hba *hba, u32 id, + char *err_name) { int i; bool found = false; + struct ufs_event_hist *e;
- for (i = 0; i < UFS_ERR_REG_HIST_LENGTH; i++) { - int p = (i + err_hist->pos) % UFS_ERR_REG_HIST_LENGTH; + if (id >= UFS_EVT_CNT) + return;
- if (err_hist->tstamp[p] == 0) + e = &hba->ufs_stats.event[id]; + + for (i = 0; i < UFS_EVENT_HIST_LENGTH; i++) { + int p = (i + e->pos) % UFS_EVENT_HIST_LENGTH; + + if (e->tstamp[p] == 0) continue; dev_err(hba->dev, "%s[%d] = 0x%x at %lld us\n", err_name, p, - err_hist->reg[p], ktime_to_us(err_hist->tstamp[p])); + e->val[p], ktime_to_us(e->tstamp[p])); found = true; }
@@@ -420,26 -437,26 +437,26 @@@ dev_err(hba->dev, "No record of %s\n", err_name); }
- static void ufshcd_print_host_regs(struct ufs_hba *hba) + static void ufshcd_print_evt_hist(struct ufs_hba *hba) { ufshcd_dump_regs(hba, 0, UFSHCI_REG_SPACE_SIZE, "host_regs: ");
- ufshcd_print_err_hist(hba, &hba->ufs_stats.pa_err, "pa_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.dl_err, "dl_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.nl_err, "nl_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.tl_err, "tl_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.dme_err, "dme_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.auto_hibern8_err, - "auto_hibern8_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.fatal_err, "fatal_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.link_startup_err, - "link_startup_fail"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.resume_err, "resume_fail"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.suspend_err, - "suspend_fail"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.dev_reset, "dev_reset"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.host_reset, "host_reset"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.task_abort, "task_abort"); + ufshcd_print_evt(hba, UFS_EVT_PA_ERR, "pa_err"); + ufshcd_print_evt(hba, UFS_EVT_DL_ERR, "dl_err"); + ufshcd_print_evt(hba, UFS_EVT_NL_ERR, "nl_err"); + ufshcd_print_evt(hba, UFS_EVT_TL_ERR, "tl_err"); + ufshcd_print_evt(hba, UFS_EVT_DME_ERR, "dme_err"); + ufshcd_print_evt(hba, UFS_EVT_AUTO_HIBERN8_ERR, + "auto_hibern8_err"); + ufshcd_print_evt(hba, UFS_EVT_FATAL_ERR, "fatal_err"); + ufshcd_print_evt(hba, UFS_EVT_LINK_STARTUP_FAIL, + "link_startup_fail"); + ufshcd_print_evt(hba, UFS_EVT_RESUME_ERR, "resume_fail"); + ufshcd_print_evt(hba, UFS_EVT_SUSPEND_ERR, + "suspend_fail"); + ufshcd_print_evt(hba, UFS_EVT_DEV_RESET, "dev_reset"); + ufshcd_print_evt(hba, UFS_EVT_HOST_RESET, "host_reset"); + ufshcd_print_evt(hba, UFS_EVT_ABORT, "task_abort");
ufshcd_vops_dbg_register_dump(hba); } @@@ -1102,7 -1119,6 +1119,6 @@@ out */ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) { - #define UFS_MIN_GEAR_TO_SCALE_DOWN UFS_HS_G1 int ret = 0; struct ufs_pa_layer_attr new_pwr_info;
@@@ -1113,16 -1129,16 +1129,16 @@@ memcpy(&new_pwr_info, &hba->pwr_info, sizeof(struct ufs_pa_layer_attr));
- if (hba->pwr_info.gear_tx > UFS_MIN_GEAR_TO_SCALE_DOWN - || hba->pwr_info.gear_rx > UFS_MIN_GEAR_TO_SCALE_DOWN) { + if (hba->pwr_info.gear_tx > hba->clk_scaling.min_gear || + hba->pwr_info.gear_rx > hba->clk_scaling.min_gear) { /* save the current power mode */ memcpy(&hba->clk_scaling.saved_pwr_info.info, &hba->pwr_info, sizeof(struct ufs_pa_layer_attr));
/* scale down gear */ - new_pwr_info.gear_tx = UFS_MIN_GEAR_TO_SCALE_DOWN; - new_pwr_info.gear_rx = UFS_MIN_GEAR_TO_SCALE_DOWN; + new_pwr_info.gear_tx = hba->clk_scaling.min_gear; + new_pwr_info.gear_rx = hba->clk_scaling.min_gear; } }
@@@ -1294,15 -1310,8 +1310,15 @@@ static int ufshcd_devfreq_target(struc } spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
+ pm_runtime_get_noresume(hba->dev); + if (!pm_runtime_active(hba->dev)) { + pm_runtime_put_noidle(hba->dev); + ret = -EAGAIN; + goto out; + } start = ktime_get(); ret = ufshcd_devfreq_scale(hba, scale_up); + pm_runtime_put(hba->dev);
trace_ufshcd_profile_clk_scaling(dev_name(hba->dev), (scale_up ? "up" : "down"), @@@ -1555,6 -1564,7 +1571,7 @@@ static void ufshcd_ungate_work(struct w }
spin_unlock_irqrestore(hba->host->host_lock, flags); + ufshcd_hba_vreg_set_hpm(hba); ufshcd_setup_clocks(hba, true);
ufshcd_enable_irq(hba); @@@ -1634,12 -1644,12 +1651,12 @@@ start */ fallthrough; case CLKS_OFF: - ufshcd_scsi_block_requests(hba); hba->clk_gating.state = REQ_CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); - queue_work(hba->clk_gating.clk_gating_workq, - &hba->clk_gating.ungate_work); + if (queue_work(hba->clk_gating.clk_gating_workq, + &hba->clk_gating.ungate_work)) + ufshcd_scsi_block_requests(hba); /* * fall through to check if we should wait for this * work to be done or not. @@@ -1714,12 -1724,10 +1731,10 @@@ static void ufshcd_gate_work(struct wor
ufshcd_disable_irq(hba);
- if (!ufshcd_is_link_active(hba)) - ufshcd_setup_clocks(hba, false); - else - /* If link is active, device ref_clk can't be switched off */ - __ufshcd_setup_clocks(hba, false, true); + ufshcd_setup_clocks(hba, false);
+ /* Put the host controller in low power mode if possible */ + ufshcd_hba_vreg_set_lpm(hba); /* * In case you are here to cancel this work the gating state * would be marked as REQ_CLKS_ON. In this case keep the state @@@ -1751,8 -1759,9 +1766,9 @@@ static void __ufshcd_release(struct ufs
if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL || - ufshcd_any_tag_in_use(hba) || hba->outstanding_tasks || - hba->active_uic_cmd || hba->uic_async_done) + hba->outstanding_tasks || + hba->active_uic_cmd || hba->uic_async_done || + hba->clk_gating.state == CLKS_OFF) return;
hba->clk_gating.state = REQ_CLKS_OFF; @@@ -1814,19 -1823,19 +1830,19 @@@ static ssize_t ufshcd_clkgate_enable_st return -EINVAL;
value = !!value; + + spin_lock_irqsave(hba->host->host_lock, flags); if (value == hba->clk_gating.is_enabled) goto out;
- if (value) { - ufshcd_release(hba); - } else { - spin_lock_irqsave(hba->host->host_lock, flags); + if (value) + __ufshcd_release(hba); + else hba->clk_gating.active_reqs++; - spin_unlock_irqrestore(hba->host->host_lock, flags); - }
hba->clk_gating.is_enabled = value; out: + spin_unlock_irqrestore(hba->host->host_lock, flags); return count; }
@@@ -1837,6 -1846,9 +1853,9 @@@ static void ufshcd_init_clk_scaling(str if (!ufshcd_is_clkscaling_supported(hba)) return;
+ if (!hba->clk_scaling.min_gear) + hba->clk_scaling.min_gear = UFS_HS_G1; + INIT_WORK(&hba->clk_scaling.suspend_work, ufshcd_clk_scaling_suspend_work); INIT_WORK(&hba->clk_scaling.resume_work, @@@ -1874,7 -1886,7 +1893,7 @@@ static void ufshcd_init_clk_gating(stru snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_gating_%d", hba->host->host_no); hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue(wq_name, - WQ_MEM_RECLAIM); + WQ_MEM_RECLAIM | WQ_HIGHPRI);
hba->clk_gating.is_enabled = true;
@@@ -2122,20 -2134,10 +2141,20 @@@ ufshcd_wait_for_uic_cmd(struct ufs_hba unsigned long flags;
if (wait_for_completion_timeout(&uic_cmd->done, - msecs_to_jiffies(UIC_CMD_TIMEOUT))) + msecs_to_jiffies(UIC_CMD_TIMEOUT))) { ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT; - else + } else { ret = -ETIMEDOUT; + dev_err(hba->dev, + "uic cmd 0x%x with arg3 0x%x completion timeout\n", + uic_cmd->command, uic_cmd->argument3); + + if (!uic_cmd->cmd_active) { + dev_err(hba->dev, "%s: UIC cmd has been completed, return the result\n", + __func__); + ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT; + } + }
spin_lock_irqsave(hba->host->host_lock, flags); hba->active_uic_cmd = NULL; @@@ -2167,7 -2169,6 +2186,7 @@@ __ufshcd_send_uic_cmd(struct ufs_hba *h if (completion) init_completion(&uic_cmd->done);
+ uic_cmd->cmd_active = 1; ufshcd_dispatch_uic_cmd(hba, uic_cmd);
return 0; @@@ -2557,6 -2558,14 +2576,14 @@@ static int ufshcd_queuecommand(struct S (hba->clk_gating.state != CLKS_ON));
lrbp = &hba->lrb[tag]; + if (unlikely(lrbp->in_use)) { + if (hba->pm_op_in_progress) + set_host_byte(cmd, DID_BAD_TARGET); + else + err = SCSI_MLQUEUE_HOST_BUSY; + ufshcd_release(hba); + goto out; + }
WARN_ON(lrbp->cmd); lrbp->cmd = cmd; @@@ -2799,6 -2808,11 +2826,11 @@@ static int ufshcd_exec_dev_cmd(struct u
init_completion(&wait); lrbp = &hba->lrb[tag]; + if (unlikely(lrbp->in_use)) { + err = -EBUSY; + goto out; + } + WARN_ON(lrbp->cmd); err = ufshcd_compose_dev_cmd(hba, lrbp, cmd_type, tag); if (unlikely(err)) @@@ -2815,6 -2829,7 +2847,7 @@@
err = ufshcd_wait_for_dev_cmd(hba, lrbp, timeout);
+ out: ufshcd_add_query_upiu_trace(hba, tag, err ? "query_complete_err" : "query_complete");
@@@ -2960,14 -2975,14 +2993,14 @@@ int ufshcd_query_attr(struct ufs_hba *h
BUG_ON(!hba);
- ufshcd_hold(hba, false); if (!attr_val) { dev_err(hba->dev, "%s: attribute value required for opcode 0x%x\n", __func__, opcode); - err = -EINVAL; - goto out; + return -EINVAL; }
+ ufshcd_hold(hba, false); + mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, selector); @@@ -2999,7 -3014,6 +3032,6 @@@
out_unlock: mutex_unlock(&hba->dev_cmd.lock); - out: ufshcd_release(hba); return err; } @@@ -3051,21 -3065,20 +3083,20 @@@ static int __ufshcd_query_descriptor(st
BUG_ON(!hba);
- ufshcd_hold(hba, false); if (!desc_buf) { dev_err(hba->dev, "%s: descriptor buffer required for opcode 0x%x\n", __func__, opcode); - err = -EINVAL; - goto out; + return -EINVAL; }
if (*buf_len < QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n", __func__, *buf_len); - err = -EINVAL; - goto out; + return -EINVAL; }
+ ufshcd_hold(hba, false); + mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, selector); @@@ -3100,7 -3113,6 +3131,6 @@@ out_unlock: hba->dev_cmd.query.descriptor = NULL; mutex_unlock(&hba->dev_cmd.lock); - out: ufshcd_release(hba); return err; } @@@ -3199,19 -3211,13 +3229,19 @@@ int ufshcd_read_desc_param(struct ufs_h /* Get the length of descriptor */ ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len); if (!buff_len) { - dev_err(hba->dev, "%s: Failed to get desc length", __func__); + dev_err(hba->dev, "%s: Failed to get desc length\n", __func__); + return -EINVAL; + } + + if (param_offset >= buff_len) { + dev_err(hba->dev, "%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n", + __func__, param_offset, desc_id, buff_len); return -EINVAL; }
/* Check whether we need temp memory */ if (param_offset != 0 || param_size < buff_len) { - desc_buf = kmalloc(buff_len, GFP_KERNEL); + desc_buf = kzalloc(buff_len, GFP_KERNEL); if (!desc_buf) return -ENOMEM; } else { @@@ -3225,14 -3231,14 +3255,14 @@@ desc_buf, &buff_len);
if (ret) { - dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d", + dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n", __func__, desc_id, desc_index, param_offset, ret); goto out; }
/* Sanity check */ if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) { - dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header", + dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n", __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]); ret = -EINVAL; goto out; @@@ -3242,12 -3248,12 +3272,12 @@@ buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET]; ufshcd_update_desc_length(hba, desc_id, desc_index, buff_len);
- /* Check wherher we will not copy more data, than available */ - if (is_kmalloc && (param_offset + param_size) > buff_len) - param_size = buff_len - param_offset; - - if (is_kmalloc) + if (is_kmalloc) { + /* Make sure we don't copy more data than available */ + if (param_offset + param_size > buff_len) + param_size = buff_len - param_offset; memcpy(param_read_buf, &desc_buf[param_offset], param_size); + } out: if (is_kmalloc) kfree(desc_buf); @@@ -3601,6 -3607,22 +3631,22 @@@ static int ufshcd_dme_reset(struct ufs_ return ret; }
+ int ufshcd_dme_configure_adapt(struct ufs_hba *hba, + int agreed_gear, + int adapt_val) + { + int ret; + + if (agreed_gear != UFS_HS_G4) + adapt_val = PA_NO_ADAPT; + + ret = ufshcd_dme_set(hba, + UIC_ARG_MIB(PA_TXHSADAPTTYPE), + adapt_val); + return ret; + } + EXPORT_SYMBOL_GPL(ufshcd_dme_configure_adapt); + /** * ufshcd_dme_enable - UIC command for DME_ENABLE * @hba: per adapter instance @@@ -3831,18 -3853,10 +3877,18 @@@ static int ufshcd_uic_pwr_ctrl(struct u dev_err(hba->dev, "pwr ctrl cmd 0x%x with mode 0x%x completion timeout\n", cmd->command, cmd->argument3); + + if (!cmd->cmd_active) { + dev_err(hba->dev, "%s: Power Mode Change operation has been completed, go check UPMCRS\n", + __func__); + goto check_upmcrs; + } + ret = -ETIMEDOUT; goto out; }
+check_upmcrs: status = ufshcd_get_upmcrs(hba); if (status != PWR_LOCAL) { dev_err(hba->dev, @@@ -3854,7 -3868,7 +3900,7 @@@ out if (ret) { ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); }
spin_lock_irqsave(hba->host->host_lock, flags); @@@ -4350,8 -4364,10 +4396,10 @@@ static inline void ufshcd_hba_stop(stru */ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) { - int retry; + int retry_outer = 3; + int retry_inner;
+ start: if (!ufshcd_is_hba_active(hba)) /* change controller state to "reset state" */ ufshcd_hba_stop(hba); @@@ -4377,13 -4393,17 +4425,17 @@@ ufshcd_delay_us(hba->vps->hba_enable_delay_us, 100);
/* wait for the host controller to complete initialization */ - retry = 50; + retry_inner = 50; while (ufshcd_is_hba_active(hba)) { - if (retry) { - retry--; + if (retry_inner) { + retry_inner--; } else { dev_err(hba->dev, "Controller enable failed\n"); + if (retry_outer) { + retry_outer--; + goto start; + } return -EIO; } usleep_range(1000, 1100); @@@ -4460,14 -4480,21 +4512,21 @@@ static inline int ufshcd_disable_device return ufshcd_disable_tx_lcc(hba, true); }
- void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist, - u32 reg) + void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val) { - reg_hist->reg[reg_hist->pos] = reg; - reg_hist->tstamp[reg_hist->pos] = ktime_get(); - reg_hist->pos = (reg_hist->pos + 1) % UFS_ERR_REG_HIST_LENGTH; + struct ufs_event_hist *e; + + if (id >= UFS_EVT_CNT) + return; + + e = &hba->ufs_stats.event[id]; + e->val[e->pos] = val; + e->tstamp[e->pos] = ktime_get(); + e->pos = (e->pos + 1) % UFS_EVENT_HIST_LENGTH; + + ufshcd_vops_event_notify(hba, id, &val); } - EXPORT_SYMBOL_GPL(ufshcd_update_reg_hist); + EXPORT_SYMBOL_GPL(ufshcd_update_evt_hist);
/** * ufshcd_link_startup - Initialize unipro link startup @@@ -4496,7 -4523,8 +4555,8 @@@ link_startup
/* check if device is detected by inter-connect layer */ if (!ret && !ufshcd_is_device_present(hba)) { - ufshcd_update_reg_hist(&hba->ufs_stats.link_startup_err, + ufshcd_update_evt_hist(hba, + UFS_EVT_LINK_STARTUP_FAIL, 0); dev_err(hba->dev, "%s: Device not present\n", __func__); ret = -ENXIO; @@@ -4509,7 -4537,8 +4569,8 @@@ * succeeds. So reset the local Uni-Pro and try again. */ if (ret && ufshcd_hba_enable(hba)) { - ufshcd_update_reg_hist(&hba->ufs_stats.link_startup_err, + ufshcd_update_evt_hist(hba, + UFS_EVT_LINK_STARTUP_FAIL, (u32)ret); goto out; } @@@ -4517,7 -4546,8 +4578,8 @@@
if (ret) { /* failed to get the link up... retire */ - ufshcd_update_reg_hist(&hba->ufs_stats.link_startup_err, + ufshcd_update_evt_hist(hba, + UFS_EVT_LINK_STARTUP_FAIL, (u32)ret); goto out; } @@@ -4551,7 -4581,7 +4613,7 @@@ out dev_err(hba->dev, "link startup failed %d\n", ret); ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); } return ret; } @@@ -4906,7 -4936,7 +4968,7 @@@ ufshcd_transfer_rsp_status(struct ufs_h dev_err(hba->dev, "OCS error from controller = %x for tag %d\n", ocs, lrbp->task_tag); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); ufshcd_print_host_state(hba); break; } /* end of switch */ @@@ -4934,14 -4964,11 +4996,14 @@@ static irqreturn_t ufshcd_uic_cmd_compl ufshcd_get_uic_cmd_result(hba); hba->active_uic_cmd->argument3 = ufshcd_get_dme_attr_val(hba); + if (!hba->uic_async_done) + hba->active_uic_cmd->cmd_active = 0; complete(&hba->active_uic_cmd->done); retval = IRQ_HANDLED; }
if ((intr_status & UFSHCD_UIC_PWR_MASK) && hba->uic_async_done) { + hba->active_uic_cmd->cmd_active = 0; complete(hba->uic_async_done); retval = IRQ_HANDLED; } @@@ -4964,9 -4991,11 +5026,11 @@@ static void __ufshcd_transfer_req_compl struct scsi_cmnd *cmd; int result; int index; + bool update_scaling = false;
for_each_set_bit(index, &completed_reqs, hba->nutrs) { lrbp = &hba->lrb[index]; + lrbp->in_use = false; lrbp->compl_time_stamp = ktime_get(); cmd = lrbp->cmd; if (cmd) { @@@ -4979,15 -5008,17 +5043,17 @@@ /* Do not touch lrbp after scsi done */ cmd->scsi_done(cmd); __ufshcd_release(hba); + update_scaling = true; } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE || lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) { if (hba->dev_cmd.complete) { ufshcd_add_command_trace(hba, index, "dev_complete"); complete(hba->dev_cmd.complete); + update_scaling = true; } } - if (ufshcd_is_clkscaling_supported(hba)) + if (ufshcd_is_clkscaling_supported(hba) && update_scaling) hba->clk_scaling.active_reqs--; }
@@@ -5632,7 -5663,9 +5698,9 @@@ static inline void ufshcd_schedule_eh_w static void ufshcd_err_handling_prepare(struct ufs_hba *hba) { pm_runtime_get_sync(hba->dev); - if (pm_runtime_suspended(hba->dev)) { + if (pm_runtime_status_suspended(hba->dev) || hba->is_sys_suspended) { + enum ufs_pm_op pm_op; + /* * Don't assume anything of pm_runtime_get_sync(), if * resume fails, irq and clocks can be OFF, and powers @@@ -5647,7 -5680,8 +5715,8 @@@ if (!ufshcd_is_clkgating_allowed(hba)) ufshcd_setup_clocks(hba, true); ufshcd_release(hba); - ufshcd_vops_resume(hba, UFS_RUNTIME_PM); + pm_op = hba->is_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM; + ufshcd_vops_resume(hba, pm_op); } else { ufshcd_hold(hba, false); if (hba->clk_scaling.is_allowed) { @@@ -5668,7 -5702,7 +5737,7 @@@ static void ufshcd_err_handling_unprepa
static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba) { - return (hba->ufshcd_state == UFSHCD_STATE_ERROR || + return (!hba->is_powered || hba->ufshcd_state == UFSHCD_STATE_ERROR || (!(hba->saved_err || hba->saved_uic_err || hba->force_reset || ufshcd_is_link_broken(hba)))); } @@@ -5681,6 -5715,7 +5750,7 @@@ static void ufshcd_recover_pm_error(str struct request_queue *q; int ret;
+ hba->is_sys_suspended = false; /* * Set RPM status of hba device to RPM_ACTIVE, * this also clears its runtime error. @@@ -5739,11 -5774,13 +5809,13 @@@ static void ufshcd_err_handler(struct w
hba = container_of(work, struct ufs_hba, eh_work);
+ down(&hba->eh_sem); spin_lock_irqsave(hba->host->host_lock, flags); if (ufshcd_err_handling_should_stop(hba)) { if (hba->ufshcd_state != UFSHCD_STATE_ERROR) hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; spin_unlock_irqrestore(hba->host->host_lock, flags); + up(&hba->eh_sem); return; } ufshcd_set_eh_in_progress(hba); @@@ -5751,20 -5788,18 +5823,18 @@@ ufshcd_err_handling_prepare(hba); spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_scsi_block_requests(hba); - /* - * A full reset and restore might have happened after preparation - * is finished, double check whether we should stop. - */ - if (ufshcd_err_handling_should_stop(hba)) { - if (hba->ufshcd_state != UFSHCD_STATE_ERROR) - hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; - goto out; - } hba->ufshcd_state = UFSHCD_STATE_RESET;
/* Complete requests that have door-bell cleared by h/w */ ufshcd_complete_requests(hba);
+ /* + * A full reset and restore might have happened after preparation + * is finished, double check whether we should stop. + */ + if (ufshcd_err_handling_should_stop(hba)) + goto skip_err_handling; + if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) { bool ret;
@@@ -5772,17 -5807,10 +5842,10 @@@ /* release the lock as ufshcd_quirk_dl_nac_errors() may sleep */ ret = ufshcd_quirk_dl_nac_errors(hba); spin_lock_irqsave(hba->host->host_lock, flags); - if (!ret && !hba->force_reset && ufshcd_is_link_active(hba)) + if (!ret && ufshcd_err_handling_should_stop(hba)) goto skip_err_handling; }
- if (hba->force_reset || ufshcd_is_link_broken(hba) || - ufshcd_is_saved_err_fatal(hba) || - ((hba->saved_err & UIC_ERROR) && - (hba->saved_uic_err & (UFSHCD_UIC_DL_NAC_RECEIVED_ERROR | - UFSHCD_UIC_DL_TCx_REPLAY_ERROR)))) - needs_reset = true; - if ((hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) || (hba->saved_uic_err && (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) { @@@ -5791,7 -5819,7 +5854,7 @@@ spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); ufshcd_print_tmrs(hba, hba->outstanding_tasks); ufshcd_print_trs(hba, hba->outstanding_reqs, pr_prdt); spin_lock_irqsave(hba->host->host_lock, flags); @@@ -5802,8 -5830,14 +5865,14 @@@ * transfers forcefully because they will get cleared during * host reset and restore */ - if (needs_reset) + if (hba->force_reset || ufshcd_is_link_broken(hba) || + ufshcd_is_saved_err_fatal(hba) || + ((hba->saved_err & UIC_ERROR) && + (hba->saved_uic_err & (UFSHCD_UIC_DL_NAC_RECEIVED_ERROR | + UFSHCD_UIC_DL_TCx_REPLAY_ERROR)))) { + needs_reset = true; goto do_reset; + }
/* * If LINERESET was caught, UFS might have been put to PWM mode, @@@ -5911,12 -5945,11 +5980,11 @@@ skip_err_handling dev_err_ratelimited(hba->dev, "%s: exit: saved_err 0x%x saved_uic_err 0x%x", __func__, hba->saved_err, hba->saved_uic_err); } - - out: ufshcd_clear_eh_in_progress(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_scsi_unblock_requests(hba); ufshcd_err_handling_unprepare(hba); + up(&hba->eh_sem); }
/** @@@ -5936,7 -5969,7 +6004,7 @@@ static irqreturn_t ufshcd_update_uic_er reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER); if ((reg & UIC_PHY_ADAPTER_LAYER_ERROR) && (reg & UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.pa_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_PA_ERR, reg); /* * To know whether this error is fatal or not, DB timeout * must be checked but this error is handled separately. @@@ -5966,7 -5999,7 +6034,7 @@@ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER); if ((reg & UIC_DATA_LINK_LAYER_ERROR) && (reg & UIC_DATA_LINK_LAYER_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.dl_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_DL_ERR, reg);
if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT) hba->uic_error |= UFSHCD_UIC_DL_PA_INIT_ERROR; @@@ -5985,7 -6018,7 +6053,7 @@@ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_NETWORK_LAYER); if ((reg & UIC_NETWORK_LAYER_ERROR) && (reg & UIC_NETWORK_LAYER_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.nl_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_NL_ERR, reg); hba->uic_error |= UFSHCD_UIC_NL_ERROR; retval |= IRQ_HANDLED; } @@@ -5993,7 -6026,7 +6061,7 @@@ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_TRANSPORT_LAYER); if ((reg & UIC_TRANSPORT_LAYER_ERROR) && (reg & UIC_TRANSPORT_LAYER_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.tl_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_TL_ERR, reg); hba->uic_error |= UFSHCD_UIC_TL_ERROR; retval |= IRQ_HANDLED; } @@@ -6001,7 -6034,7 +6069,7 @@@ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DME); if ((reg & UIC_DME_ERROR) && (reg & UIC_DME_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.dme_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_DME_ERR, reg); hba->uic_error |= UFSHCD_UIC_DME_ERROR; retval |= IRQ_HANDLED; } @@@ -6043,7 -6076,8 +6111,8 @@@ static irqreturn_t ufshcd_check_errors( irqreturn_t retval = IRQ_NONE;
if (hba->errors & INT_FATAL_ERRORS) { - ufshcd_update_reg_hist(&hba->ufs_stats.fatal_err, hba->errors); + ufshcd_update_evt_hist(hba, UFS_EVT_FATAL_ERR, + hba->errors); queue_eh_work = true; }
@@@ -6060,7 -6094,7 +6129,7 @@@ __func__, (hba->errors & UIC_HIBERNATE_ENTER) ? "Enter" : "Exit", hba->errors, ufshcd_get_upmcrs(hba)); - ufshcd_update_reg_hist(&hba->ufs_stats.auto_hibern8_err, + ufshcd_update_evt_hist(hba, UFS_EVT_AUTO_HIBERN8_ERR, hba->errors); ufshcd_set_link_broken(hba); queue_eh_work = true; @@@ -6075,7 -6109,8 +6144,8 @@@ hba->saved_uic_err |= hba->uic_error;
/* dump controller state before resetting */ - if ((hba->saved_err & (INT_FATAL_ERRORS)) || + if ((hba->saved_err & + (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) || (hba->saved_uic_err && (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) { dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x\n", @@@ -6407,8 -6442,12 +6477,12 @@@ static int ufshcd_issue_devman_upiu_cmd
init_completion(&wait); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); + if (unlikely(lrbp->in_use)) { + err = -EBUSY; + goto out; + }
+ WARN_ON(lrbp->cmd); lrbp->cmd = NULL; lrbp->sense_bufflen = 0; lrbp->sense_buffer = NULL; @@@ -6480,6 -6519,7 +6554,7 @@@ } }
+ out: blk_put_request(req); out_unlock: up_read(&hba->clk_scaling_lock); @@@ -6601,7 -6641,7 +6676,7 @@@ static int ufshcd_eh_device_reset_handl
out: hba->req_abort_count = 0; - ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, (u32)err); + ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, (u32)err); if (!err) { err = SUCCESS; } else { @@@ -6624,7 -6664,8 +6699,8 @@@ static void ufshcd_set_req_abort_skip(s
/** * ufshcd_try_to_abort_task - abort a specific task - * @cmd: SCSI command pointer + * @hba: Pointer to adapter instance + * @tag: Task tag/index to be aborted * * Abort the pending command in device by sending UFS_ABORT_TASK task management * command, and in host controller by clearing the door-bell register. There can @@@ -6729,16 -6770,6 +6805,6 @@@ static int ufshcd_abort(struct scsi_cmn BUG(); }
- /* - * Task abort to the device W-LUN is illegal. When this command - * will fail, due to spec violation, scsi err handling next step - * will be to send LU reset which, again, is a spec violation. - * To avoid these unnecessary/illegal step we skip to the last error - * handling stage: reset and restore. - */ - if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) - return ufshcd_eh_host_reset_handler(cmd); - ufshcd_hold(hba, false); reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); /* If command is already aborted/completed, return SUCCESS */ @@@ -6759,10 -6790,10 +6825,10 @@@ * to reduce repeated printouts. For other aborted requests only print * basic details. */ - scsi_print_command(hba->lrb[tag].cmd); + scsi_print_command(cmd); if (!hba->req_abort_count) { - ufshcd_update_reg_hist(&hba->ufs_stats.task_abort, 0); - ufshcd_print_host_regs(hba); + ufshcd_update_evt_hist(hba, UFS_EVT_ABORT, tag); + ufshcd_print_evt_hist(hba); ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); ufshcd_print_trs(hba, 1 << tag, true); @@@ -6778,6 -6809,29 +6844,29 @@@ goto cleanup; }
+ /* + * Task abort to the device W-LUN is illegal. When this command + * will fail, due to spec violation, scsi err handling next step + * will be to send LU reset which, again, is a spec violation. + * To avoid these unnecessary/illegal steps, first we clean up + * the lrb taken by this cmd and mark the lrb as in_use, then + * queue the eh_work and bail. + */ + if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) { + ufshcd_update_evt_hist(hba, UFS_EVT_ABORT, lrbp->lun); + spin_lock_irqsave(host->host_lock, flags); + if (lrbp->cmd) { + __ufshcd_transfer_req_compl(hba, (1UL << tag)); + __set_bit(tag, &hba->outstanding_reqs); + lrbp->in_use = true; + hba->force_reset = true; + ufshcd_schedule_eh_work(hba); + } + + spin_unlock_irqrestore(host->host_lock, flags); + goto out; + } + /* Skip task abort in case previous aborts failed and report failure */ if (lrbp->req_abort_skip) err = -EIO; @@@ -6845,7 -6899,7 +6934,7 @@@ static int ufshcd_host_reset_and_restor out: if (err) dev_err(hba->dev, "%s: Host init failed %d\n", __func__, err); - ufshcd_update_reg_hist(&hba->ufs_stats.host_reset, (u32)err); + ufshcd_update_evt_hist(hba, UFS_EVT_HOST_RESET, (u32)err); return err; }
@@@ -6891,6 -6945,7 +6980,7 @@@ static int ufshcd_reset_and_restore(str */ scsi_report_bus_reset(hba->host, 0); if (err) { + hba->ufshcd_state = UFSHCD_STATE_ERROR; hba->saved_err |= saved_err; hba->saved_uic_err |= saved_uic_err; } @@@ -7092,7 -7147,6 +7182,6 @@@ static inline void ufshcd_blk_pm_runtim static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) { int ret = 0; - struct scsi_device *sdev_rpmb; struct scsi_device *sdev_boot;
hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0, @@@ -7105,14 -7159,14 +7194,14 @@@ ufshcd_blk_pm_runtime_init(hba->sdev_ufs_device); scsi_device_put(hba->sdev_ufs_device);
- sdev_rpmb = __scsi_add_device(hba->host, 0, 0, + hba->sdev_rpmb = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL); - if (IS_ERR(sdev_rpmb)) { - ret = PTR_ERR(sdev_rpmb); + if (IS_ERR(hba->sdev_rpmb)) { + ret = PTR_ERR(hba->sdev_rpmb); goto remove_sdev_ufs_device; } - ufshcd_blk_pm_runtime_init(sdev_rpmb); - scsi_device_put(sdev_rpmb); + ufshcd_blk_pm_runtime_init(hba->sdev_rpmb); + scsi_device_put(hba->sdev_rpmb);
sdev_boot = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); @@@ -7636,6 -7690,63 +7725,63 @@@ out return ret; }
+ static int + ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp); + + static int ufshcd_clear_ua_wlun(struct ufs_hba *hba, u8 wlun) + { + struct scsi_device *sdp; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(hba->host->host_lock, flags); + if (wlun == UFS_UPIU_UFS_DEVICE_WLUN) + sdp = hba->sdev_ufs_device; + else if (wlun == UFS_UPIU_RPMB_WLUN) + sdp = hba->sdev_rpmb; + else + BUG(); + if (sdp) { + ret = scsi_device_get(sdp); + if (!ret && !scsi_device_online(sdp)) { + ret = -ENODEV; + scsi_device_put(sdp); + } + } else { + ret = -ENODEV; + } + spin_unlock_irqrestore(hba->host->host_lock, flags); + if (ret) + goto out_err; + + ret = ufshcd_send_request_sense(hba, sdp); + scsi_device_put(sdp); + out_err: + if (ret) + dev_err(hba->dev, "%s: UAC clear LU=%x ret = %d\n", + __func__, wlun, ret); + return ret; + } + + static int ufshcd_clear_ua_wluns(struct ufs_hba *hba) + { + int ret = 0; + + if (!hba->wlun_dev_clr_ua) + goto out; + + ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_UFS_DEVICE_WLUN); + if (!ret) + ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_RPMB_WLUN); + if (!ret) + hba->wlun_dev_clr_ua = false; + out: + if (ret) + dev_err(hba->dev, "%s: Failed to clear UAC WLUNS ret = %d\n", + __func__, ret); + return ret; + } + /** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance @@@ -7739,8 -7850,10 +7885,10 @@@ static void ufshcd_async_scan(void *dat struct ufs_hba *hba = (struct ufs_hba *)data; int ret;
+ down(&hba->eh_sem); /* Initialize hba, detect and initialize UFS device */ ret = ufshcd_probe_hba(hba, true); + up(&hba->eh_sem); if (ret) goto out;
@@@ -7755,6 -7868,8 +7903,8 @@@ out pm_runtime_put_sync(hba->dev); ufshcd_exit_clk_scaling(hba); ufshcd_hba_exit(hba); + } else { + ufshcd_clear_ua_wluns(hba); } }
@@@ -7988,8 -8103,7 +8138,7 @@@ static int ufshcd_init_hba_vreg(struct return 0; }
- static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, - bool skip_ref_clk) + static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on) { int ret = 0; struct ufs_clk_info *clki; @@@ -8007,7 -8121,12 +8156,12 @@@
list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk)) { - if (skip_ref_clk && !strcmp(clki->name, "ref_clk")) + /* + * Don't disable clocks which are needed + * to keep the link active. + */ + if (ufshcd_is_link_active(hba) && + clki->keep_link_active) continue;
clk_state_changed = on ^ clki->enabled; @@@ -8052,11 -8171,6 +8206,6 @@@ out return ret; }
- static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on) - { - return __ufshcd_setup_clocks(hba, on, false); - } - static int ufshcd_init_clocks(struct ufs_hba *hba) { int ret = 0; @@@ -8112,16 -8226,10 +8261,10 @@@ static int ufshcd_variant_hba_init(stru goto out;
err = ufshcd_vops_init(hba); - if (err) - goto out; - - err = ufshcd_vops_setup_regulators(hba, true); - if (err) - ufshcd_vops_exit(hba); - out: if (err) dev_err(hba->dev, "%s: variant %s init failed err %d\n", __func__, ufshcd_get_var_name(hba), err); + out: return err; }
@@@ -8130,8 -8238,6 +8273,6 @@@ static void ufshcd_variant_hba_exit(str if (!hba->vops) return;
- ufshcd_vops_setup_regulators(hba, false); - ufshcd_vops_exit(hba); }
@@@ -8327,7 -8433,8 +8468,8 @@@ static int ufshcd_link_state_transition } /* * If autobkops is enabled, link can't be turned off because - * turning off the link would also turn off the device. + * turning off the link would also turn off the device, except in the + * case of DeepSleep where the device is expected to remain powered. */ else if ((req_link_state == UIC_LINK_OFF_STATE) && (!check_for_bkops || !hba->auto_bkops_enabled)) { @@@ -8337,6 -8444,9 +8479,9 @@@ * put the link in low power mode is to send the DME end point * to device and then send the DME reset command to local * unipro. But putting the link in hibern8 is much faster. + * + * Note also that putting the link in Hibern8 is a requirement + * for entering DeepSleep. */ ret = ufshcd_uic_hibern8_enter(hba); if (ret) { @@@ -8440,13 -8550,13 +8585,13 @@@ out
static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba) { - if (ufshcd_is_link_off(hba)) + if (ufshcd_is_link_off(hba) || ufshcd_can_aggressive_pc(hba)) ufshcd_setup_hba_vreg(hba, false); }
static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba) { - if (ufshcd_is_link_off(hba)) + if (ufshcd_is_link_off(hba) || ufshcd_can_aggressive_pc(hba)) ufshcd_setup_hba_vreg(hba, true); }
@@@ -8469,6 -8579,7 +8614,7 @@@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) { int ret = 0; + int check_for_bkops; enum ufs_pm_level pm_lvl; enum ufs_dev_pwr_mode req_dev_pwr_mode; enum uic_link_state req_link_state; @@@ -8540,11 -8651,9 +8686,9 @@@ }
if (req_dev_pwr_mode != hba->curr_dev_pwr_mode) { - if ((ufshcd_is_runtime_pm(pm_op) && !hba->auto_bkops_enabled) || - !ufshcd_is_runtime_pm(pm_op)) { + if (!ufshcd_is_runtime_pm(pm_op)) /* ensure that bkops is disabled */ ufshcd_disable_auto_bkops(hba); - }
if (!hba->dev_info.b_rpm_dev_flush_capable) { ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode); @@@ -8554,7 -8663,13 +8698,13 @@@ }
flush_work(&hba->eeh_work); - ret = ufshcd_link_state_transition(hba, req_link_state, 1); + + /* + * In the case of DeepSleep, the device is expected to remain powered + * with the link off, so do not check for bkops. + */ + check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba); + ret = ufshcd_link_state_transition(hba, req_link_state, check_for_bkops); if (ret) goto set_dev_active;
@@@ -8575,11 -8690,7 +8725,7 @@@ disable_clks */ ufshcd_disable_irq(hba);
- if (!ufshcd_is_link_active(hba)) - ufshcd_setup_clocks(hba, false); - else - /* If link is active, device ref_clk can't be switched off */ - __ufshcd_setup_clocks(hba, false, true); + ufshcd_setup_clocks(hba, false);
if (ufshcd_is_clkgating_allowed(hba)) { hba->clk_gating.state = CLKS_OFF; @@@ -8595,11 -8706,25 +8741,25 @@@ set_link_active if (hba->clk_scaling.is_allowed) ufshcd_resume_clkscaling(hba); ufshcd_vreg_set_hpm(hba); + /* + * Device hardware reset is required to exit DeepSleep. Also, for + * DeepSleep, the link is off so host reset and restore will be done + * further below. + */ + if (ufshcd_is_ufs_dev_deepsleep(hba)) { + ufshcd_vops_device_reset(hba); + WARN_ON(!ufshcd_is_link_off(hba)); + } if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba)) ufshcd_set_link_active(hba); else if (ufshcd_is_link_off(hba)) ufshcd_host_reset_and_restore(hba); set_dev_active: + /* Can also get here needing to exit DeepSleep */ + if (ufshcd_is_ufs_dev_deepsleep(hba)) { + ufshcd_vops_device_reset(hba); + ufshcd_host_reset_and_restore(hba); + } if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE)) ufshcd_disable_auto_bkops(hba); enable_gating: @@@ -8617,7 -8742,7 +8777,7 @@@ out hba->pm_op_in_progress = 0;
if (ret) - ufshcd_update_reg_hist(&hba->ufs_stats.suspend_err, (u32)ret); + ufshcd_update_evt_hist(hba, UFS_EVT_SUSPEND_ERR, (u32)ret); return ret; }
@@@ -8661,6 -8786,9 +8821,9 @@@ static int ufshcd_resume(struct ufs_hb if (ret) goto disable_vreg;
+ /* For DeepSleep, the only supported option is to have the link off */ + WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && !ufshcd_is_link_off(hba)); + if (ufshcd_is_link_hibern8(hba)) { ret = ufshcd_uic_hibern8_exit(hba); if (!ret) { @@@ -8674,6 -8802,8 +8837,8 @@@ /* * A full initialization of the host and the device is * required since the link was put to off during suspend. + * Note, in the case of DeepSleep, the device will exit + * DeepSleep due to device reset. */ ret = ufshcd_reset_and_restore(hba); /* @@@ -8736,7 -8866,7 +8901,7 @@@ disable_irq_and_vops_clks out: hba->pm_op_in_progress = 0; if (ret) - ufshcd_update_reg_hist(&hba->ufs_stats.resume_err, (u32)ret); + ufshcd_update_evt_hist(hba, UFS_EVT_RESUME_ERR, (u32)ret); return ret; }
@@@ -8753,6 -8883,7 +8918,7 @@@ int ufshcd_system_suspend(struct ufs_hb int ret = 0; ktime_t start = ktime_get();
+ down(&hba->eh_sem); if (!hba || !hba->is_powered) return 0;
@@@ -8783,6 -8914,8 +8949,8 @@@ out hba->curr_dev_pwr_mode, hba->uic_link_state); if (!ret) hba->is_sys_suspended = true; + else + up(&hba->eh_sem); return ret; } EXPORT_SYMBOL(ufshcd_system_suspend); @@@ -8799,8 -8932,10 +8967,10 @@@ int ufshcd_system_resume(struct ufs_hb int ret = 0; ktime_t start = ktime_get();
- if (!hba) + if (!hba) { + up(&hba->eh_sem); return -EINVAL; + }
if (!hba->is_powered || pm_runtime_suspended(hba->dev)) /* @@@ -8816,6 -8951,7 +8986,7 @@@ out hba->curr_dev_pwr_mode, hba->uic_link_state); if (!ret) hba->is_sys_suspended = false; + up(&hba->eh_sem); return ret; } EXPORT_SYMBOL(ufshcd_system_resume); @@@ -8907,18 -9043,25 +9078,21 @@@ int ufshcd_shutdown(struct ufs_hba *hba { int ret = 0;
+ down(&hba->eh_sem); if (!hba->is_powered) goto out;
if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba)) goto out;
- if (pm_runtime_suspended(hba->dev)) { - ret = ufshcd_runtime_resume(hba); - if (ret) - goto out; - } + pm_runtime_get_sync(hba->dev);
ret = ufshcd_suspend(hba, UFS_SHUTDOWN_PM); out: if (ret) dev_err(hba->dev, "%s failed, err %d\n", __func__, ret); + hba->is_powered = false; + up(&hba->eh_sem); /* allow force shutdown even in case of errors */ return 0; } @@@ -8937,7 -9080,6 +9111,7 @@@ void ufshcd_remove(struct ufs_hba *hba blk_mq_free_tag_set(&hba->tmf_tag_set); blk_cleanup_queue(hba->cmd_queue); scsi_remove_host(hba->host); + destroy_workqueue(hba->eh_wq); /* disable interrupts */ ufshcd_disable_intr(hba, hba->intr_mask); ufshcd_hba_stop(hba); @@@ -9114,6 -9256,8 +9288,8 @@@ int ufshcd_init(struct ufs_hba *hba, vo INIT_WORK(&hba->eh_work, ufshcd_err_handler); INIT_WORK(&hba->eeh_work, ufshcd_exception_event_handler);
+ sema_init(&hba->eh_sem, 1); + /* Initialize UIC command mutex */ mutex_init(&hba->uic_cmd_mutex);
@@@ -9185,7 -9329,7 +9361,7 @@@ err = ufshcd_hba_enable(hba); if (err) { dev_err(hba->dev, "Host controller enable failed\n"); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); ufshcd_print_host_state(hba); goto free_tmf_queue; } @@@ -9238,7 -9382,6 +9414,7 @@@ out_remove_scsi_host exit_gating: ufshcd_exit_clk_scaling(hba); ufshcd_exit_clk_gating(hba); + destroy_workqueue(hba->eh_wq); out_disable: hba->is_irq_enabled = false; ufshcd_hba_exit(hba); diff --combined drivers/scsi/ufs/ufshcd.h index e0f00a42371c,08c8a591e6b0..f8c2467dc014 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@@ -58,13 -58,35 +58,36 @@@ enum dev_cmd_type DEV_CMD_TYPE_QUERY = 0x1, };
+ enum ufs_event_type { + /* uic specific errors */ + UFS_EVT_PA_ERR = 0, + UFS_EVT_DL_ERR, + UFS_EVT_NL_ERR, + UFS_EVT_TL_ERR, + UFS_EVT_DME_ERR, + + /* fatal errors */ + UFS_EVT_AUTO_HIBERN8_ERR, + UFS_EVT_FATAL_ERR, + UFS_EVT_LINK_STARTUP_FAIL, + UFS_EVT_RESUME_ERR, + UFS_EVT_SUSPEND_ERR, + + /* abnormal events */ + UFS_EVT_DEV_RESET, + UFS_EVT_HOST_RESET, + UFS_EVT_ABORT, + + UFS_EVT_CNT, + }; + /** * struct uic_command - UIC command structure * @command: UIC command * @argument1: UIC command argument 1 * @argument2: UIC command argument 2 * @argument3: UIC command argument 3 + * @cmd_active: Indicate if UIC command is outstanding * @done: UIC command completion */ struct uic_command { @@@ -72,7 -94,6 +95,7 @@@ u32 argument1; u32 argument2; u32 argument3; + int cmd_active; struct completion done; };
@@@ -116,16 -137,22 +139,22 @@@ enum uic_link_state ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE) #define ufshcd_set_ufs_dev_poweroff(h) \ ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE) + #define ufshcd_set_ufs_dev_deepsleep(h) \ + ((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE) #define ufshcd_is_ufs_dev_active(h) \ ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE) #define ufshcd_is_ufs_dev_sleep(h) \ ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE) #define ufshcd_is_ufs_dev_poweroff(h) \ ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE) + #define ufshcd_is_ufs_dev_deepsleep(h) \ + ((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE)
/* * UFS Power management levels. - * Each level is in increasing order of power savings. + * Each level is in increasing order of power savings, except DeepSleep + * which is lower than PowerDown with power on but not PowerDown with + * power off. */ enum ufs_pm_level { UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */ @@@ -134,6 -161,7 +163,7 @@@ UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */ UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE */ UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */ + UFS_PM_LVL_6, /* UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE */ UFS_PM_LVL_MAX };
@@@ -165,6 -193,7 +195,7 @@@ struct ufs_pm_lvl_states * @crypto_key_slot: the key slot to use for inline crypto (-1 if none) * @data_unit_num: the data unit number for the first block for inline crypto * @req_abort_skip: skip request abort task flag + * @in_use: indicates that this lrb is still in use */ struct ufshcd_lrb { struct utp_transfer_req_desc *utr_descriptor_ptr; @@@ -194,6 -223,7 +225,7 @@@ #endif
bool req_abort_skip; + bool in_use; };
/** @@@ -229,6 -259,8 +261,8 @@@ struct ufs_dev_cmd * @max_freq: maximum frequency supported by the clock * @min_freq: min frequency that can be used for clock scaling * @curr_freq: indicates the current frequency that it is set to + * @keep_link_active: indicates that the clk should not be disabled if + link is active * @enabled: variable to check against multiple enable/disable */ struct ufs_clk_info { @@@ -238,6 -270,7 +272,7 @@@ u32 max_freq; u32 min_freq; u32 curr_freq; + bool keep_link_active; bool enabled; };
@@@ -269,7 -302,6 +304,6 @@@ struct ufs_pwr_mode_info * @get_ufs_hci_version: called to get UFS HCI version * @clk_scale_notify: notifies that clks are scaled up/down * @setup_clocks: called before touching any of the controller registers - * @setup_regulators: called before accessing the host controller * @hce_enable_notify: called before and after HCE enable bit is set to allow * variant specific Uni-Pro initialization. * @link_startup_notify: called before and after Link startup is carried out @@@ -289,6 -321,7 +323,7 @@@ * @phy_initialization: used to initialize phys * @device_reset: called to issue a reset pulse on the UFS device * @program_key: program or evict an inline encryption key + * @event_notify: called to notify important events */ struct ufs_hba_variant_ops { const char *name; @@@ -299,7 -332,6 +334,6 @@@ enum ufs_notify_change_status); int (*setup_clocks)(struct ufs_hba *, bool, enum ufs_notify_change_status); - int (*setup_regulators)(struct ufs_hba *, bool); int (*hce_enable_notify)(struct ufs_hba *, enum ufs_notify_change_status); int (*link_startup_notify)(struct ufs_hba *, @@@ -318,12 -350,14 +352,14 @@@ int (*resume)(struct ufs_hba *, enum ufs_pm_op); void (*dbg_register_dump)(struct ufs_hba *hba); int (*phy_initialization)(struct ufs_hba *); - void (*device_reset)(struct ufs_hba *hba); + int (*device_reset)(struct ufs_hba *hba); void (*config_scaling_param)(struct ufs_hba *hba, struct devfreq_dev_profile *profile, void *data); int (*program_key)(struct ufs_hba *hba, const union ufs_crypto_cfg_entry *cfg, int slot); + void (*event_notify)(struct ufs_hba *hba, + enum ufs_event_type evt, void *data); };
/* clock gating state */ @@@ -382,6 -416,7 +418,7 @@@ struct ufs_saved_pwr_info * @workq: workqueue to schedule devfreq suspend/resume work * @suspend_work: worker to suspend devfreq * @resume_work: worker to resume devfreq + * @min_gear: lowest HS gear to scale down to * @is_allowed: tracks if scaling is currently allowed or not * @is_busy_started: tracks if busy period has started or not * @is_suspended: tracks if devfreq is suspended or not @@@ -396,22 -431,23 +433,23 @@@ struct ufs_clk_scaling struct workqueue_struct *workq; struct work_struct suspend_work; struct work_struct resume_work; + u32 min_gear; bool is_allowed; bool is_busy_started; bool is_suspended; };
- #define UFS_ERR_REG_HIST_LENGTH 8 + #define UFS_EVENT_HIST_LENGTH 8 /** - * struct ufs_err_reg_hist - keeps history of errors + * struct ufs_event_hist - keeps history of errors * @pos: index to indicate cyclic buffer position * @reg: cyclic buffer for registers value * @tstamp: cyclic buffer for time stamp */ - struct ufs_err_reg_hist { + struct ufs_event_hist { int pos; - u32 reg[UFS_ERR_REG_HIST_LENGTH]; - ktime_t tstamp[UFS_ERR_REG_HIST_LENGTH]; + u32 val[UFS_EVENT_HIST_LENGTH]; + ktime_t tstamp[UFS_EVENT_HIST_LENGTH]; };
/** @@@ -422,19 -458,6 +460,6 @@@ * reset this after link-startup. * @last_hibern8_exit_tstamp: Set time after the hibern8 exit. * Clear after the first successful command completion. - * @pa_err: tracks pa-uic errors - * @dl_err: tracks dl-uic errors - * @nl_err: tracks nl-uic errors - * @tl_err: tracks tl-uic errors - * @dme_err: tracks dme errors - * @auto_hibern8_err: tracks auto-hibernate errors - * @fatal_err: tracks fatal errors - * @linkup_err: tracks link-startup errors - * @resume_err: tracks resume errors - * @suspend_err: tracks suspend errors - * @dev_reset: tracks device reset events - * @host_reset: tracks host reset events - * @tsk_abort: tracks task abort events */ struct ufs_stats { u32 last_intr_status; @@@ -442,25 -465,7 +467,7 @@@
u32 hibern8_exit_cnt; ktime_t last_hibern8_exit_tstamp; - - /* uic specific errors */ - struct ufs_err_reg_hist pa_err; - struct ufs_err_reg_hist dl_err; - struct ufs_err_reg_hist nl_err; - struct ufs_err_reg_hist tl_err; - struct ufs_err_reg_hist dme_err; - - /* fatal errors */ - struct ufs_err_reg_hist auto_hibern8_err; - struct ufs_err_reg_hist fatal_err; - struct ufs_err_reg_hist link_startup_err; - struct ufs_err_reg_hist resume_err; - struct ufs_err_reg_hist suspend_err; - - /* abnormal events */ - struct ufs_err_reg_hist dev_reset; - struct ufs_err_reg_hist host_reset; - struct ufs_err_reg_hist task_abort; + struct ufs_event_hist event[UFS_EVT_CNT]; };
enum ufshcd_quirks { @@@ -594,6 -599,21 +601,21 @@@ enum ufshcd_caps * inline crypto engine, if it is present */ UFSHCD_CAP_CRYPTO = 1 << 8, + + /* + * This capability allows the controller regulators to be put into + * lpm mode aggressively during clock gating. + * This would increase power savings. + */ + UFSHCD_CAP_AGGR_POWER_COLLAPSE = 1 << 9, + + /* + * This capability allows the host controller driver to use DeepSleep, + * if it is supported by the UFS device. The host controller driver must + * support device hardware reset via the hba->device_reset() callback, + * in order to exit DeepSleep state. + */ + UFSHCD_CAP_DEEPSLEEP = 1 << 10, };
struct ufs_hba_variant_params { @@@ -683,6 -703,7 +705,7 @@@ struct ufs_hba * "UFS device" W-LU. */ struct scsi_device *sdev_ufs_device; + struct scsi_device *sdev_rpmb;
enum ufs_dev_pwr_mode curr_dev_pwr_mode; enum uic_link_state uic_link_state; @@@ -730,6 -751,7 +753,7 @@@ u32 intr_mask; u16 ee_ctrl_mask; bool is_powered; + struct semaphore eh_sem;
/* Work Queues */ struct workqueue_struct *eh_wq; @@@ -831,6 -853,12 +855,12 @@@ return true #endif }
+ static inline bool ufshcd_can_aggressive_pc(struct ufs_hba *hba) + { + return !!(ufshcd_is_link_hibern8(hba) && + (hba->caps & UFSHCD_CAP_AGGR_POWER_COLLAPSE)); + } + static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba) { return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) && @@@ -882,8 -910,7 +912,7 @@@ int ufshcd_wait_for_register(struct ufs u32 val, unsigned long interval_us, unsigned long timeout_ms); void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk); - void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist, - u32 reg); + void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val);
static inline void check_upiu_size(void) { @@@ -930,6 -957,9 +959,9 @@@ extern int ufshcd_runtime_idle(struct u extern int ufshcd_system_suspend(struct ufs_hba *hba); extern int ufshcd_system_resume(struct ufs_hba *hba); extern int ufshcd_shutdown(struct ufs_hba *hba); + extern int ufshcd_dme_configure_adapt(struct ufs_hba *hba, + int agreed_gear, + int adapt_val); extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, u8 attr_set, u32 mib_val, u8 peer); extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel, @@@ -1076,6 -1106,14 +1108,14 @@@ static inline int ufshcd_vops_clk_scale return 0; }
+ static inline void ufshcd_vops_event_notify(struct ufs_hba *hba, + enum ufs_event_type evt, + void *data) + { + if (hba->vops && hba->vops->event_notify) + hba->vops->event_notify(hba, evt, data); + } + static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on, enum ufs_notify_change_status status) { @@@ -1084,14 -1122,6 +1124,6 @@@ return 0; }
- static inline int ufshcd_vops_setup_regulators(struct ufs_hba *hba, bool status) - { - if (hba->vops && hba->vops->setup_regulators) - return hba->vops->setup_regulators(hba, status); - - return 0; - } - static inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba, bool status) { @@@ -1109,6 -1139,14 +1141,14 @@@ static inline int ufshcd_vops_link_star return 0; }
+ static inline int ufshcd_vops_phy_initialization(struct ufs_hba *hba) + { + if (hba->vops && hba->vops->phy_initialization) + return hba->vops->phy_initialization(hba); + + return 0; + } + static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba, bool status, struct ufs_pa_layer_attr *dev_max_params, @@@ -1181,9 -1219,12 +1221,12 @@@ static inline void ufshcd_vops_dbg_regi static inline void ufshcd_vops_device_reset(struct ufs_hba *hba) { if (hba->vops && hba->vops->device_reset) { - hba->vops->device_reset(hba); - ufshcd_set_ufs_dev_active(hba); - ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0); + int err = hba->vops->device_reset(hba); + + if (!err) + ufshcd_set_ufs_dev_active(hba); + if (err != -EOPNOTSUPP) + ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, err); } }
diff --combined drivers/target/target_core_user.c index 590e6d072228,0458bfb143f8..6b171fff007b --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@@ -194,7 -194,7 +194,7 @@@ struct tcmu_tmr
uint8_t tmr_type; uint32_t tmr_cmd_cnt; - int16_t tmr_cmd_ids[0]; + int16_t tmr_cmd_ids[]; };
/* @@@ -586,14 -586,15 +586,15 @@@ static inline void tcmu_cmd_set_block_c }
static int new_block_to_iov(struct tcmu_dev *udev, struct tcmu_cmd *cmd, - struct iovec **iov, int prev_dbi, int *remain) + struct iovec **iov, int prev_dbi, int len) { /* Get the next dbi */ int dbi = tcmu_cmd_get_dbi(cmd); + /* Do not add more than DATA_BLOCK_SIZE to iov */ - int len = min_t(int, DATA_BLOCK_SIZE, *remain); + if (len > DATA_BLOCK_SIZE) + len = DATA_BLOCK_SIZE;
- *remain -= len; /* * The following code will gather and map the blocks to the same iovec * when the blocks are all next to each other. @@@ -618,8 -619,8 +619,8 @@@ static void tcmu_setup_iovs(struct tcmu int dbi = -2;
/* We prepare the IOVs for DMA_FROM_DEVICE transfer direction */ - while (data_length > 0) - dbi = new_block_to_iov(udev, cmd, iov, dbi, &data_length); + for (; data_length > 0; data_length -= DATA_BLOCK_SIZE) + dbi = new_block_to_iov(udev, cmd, iov, dbi, data_length); }
static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd) @@@ -688,67 -689,83 +689,83 @@@ static inline size_t head_to_end(size_
#define UPDATE_HEAD(head, used, size) smp_store_release(&head, ((head % size) + used) % size)
- static void scatter_data_area(struct tcmu_dev *udev, struct tcmu_cmd *tcmu_cmd, - struct iovec **iov) + #define TCMU_SG_TO_DATA_AREA 1 + #define TCMU_DATA_AREA_TO_SG 2 + + static inline void tcmu_copy_data(struct tcmu_dev *udev, + struct tcmu_cmd *tcmu_cmd, uint32_t direction, + struct scatterlist *sg, unsigned int sg_nents, + struct iovec **iov, size_t data_len) { - struct se_cmd *se_cmd = tcmu_cmd->se_cmd; /* start value of dbi + 1 must not be a valid dbi */ - int i, dbi = -2; - int block_remaining = 0; - int data_len = se_cmd->data_length; - void *from, *to = NULL; - size_t copy_bytes, offset; - struct scatterlist *sg; - struct page *page = NULL; - - for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, i) { - int sg_remaining = sg->length; - from = kmap_atomic(sg_page(sg)) + sg->offset; - while (sg_remaining > 0) { - if (block_remaining == 0) { - if (to) { - flush_dcache_page(page); - kunmap_atomic(to); - } - - /* get next dbi and add to IOVs */ - dbi = new_block_to_iov(udev, tcmu_cmd, iov, dbi, - &data_len); - page = tcmu_get_block_page(udev, dbi); - to = kmap_atomic(page); - block_remaining = DATA_BLOCK_SIZE; - } - - copy_bytes = min_t(size_t, sg_remaining, - block_remaining); - offset = DATA_BLOCK_SIZE - block_remaining; - memcpy(to + offset, from + sg->length - sg_remaining, - copy_bytes); + int dbi = -2; + size_t block_remaining, cp_len; + struct sg_mapping_iter sg_iter; + unsigned int sg_flags; + struct page *page; + void *data_page_start, *data_addr;
- sg_remaining -= copy_bytes; - block_remaining -= copy_bytes; + if (direction == TCMU_SG_TO_DATA_AREA) + sg_flags = SG_MITER_ATOMIC | SG_MITER_FROM_SG; + else + sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG; + sg_miter_start(&sg_iter, sg, sg_nents, sg_flags); + + while (data_len) { + if (direction == TCMU_SG_TO_DATA_AREA) + dbi = new_block_to_iov(udev, tcmu_cmd, iov, dbi, + data_len); + else + dbi = tcmu_cmd_get_dbi(tcmu_cmd); + page = tcmu_get_block_page(udev, dbi); + if (direction == TCMU_DATA_AREA_TO_SG) + flush_dcache_page(page); + data_page_start = kmap_atomic(page); + block_remaining = DATA_BLOCK_SIZE; + + while (block_remaining && data_len) { + if (!sg_miter_next(&sg_iter)) { + /* set length to 0 to abort outer loop */ + data_len = 0; + pr_debug("tcmu_move_data: aborting data copy due to exhausted sg_list\n"); + break; + } + cp_len = min3(sg_iter.length, block_remaining, data_len); + + data_addr = data_page_start + + DATA_BLOCK_SIZE - block_remaining; + if (direction == TCMU_SG_TO_DATA_AREA) + memcpy(data_addr, sg_iter.addr, cp_len); + else + memcpy(sg_iter.addr, data_addr, cp_len); + + data_len -= cp_len; + block_remaining -= cp_len; + sg_iter.consumed = cp_len; } - kunmap_atomic(from - sg->offset); - } + sg_miter_stop(&sg_iter);
- if (to) { - flush_dcache_page(page); - kunmap_atomic(to); + kunmap_atomic(data_page_start); + if (direction == TCMU_SG_TO_DATA_AREA) + flush_dcache_page(page); } }
- static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd, + static void scatter_data_area(struct tcmu_dev *udev, struct tcmu_cmd *tcmu_cmd, + struct iovec **iov) + { + struct se_cmd *se_cmd = tcmu_cmd->se_cmd; + + tcmu_copy_data(udev, tcmu_cmd, TCMU_SG_TO_DATA_AREA, se_cmd->t_data_sg, + se_cmd->t_data_nents, iov, se_cmd->data_length); + } + + static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *tcmu_cmd, bool bidi, uint32_t read_len) { - struct se_cmd *se_cmd = cmd->se_cmd; - int i, dbi; - int block_remaining = 0; - void *from = NULL, *to; - size_t copy_bytes, offset; - struct scatterlist *sg, *data_sg; - struct page *page; + struct se_cmd *se_cmd = tcmu_cmd->se_cmd; + struct scatterlist *data_sg; unsigned int data_nents; - uint32_t count = 0;
if (!bidi) { data_sg = se_cmd->t_data_sg; @@@ -759,46 -776,15 +776,15 @@@ * buffer blocks, and before gathering the Data-In buffer * the Data-Out buffer blocks should be skipped. */ - count = cmd->dbi_cnt - cmd->dbi_bidi_cnt; + tcmu_cmd_set_dbi_cur(tcmu_cmd, + tcmu_cmd->dbi_cnt - tcmu_cmd->dbi_bidi_cnt);
data_sg = se_cmd->t_bidi_data_sg; data_nents = se_cmd->t_bidi_data_nents; }
- tcmu_cmd_set_dbi_cur(cmd, count); - - for_each_sg(data_sg, sg, data_nents, i) { - int sg_remaining = sg->length; - to = kmap_atomic(sg_page(sg)) + sg->offset; - while (sg_remaining > 0 && read_len > 0) { - if (block_remaining == 0) { - if (from) - kunmap_atomic(from); - - block_remaining = DATA_BLOCK_SIZE; - dbi = tcmu_cmd_get_dbi(cmd); - page = tcmu_get_block_page(udev, dbi); - from = kmap_atomic(page); - flush_dcache_page(page); - } - copy_bytes = min_t(size_t, sg_remaining, - block_remaining); - if (read_len < copy_bytes) - copy_bytes = read_len; - offset = DATA_BLOCK_SIZE - block_remaining; - memcpy(to + sg->length - sg_remaining, from + offset, - copy_bytes); - - sg_remaining -= copy_bytes; - block_remaining -= copy_bytes; - read_len -= copy_bytes; - } - kunmap_atomic(to - sg->offset); - if (read_len == 0) - break; - } - if (from) - kunmap_atomic(from); + tcmu_copy_data(udev, tcmu_cmd, TCMU_DATA_AREA_TO_SG, data_sg, + data_nents, NULL, read_len); }
static inline size_t spc_bitmap_free(unsigned long *bitmap, uint32_t thresh)