Cross-merge networking fixes after downstream PR (net-6.17-rc4). No conflicts. Adjacent changes: drivers/net/ethernet/intel/idpf/idpf_txrx.c 02614eee26fb ("idpf: do not linearize big TSO packets") 6c4e68480238 ("idpf: remove obsolete stashing code")
Unified · Split
| @@ -226,6 +226,8 @@ Domen Puncer <domen@coderock.org> · 225 unmodified lines | ||
| 226 | 226 | Douglas Gilbert <dougg@torque.net> |
| 227 | 227 | Drew Fustini <fustini@kernel.org> <drew@pdp7.com> |
| 228 | 228 | <duje@dujemihanovic.xyz> <duje.mihanovic@skole.hr> |
| 229 | +Easwar Hariharan <easwar.hariharan@linux.microsoft.com> <easwar.hariharan@intel.com> | |
| 230 | +Easwar Hariharan <easwar.hariharan@linux.microsoft.com> <eahariha@linux.microsoft.com> | |
| 229 | 231 | Ed L. Cashin <ecashin@coraid.com> |
| 230 | 232 | Elliot Berman <quic_eberman@quicinc.com> <eberman@codeaurora.org> |
| 231 | 233 | Enric Balletbo i Serra <eballetbo@kernel.org> <enric.balletbo@collabora.com> |
| @@ -3222,6 +3222,10 @@ D: AIC5800 IEEE 1394, RAW I/O on 1394 · 3221 unmodified lines | ||
| 3222 | 3222 | D: Starter of Linux1394 effort |
| 3223 | 3223 | S: ask per mail for current address |
| 3224 | 3224 | |
| 3225 | +N: Boris Pismenny | |
| 3226 | +E: borisp@mellanox.com | |
| 3227 | +D: Kernel TLS implementation and offload support. | |
| 3228 | + | |
| 3225 | 3229 | N: Nicolas Pitre |
| 3226 | 3230 | E: nico@fluxnic.net |
| 3227 | 3231 | D: StrongARM SA1100 support integrator & hacker |
| @@ -4168,6 +4172,9 @@ S: 1513 Brewster Dr. · 940 unmodified lines | ||
| 4168 | 4172 | S: Carrollton, TX 75010 |
| 4169 | 4173 | S: USA |
| 4170 | 4174 | |
| 4175 | +N: Dave Watson | |
| 4176 | +D: Kernel TLS implementation. | |
| 4177 | + | |
| 4171 | 4178 | N: Tim Waugh |
| 4172 | 4179 | E: tim@cyberelk.net |
| 4173 | 4180 | D: Co-architect of the parallel-port sharing system |
| @@ -435,8 +435,8 @@ both cgroups. · 434 unmodified lines | ||
| 435 | 435 | Controlling Controllers |
| 436 | 436 | ----------------------- |
| 437 | 437 | |
| 438 | −Availablity | |
| 439 | −~~~~~~~~~~~ | |
| 438 | +Availability | |
| 439 | +~~~~~~~~~~~~ | |
| 440 | 440 | |
| 441 | 441 | A controller is available in a cgroup when it is supported by the kernel (i.e., |
| 442 | 442 | compiled in, not disabled and not attached to a v1 hierarchy) and listed in the |
| @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | ||
| 7 | 7 | title: Infineon Buck Regulators with PMBUS interfaces |
| 8 | 8 | |
| 9 | 9 | maintainers: |
| 10 | − - Not Me. | |
| 10 | + - Guenter Roeck <linux@roeck-us.net> | |
| 11 | 11 | |
| 12 | 12 | allOf: |
| 13 | 13 | - $ref: regulator.yaml# |
| @@ -507,6 +507,8 @@ patternProperties: · 506 unmodified lines | ||
| 507 | 507 | description: Espressif Systems Co. Ltd. |
| 508 | 508 | "^est,.*": |
| 509 | 509 | description: ESTeem Wireless Modems |
| 510 | + "^eswin,.*": | |
| 511 | + description: Beijing ESWIN Technology Group Co. Ltd. | |
| 510 | 512 | "^ettus,.*": |
| 511 | 513 | description: NI Ettus Research |
| 512 | 514 | "^eukrea,.*": |
| @@ -8,8 +8,22 @@ like to know when a security bug is found so that it can be fixed and · 7 unmodified lines | ||
| 8 | 8 | disclosed as quickly as possible. Please report security bugs to the |
| 9 | 9 | Linux kernel security team. |
| 10 | 10 | |
| 11 | −Contact | |
| 12 | −------- | |
| 11 | +The security team and maintainers almost always require additional | |
| 12 | +information beyond what was initially provided in a report and rely on | |
| 13 | +active and efficient collaboration with the reporter to perform further | |
| 14 | +testing (e.g., verifying versions, configuration options, mitigations, or | |
| 15 | +patches). Before contacting the security team, the reporter must ensure | |
| 16 | +they are available to explain their findings, engage in discussions, and | |
| 17 | +run additional tests. Reports where the reporter does not respond promptly | |
| 18 | +or cannot effectively discuss their findings may be abandoned if the | |
| 19 | +communication does not quickly improve. | |
| 20 | + | |
| 21 | +As it is with any bug, the more information provided the easier it | |
| 22 | +will be to diagnose and fix. Please review the procedure outlined in | |
| 23 | +'Documentation/admin-guide/reporting-issues.rst' if you are unclear about what | |
| 24 | +information is helpful. Any exploit code is very helpful and will not | |
| 25 | +be released without consent from the reporter unless it has already been | |
| 26 | +made public. | |
| 13 | 27 | |
| 14 | 28 | The Linux kernel security team can be contacted by email at |
| 15 | 29 | <security@kernel.org>. This is a private list of security officers |
| @@ -19,13 +33,6 @@ that can speed up the process considerably. It is possible that the · 3 unmodified lines | ||
| 19 | 33 | security team will bring in extra help from area maintainers to |
| 20 | 34 | understand and fix the security vulnerability. |
| 21 | 35 | |
| 22 | −As it is with any bug, the more information provided the easier it | |
| 23 | −will be to diagnose and fix. Please review the procedure outlined in | |
| 24 | −'Documentation/admin-guide/reporting-issues.rst' if you are unclear about what | |
| 25 | −information is helpful. Any exploit code is very helpful and will not | |
| 26 | −be released without consent from the reporter unless it has already been | |
| 27 | −made public. | |
| 28 | − | |
| 29 | 36 | Please send plain text emails without attachments where possible. |
| 30 | 37 | It is much harder to have a context-quoted discussion about a complex |
| 31 | 38 | issue if all the details are hidden away in attachments. Think of it like a |
| @@ -43,7 +43,7 @@ Following IOMMUFD objects are exposed to userspace: · 42 unmodified lines | ||
| 43 | 43 | |
| 44 | 44 | - IOMMUFD_OBJ_HWPT_PAGING, representing an actual hardware I/O page table |
| 45 | 45 | (i.e. a single struct iommu_domain) managed by the iommu driver. "PAGING" |
| 46 | − primarly indicates this type of HWPT should be linked to an IOAS. It also | |
| 46 | + primarily indicates this type of HWPT should be linked to an IOAS. It also | |
| 47 | 47 | indicates that it is backed by an iommu_domain with __IOMMU_DOMAIN_PAGING |
| 48 | 48 | feature flag. This can be either an UNMANAGED stage-1 domain for a device |
| 49 | 49 | running in the user space, or a nesting parent stage-2 domain for mappings |
| @@ -76,7 +76,7 @@ Following IOMMUFD objects are exposed to userspace: · 26 unmodified lines | ||
| 76 | 76 | |
| 77 | 77 | * Security namespace for guest owned ID, e.g. guest-controlled cache tags |
| 78 | 78 | * Non-device-affiliated event reporting, e.g. invalidation queue errors |
| 79 | − * Access to a sharable nesting parent pagetable across physical IOMMUs | |
| 79 | + * Access to a shareable nesting parent pagetable across physical IOMMUs | |
| 80 | 80 | * Virtualization of various platforms IDs, e.g. RIDs and others |
| 81 | 81 | * Delivery of paravirtualized invalidation |
| 82 | 82 | * Direct assigned invalidation queues |
| @@ -937,7 +937,7 @@ S: Maintained · 936 unmodified lines | ||
| 937 | 937 | F: drivers/gpio/gpio-altera.c |
| 938 | 938 | |
| 939 | 939 | ALTERA TRIPLE SPEED ETHERNET DRIVER |
| 940 | −M: Joyce Ooi <joyce.ooi@intel.com> | |
| 940 | +M: Boon Khai Ng <boon.khai.ng@altera.com> | |
| 941 | 941 | L: netdev@vger.kernel.org |
| 942 | 942 | S: Maintained |
| 943 | 943 | F: drivers/net/ethernet/altera/ |
| @@ -4216,7 +4216,7 @@ F: drivers/md/bcache/ · 3272 unmodified lines | ||
| 4216 | 4216 | BCACHEFS |
| 4217 | 4217 | M: Kent Overstreet <kent.overstreet@linux.dev> |
| 4218 | 4218 | L: linux-bcachefs@vger.kernel.org |
| 4219 | −S: Supported | |
| 4219 | +S: Externally maintained | |
| 4220 | 4220 | C: irc://irc.oftc.net/bcache |
| 4221 | 4221 | P: Documentation/filesystems/bcachefs/SubmittingPatches.rst |
| 4222 | 4222 | T: git https://evilpiepirate.org/git/bcachefs.git |
| @@ -8427,6 +8427,17 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git · 4204 unmodified lines | ||
| 8427 | 8427 | F: drivers/gpu/drm/scheduler/ |
| 8428 | 8428 | F: include/drm/gpu_scheduler.h |
| 8429 | 8429 | |
| 8430 | +DRM GPUVM | |
| 8431 | +M: Danilo Krummrich <dakr@kernel.org> | |
| 8432 | +R: Matthew Brost <matthew.brost@intel.com> | |
| 8433 | +R: Thomas Hellström <thomas.hellstrom@linux.intel.com> | |
| 8434 | +R: Alice Ryhl <aliceryhl@google.com> | |
| 8435 | +L: dri-devel@lists.freedesktop.org | |
| 8436 | +S: Supported | |
| 8437 | +T: git https://gitlab.freedesktop.org/drm/misc/kernel.git | |
| 8438 | +F: drivers/gpu/drm/drm_gpuvm.c | |
| 8439 | +F: include/drm/drm_gpuvm.h | |
| 8440 | + | |
| 8430 | 8441 | DRM LOG |
| 8431 | 8442 | M: Jocelyn Falempe <jfalempe@redhat.com> |
| 8432 | 8443 | M: Javier Martinez Canillas <javierm@redhat.com> |
| @@ -10656,7 +10667,8 @@ S: Maintained · 2223 unmodified lines | ||
| 10656 | 10667 | F: block/partitions/efi.* |
| 10657 | 10668 | |
| 10658 | 10669 | HABANALABS PCI DRIVER |
| 10659 | −M: Yaron Avizrat <yaron.avizrat@intel.com> | |
| 10670 | +M: Koby Elbaz <koby.elbaz@intel.com> | |
| 10671 | +M: Konstantin Sinyuk <konstantin.sinyuk@intel.com> | |
| 10660 | 10672 | L: dri-devel@lists.freedesktop.org |
| 10661 | 10673 | S: Supported |
| 10662 | 10674 | C: irc://irc.oftc.net/dri-devel |
| @@ -11014,7 +11026,7 @@ F: Documentation/admin-guide/perf/hns3-pmu.rst · 351 unmodified lines | ||
| 11014 | 11026 | F: drivers/perf/hisilicon/hns3_pmu.c |
| 11015 | 11027 | |
| 11016 | 11028 | HISILICON I2C CONTROLLER DRIVER |
| 11017 | −M: Yicong Yang <yangyicong@hisilicon.com> | |
| 11029 | +M: Devyn Liu <liudingyuan@h-partners.com> | |
| 11018 | 11030 | L: linux-i2c@vger.kernel.org |
| 11019 | 11031 | S: Maintained |
| 11020 | 11032 | W: https://www.hisilicon.com |
| @@ -12282,7 +12294,6 @@ F: include/linux/avf/virtchnl.h · 1261 unmodified lines | ||
| 12282 | 12294 | F: include/linux/net/intel/*/ |
| 12283 | 12295 | |
| 12284 | 12296 | INTEL ETHERNET PROTOCOL DRIVER FOR RDMA |
| 12285 | −M: Mustafa Ismail <mustafa.ismail@intel.com> | |
| 12286 | 12297 | M: Tatyana Nikolova <tatyana.e.nikolova@intel.com> |
| 12287 | 12298 | L: linux-rdma@vger.kernel.org |
| 12288 | 12299 | S: Supported |
| @@ -16059,6 +16070,23 @@ F: mm/mempolicy.c · 3770 unmodified lines | ||
| 16059 | 16070 | F: mm/migrate.c |
| 16060 | 16071 | F: mm/migrate_device.c |
| 16061 | 16072 | |
| 16073 | +MEMORY MANAGEMENT - MGLRU (MULTI-GEN LRU) | |
| 16074 | +M: Andrew Morton <akpm@linux-foundation.org> | |
| 16075 | +M: Axel Rasmussen <axelrasmussen@google.com> | |
| 16076 | +M: Yuanchu Xie <yuanchu@google.com> | |
| 16077 | +R: Wei Xu <weixugc@google.com> | |
| 16078 | +L: linux-mm@kvack.org | |
| 16079 | +S: Maintained | |
| 16080 | +W: http://www.linux-mm.org | |
| 16081 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm | |
| 16082 | +F: Documentation/admin-guide/mm/multigen_lru.rst | |
| 16083 | +F: Documentation/mm/multigen_lru.rst | |
| 16084 | +F: include/linux/mm_inline.h | |
| 16085 | +F: include/linux/mmzone.h | |
| 16086 | +F: mm/swap.c | |
| 16087 | +F: mm/vmscan.c | |
| 16088 | +F: mm/workingset.c | |
| 16089 | + | |
| 16062 | 16090 | MEMORY MANAGEMENT - MISC |
| 16063 | 16091 | M: Andrew Morton <akpm@linux-foundation.org> |
| 16064 | 16092 | M: David Hildenbrand <david@redhat.com> |
| @@ -16249,8 +16277,10 @@ S: Maintained · 184 unmodified lines | ||
| 16249 | 16277 | W: http://www.linux-mm.org |
| 16250 | 16278 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm |
| 16251 | 16279 | F: rust/helpers/mm.c |
| 16280 | +F: rust/helpers/page.c | |
| 16252 | 16281 | F: rust/kernel/mm.rs |
| 16253 | 16282 | F: rust/kernel/mm/ |
| 16283 | +F: rust/kernel/page.rs | |
| 16254 | 16284 | |
| 16255 | 16285 | MEMORY MAPPING |
| 16256 | 16286 | M: Andrew Morton <akpm@linux-foundation.org> |
| @@ -17819,7 +17849,6 @@ F: net/ipv6/syncookies.c · 1562 unmodified lines | ||
| 17819 | 17849 | F: net/ipv6/tcp*.c |
| 17820 | 17850 | |
| 17821 | 17851 | NETWORKING [TLS] |
| 17822 | −M: Boris Pismenny <borisp@nvidia.com> | |
| 17823 | 17852 | M: John Fastabend <john.fastabend@gmail.com> |
| 17824 | 17853 | M: Jakub Kicinski <kuba@kernel.org> |
| 17825 | 17854 | L: netdev@vger.kernel.org |
| @@ -20857,8 +20886,8 @@ S: Maintained · 3031 unmodified lines | ||
| 20857 | 20886 | F: drivers/firmware/qcom/qcom_qseecom_uefisecapp.c |
| 20858 | 20887 | |
| 20859 | 20888 | QUALCOMM RMNET DRIVER |
| 20860 | −M: Subash Abhinov Kasiviswanathan <quic_subashab@quicinc.com> | |
| 20861 | −M: Sean Tranchetti <quic_stranche@quicinc.com> | |
| 20889 | +M: Subash Abhinov Kasiviswanathan <subash.a.kasiviswanathan@oss.qualcomm.com> | |
| 20890 | +M: Sean Tranchetti <sean.tranchetti@oss.qualcomm.com> | |
| 20862 | 20891 | L: netdev@vger.kernel.org |
| 20863 | 20892 | S: Maintained |
| 20864 | 20893 | F: Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 17 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc2 | |
| 5 | +EXTRAVERSION = -rc3 | |
| 6 | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -82,13 +82,16 @@ · 81 unmodified lines | ||
| 82 | 82 | }; |
| 83 | 83 | }; |
| 84 | 84 | |
| 85 | − etop@e180000 { | |
| 85 | + ethernet@e180000 { | |
| 86 | 86 | compatible = "lantiq,etop-xway"; |
| 87 | 87 | reg = <0xe180000 0x40000>; |
| 88 | 88 | interrupt-parent = <&icu0>; |
| 89 | 89 | interrupts = <73 78>; |
| 90 | + interrupt-names = "tx", "rx"; | |
| 90 | 91 | phy-mode = "rmii"; |
| 91 | 92 | mac-address = [ 00 11 22 33 44 55 ]; |
| 93 | + lantiq,rx-burst-length = <4>; | |
| 94 | + lantiq,tx-burst-length = <4>; | |
| 92 | 95 | }; |
| 93 | 96 | |
| 94 | 97 | stp0: stp@e100bb0 { |
| @@ -497,7 +497,7 @@ void __init ltq_soc_init(void) · 496 unmodified lines | ||
| 497 | 497 | ifccr = CGU_IFCCR_VR9; |
| 498 | 498 | pcicr = CGU_PCICR_VR9; |
| 499 | 499 | } else { |
| 500 | − clkdev_add_pmu("1e180000.etop", NULL, 1, 0, PMU_PPE); | |
| 500 | + clkdev_add_pmu("1e180000.ethernet", NULL, 1, 0, PMU_PPE); | |
| 501 | 501 | } |
| 502 | 502 | |
| 503 | 503 | if (!of_machine_is_compatible("lantiq,ase")) |
| @@ -531,9 +531,9 @@ void __init ltq_soc_init(void) · 27 unmodified lines | ||
| 531 | 531 | CLOCK_133M, CLOCK_133M); |
| 532 | 532 | clkdev_add_pmu("1e101000.usb", "otg", 1, 0, PMU_USB0); |
| 533 | 533 | clkdev_add_pmu("1f203018.usb2-phy", "phy", 1, 0, PMU_USB0_P); |
| 534 | − clkdev_add_pmu("1e180000.etop", "ppe", 1, 0, PMU_PPE); | |
| 535 | − clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY); | |
| 536 | − clkdev_add_pmu("1e180000.etop", "ephy", 1, 0, PMU_EPHY); | |
| 534 | + clkdev_add_pmu("1e180000.ethernet", "ppe", 1, 0, PMU_PPE); | |
| 535 | + clkdev_add_cgu("1e180000.ethernet", "ephycgu", CGU_EPHY); | |
| 536 | + clkdev_add_pmu("1e180000.ethernet", "ephy", 1, 0, PMU_EPHY); | |
| 537 | 537 | clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_ASE_SDIO); |
| 538 | 538 | clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); |
| 539 | 539 | } else if (of_machine_is_compatible("lantiq,grx390")) { |
| @@ -592,7 +592,7 @@ void __init ltq_soc_init(void) · 52 unmodified lines | ||
| 592 | 592 | clkdev_add_pmu("1e101000.usb", "otg", 1, 0, PMU_USB0 | PMU_AHBM); |
| 593 | 593 | clkdev_add_pmu("1f203034.usb2-phy", "phy", 1, 0, PMU_USB1_P); |
| 594 | 594 | clkdev_add_pmu("1e106000.usb", "otg", 1, 0, PMU_USB1 | PMU_AHBM); |
| 595 | − clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH); | |
| 595 | + clkdev_add_pmu("1e180000.ethernet", "switch", 1, 0, PMU_SWITCH); | |
| 596 | 596 | clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); |
| 597 | 597 | clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); |
| 598 | 598 | clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); |
| @@ -243,13 +243,13 @@ $(obj)/wrapper.a: $(obj-wlib) FORCE · 242 unmodified lines | ||
| 243 | 243 | hostprogs := addnote hack-coff mktree |
| 244 | 244 | |
| 245 | 245 | targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) zImage.lds |
| 246 | −extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ | |
| 246 | +always-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ | |
| 247 | 247 | $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds |
| 248 | 248 | |
| 249 | 249 | dtstree := $(src)/dts |
| 250 | 250 | |
| 251 | 251 | wrapper := $(src)/wrapper |
| 252 | −wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ | |
| 252 | +wrapperbits := $(always-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ | |
| 253 | 253 | $(wrapper) FORCE |
| 254 | 254 | |
| 255 | 255 | ############# |
| @@ -456,7 +456,7 @@ WRAPPER_DTSDIR := /usr/lib/kernel-wrapper/dts · 200 unmodified lines | ||
| 456 | 456 | WRAPPER_BINDIR := /usr/sbin |
| 457 | 457 | INSTALL := install |
| 458 | 458 | |
| 459 | −extra-installed := $(patsubst $(obj)/%, $(DESTDIR)$(WRAPPER_OBJDIR)/%, $(extra-y)) | |
| 459 | +extra-installed := $(patsubst $(obj)/%, $(DESTDIR)$(WRAPPER_OBJDIR)/%, $(always-y)) | |
| 460 | 460 | hostprogs-installed := $(patsubst %, $(DESTDIR)$(WRAPPER_BINDIR)/%, $(hostprogs)) |
| 461 | 461 | wrapper-installed := $(DESTDIR)$(WRAPPER_BINDIR)/wrapper |
| 462 | 462 | dts-installed := $(patsubst $(dtstree)/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(dtstree)/*.dts)) |
| @@ -19,19 +19,19 @@ · 18 unmodified lines | ||
| 19 | 19 | set -e |
| 20 | 20 | |
| 21 | 21 | # this should work for both the pSeries zImage and the iSeries vmlinux.sm |
| 22 | −image_name=`basename $2` | |
| 22 | +image_name=$(basename "$2") | |
| 23 | 23 | |
| 24 | 24 | |
| 25 | 25 | echo "Warning: '${INSTALLKERNEL}' command not available... Copying" \ |
| 26 | 26 | "directly to $4/$image_name-$1" >&2 |
| 27 | 27 | |
| 28 | −if [ -f $4/$image_name-$1 ]; then | |
| 29 | − mv $4/$image_name-$1 $4/$image_name-$1.old | |
| 28 | +if [ -f "$4"/"$image_name"-"$1" ]; then | |
| 29 | + mv "$4"/"$image_name"-"$1" "$4"/"$image_name"-"$1".old | |
| 30 | 30 | fi |
| 31 | 31 | |
| 32 | −if [ -f $4/System.map-$1 ]; then | |
| 33 | − mv $4/System.map-$1 $4/System-$1.old | |
| 32 | +if [ -f "$4"/System.map-"$1" ]; then | |
| 33 | + mv "$4"/System.map-"$1" "$4"/System-"$1".old | |
| 34 | 34 | fi |
| 35 | 35 | |
| 36 | −cat $2 > $4/$image_name-$1 | |
| 37 | −cp $3 $4/System.map-$1 | |
| 36 | +cat "$2" > "$4"/"$image_name"-"$1" | |
| 37 | +cp "$3" "$4"/System.map-"$1" | |
| @@ -199,7 +199,9 @@ obj-$(CONFIG_ALTIVEC) += vector.o · 198 unmodified lines | ||
| 199 | 199 | |
| 200 | 200 | obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init.o |
| 201 | 201 | obj64-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_entry_64.o |
| 202 | −extra-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init_check | |
| 202 | +ifdef KBUILD_BUILTIN | |
| 203 | +always-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init_check | |
| 204 | +endif | |
| 203 | 205 | |
| 204 | 206 | obj-$(CONFIG_PPC64) += $(obj64-y) |
| 205 | 207 | obj-$(CONFIG_PPC32) += $(obj32-y) |
| @@ -632,19 +632,19 @@ static void __init kvm_check_ins(u32 *inst, u32 features) · 631 unmodified lines | ||
| 632 | 632 | #endif |
| 633 | 633 | } |
| 634 | 634 | |
| 635 | − switch (inst_no_rt & ~KVM_MASK_RB) { | |
| 636 | 635 | #ifdef CONFIG_PPC_BOOK3S_32 |
| 636 | + switch (inst_no_rt & ~KVM_MASK_RB) { | |
| 637 | 637 | case KVM_INST_MTSRIN: |
| 638 | 638 | if (features & KVM_MAGIC_FEAT_SR) { |
| 639 | 639 | u32 inst_rb = _inst & KVM_MASK_RB; |
| 640 | 640 | kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); |
| 641 | 641 | } |
| 642 | 642 | break; |
| 643 | −#endif | |
| 644 | 643 | } |
| 644 | +#endif | |
| 645 | 645 | |
| 646 | − switch (_inst) { | |
| 647 | 646 | #ifdef CONFIG_BOOKE |
| 647 | + switch (_inst) { | |
| 648 | 648 | case KVM_INST_WRTEEI_0: |
| 649 | 649 | kvm_patch_ins_wrteei_0(inst); |
| 650 | 650 | break; |
| @@ -652,8 +652,8 @@ static void __init kvm_check_ins(u32 *inst, u32 features) · 1 unmodified line | ||
| 652 | 652 | case KVM_INST_WRTEEI_1: |
| 653 | 653 | kvm_patch_ins_wrtee(inst, 0, 1); |
| 654 | 654 | break; |
| 655 | −#endif | |
| 656 | 655 | } |
| 656 | +#endif | |
| 657 | 657 | } |
| 658 | 658 | |
| 659 | 659 | extern u32 kvm_template_start[]; |
| @@ -15,8 +15,8 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | has_renamed_memintrinsics() |
| 17 | 17 | { |
| 18 | − grep -q "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} && \ | |
| 19 | − ! grep -q "^CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX=y" ${KCONFIG_CONFIG} | |
| 18 | + grep -q "^CONFIG_KASAN=y$" "${KCONFIG_CONFIG}" && \ | |
| 19 | + ! grep -q "^CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX=y" "${KCONFIG_CONFIG}" | |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | if has_renamed_memintrinsics |
| @@ -42,15 +42,15 @@ check_section() · 19 unmodified lines | ||
| 42 | 42 | { |
| 43 | 43 | file=$1 |
| 44 | 44 | section=$2 |
| 45 | − size=$(objdump -h -j $section $file 2>/dev/null | awk "\$2 == \"$section\" {print \$3}") | |
| 45 | + size=$(objdump -h -j "$section" "$file" 2>/dev/null | awk "\$2 == \"$section\" {print \$3}") | |
| 46 | 46 | size=${size:-0} |
| 47 | − if [ $size -ne 0 ]; then | |
| 47 | + if [ "$size" -ne 0 ]; then | |
| 48 | 48 | ERROR=1 |
| 49 | 49 | echo "Error: Section $section not empty in prom_init.c" >&2 |
| 50 | 50 | fi |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | −for UNDEF in $($NM -u $OBJ | awk '{print $2}') | |
| 53 | +for UNDEF in $($NM -u "$OBJ" | awk '{print $2}') | |
| 54 | 54 | do |
| 55 | 55 | # On 64-bit nm gives us the function descriptors, which have |
| 56 | 56 | # a leading . on the name, so strip it off here. |
| @@ -87,8 +87,8 @@ do · 30 unmodified lines | ||
| 87 | 87 | fi |
| 88 | 88 | done |
| 89 | 89 | |
| 90 | −check_section $OBJ .data | |
| 91 | −check_section $OBJ .bss | |
| 92 | −check_section $OBJ .init.data | |
| 90 | +check_section "$OBJ" .data | |
| 91 | +check_section "$OBJ" .bss | |
| 92 | +check_section "$OBJ" .init.data | |
| 93 | 93 | |
| 94 | 94 | exit $ERROR |
| @@ -141,10 +141,7 @@ void __init check_smt_enabled(void) · 140 unmodified lines | ||
| 141 | 141 | smt_enabled_at_boot = 0; |
| 142 | 142 | else { |
| 143 | 143 | int smt; |
| 144 | − int rc; | |
| 145 | − | |
| 146 | − rc = kstrtoint(smt_enabled_cmdline, 10, &smt); | |
| 147 | − if (!rc) | |
| 144 | + if (!kstrtoint(smt_enabled_cmdline, 10, &smt)) | |
| 148 | 145 | smt_enabled_at_boot = |
| 149 | 146 | min(threads_per_core, smt); |
| 150 | 147 | } |
| @@ -69,7 +69,7 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) · 68 unmodified lines | ||
| 69 | 69 | |
| 70 | 70 | /* |
| 71 | 71 | * Common checks before entering the guest world. Call with interrupts |
| 72 | − * disabled. | |
| 72 | + * enabled. | |
| 73 | 73 | * |
| 74 | 74 | * returns: |
| 75 | 75 | * |
| @@ -110,8 +110,7 @@ static int cpm_pic_probe(struct platform_device *pdev) · 109 unmodified lines | ||
| 110 | 110 | |
| 111 | 111 | out_be32(&data->reg->cpic_cimr, 0); |
| 112 | 112 | |
| 113 | − data->host = irq_domain_create_linear(of_fwnode_handle(dev->of_node), | |
| 114 | − 64, &cpm_pic_host_ops, data); | |
| 113 | + data->host = irq_domain_create_linear(dev_fwnode(dev), 64, &cpm_pic_host_ops, data); | |
| 115 | 114 | if (!data->host) |
| 116 | 115 | return -ENODEV; |
| 117 | 116 | |
| @@ -122,16 +122,11 @@ choice · 121 unmodified lines | ||
| 122 | 122 | If unsure, select Generic. |
| 123 | 123 | |
| 124 | 124 | config POWERPC64_CPU |
| 125 | − bool "Generic (POWER5 and PowerPC 970 and above)" | |
| 126 | − depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN | |
| 127 | − select PPC_64S_HASH_MMU | |
| 128 | − | |
| 129 | −config POWERPC64_CPU | |
| 130 | − bool "Generic (POWER8 and above)" | |
| 131 | − depends on PPC_BOOK3S_64 && CPU_LITTLE_ENDIAN | |
| 132 | − select ARCH_HAS_FAST_MULTIPLIER | |
| 125 | + bool "Generic 64 bits powerpc" | |
| 126 | + depends on PPC_BOOK3S_64 | |
| 127 | + select ARCH_HAS_FAST_MULTIPLIER if CPU_LITTLE_ENDIAN | |
| 133 | 128 | select PPC_64S_HASH_MMU |
| 134 | − select PPC_HAS_LBARX_LHARX | |
| 129 | + select PPC_HAS_LBARX_LHARX if CPU_LITTLE_ENDIAN | |
| 135 | 130 | |
| 136 | 131 | config POWERPC_CPU |
| 137 | 132 | bool "Generic 32 bits powerpc" |
| @@ -412,9 +412,8 @@ static int fsl_of_msi_probe(struct platform_device *dev) · 411 unmodified lines | ||
| 412 | 412 | } |
| 413 | 413 | platform_set_drvdata(dev, msi); |
| 414 | 414 | |
| 415 | − msi->irqhost = irq_domain_create_linear(of_fwnode_handle(dev->dev.of_node), | |
| 416 | − NR_MSI_IRQS_MAX, &fsl_msi_host_ops, msi); | |
| 417 | − | |
| 415 | + msi->irqhost = irq_domain_create_linear(dev_fwnode(&dev->dev), NR_MSI_IRQS_MAX, | |
| 416 | + &fsl_msi_host_ops, msi); | |
| 418 | 417 | if (msi->irqhost == NULL) { |
| 419 | 418 | dev_err(&dev->dev, "No memory for MSI irqhost\n"); |
| 420 | 419 | err = -ENOMEM; |
| @@ -530,6 +530,9 @@ void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned l · 529 unmodified lines | ||
| 530 | 530 | lowcore_address + sizeof(struct lowcore), |
| 531 | 531 | POPULATE_LOWCORE); |
| 532 | 532 | for_each_physmem_usable_range(i, &start, &end) { |
| 533 | + /* Do not map lowcore with identity mapping */ | |
| 534 | + if (!start) | |
| 535 | + start = sizeof(struct lowcore); | |
| 533 | 536 | pgtable_populate((unsigned long)__identity_va(start), |
| 534 | 537 | (unsigned long)__identity_va(end), |
| 535 | 538 | POPULATE_IDENTITY); |
| @@ -5,6 +5,7 @@ CONFIG_WATCH_QUEUE=y · 4 unmodified lines | ||
| 5 | 5 | CONFIG_AUDIT=y |
| 6 | 6 | CONFIG_NO_HZ_IDLE=y |
| 7 | 7 | CONFIG_HIGH_RES_TIMERS=y |
| 8 | +CONFIG_POSIX_AUX_CLOCKS=y | |
| 8 | 9 | CONFIG_BPF_SYSCALL=y |
| 9 | 10 | CONFIG_BPF_JIT=y |
| 10 | 11 | CONFIG_BPF_JIT_ALWAYS_ON=y |
| @@ -19,6 +20,7 @@ CONFIG_TASK_XACCT=y · 8 unmodified lines | ||
| 19 | 20 | CONFIG_TASK_IO_ACCOUNTING=y |
| 20 | 21 | CONFIG_IKCONFIG=y |
| 21 | 22 | CONFIG_IKCONFIG_PROC=y |
| 23 | +CONFIG_SCHED_PROXY_EXEC=y | |
| 22 | 24 | CONFIG_NUMA_BALANCING=y |
| 23 | 25 | CONFIG_MEMCG=y |
| 24 | 26 | CONFIG_BLK_CGROUP=y |
| @@ -42,6 +44,7 @@ CONFIG_PROFILING=y · 17 unmodified lines | ||
| 42 | 44 | CONFIG_KEXEC=y |
| 43 | 45 | CONFIG_KEXEC_FILE=y |
| 44 | 46 | CONFIG_KEXEC_SIG=y |
| 47 | +CONFIG_CRASH_DM_CRYPT=y | |
| 45 | 48 | CONFIG_LIVEPATCH=y |
| 46 | 49 | CONFIG_MARCH_Z13=y |
| 47 | 50 | CONFIG_NR_CPUS=512 |
| @@ -105,6 +108,7 @@ CONFIG_CMA_AREAS=7 · 57 unmodified lines | ||
| 105 | 108 | CONFIG_MEM_SOFT_DIRTY=y |
| 106 | 109 | CONFIG_DEFERRED_STRUCT_PAGE_INIT=y |
| 107 | 110 | CONFIG_IDLE_PAGE_TRACKING=y |
| 111 | +CONFIG_ZONE_DEVICE=y | |
| 108 | 112 | CONFIG_PERCPU_STATS=y |
| 109 | 113 | CONFIG_GUP_TEST=y |
| 110 | 114 | CONFIG_ANON_VMA_NAME=y |
| @@ -223,17 +227,19 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=m · 112 unmodified lines | ||
| 223 | 227 | CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m |
| 224 | 228 | CONFIG_NETFILTER_XT_TARGET_CT=m |
| 225 | 229 | CONFIG_NETFILTER_XT_TARGET_DSCP=m |
| 230 | +CONFIG_NETFILTER_XT_TARGET_HL=m | |
| 226 | 231 | CONFIG_NETFILTER_XT_TARGET_HMARK=m |
| 227 | 232 | CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m |
| 228 | 233 | CONFIG_NETFILTER_XT_TARGET_LOG=m |
| 229 | 234 | CONFIG_NETFILTER_XT_TARGET_MARK=m |
| 235 | +CONFIG_NETFILTER_XT_NAT=m | |
| 230 | 236 | CONFIG_NETFILTER_XT_TARGET_NETMAP=m |
| 231 | 237 | CONFIG_NETFILTER_XT_TARGET_NFLOG=m |
| 232 | 238 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
| 233 | 239 | CONFIG_NETFILTER_XT_TARGET_REDIRECT=m |
| 240 | +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m | |
| 234 | 241 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
| 235 | 242 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m |
| 236 | −CONFIG_NETFILTER_XT_TARGET_TRACE=m | |
| 237 | 243 | CONFIG_NETFILTER_XT_TARGET_SECMARK=m |
| 238 | 244 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
| 239 | 245 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
| @@ -248,6 +254,7 @@ CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m · 8 unmodified lines | ||
| 248 | 254 | CONFIG_NETFILTER_XT_MATCH_CONNMARK=m |
| 249 | 255 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m |
| 250 | 256 | CONFIG_NETFILTER_XT_MATCH_CPU=m |
| 257 | +CONFIG_NETFILTER_XT_MATCH_DCCP=m | |
| 251 | 258 | CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m |
| 252 | 259 | CONFIG_NETFILTER_XT_MATCH_DSCP=m |
| 253 | 260 | CONFIG_NETFILTER_XT_MATCH_ESP=m |
| @@ -318,16 +325,8 @@ CONFIG_IP_NF_MATCH_AH=m · 64 unmodified lines | ||
| 318 | 325 | CONFIG_IP_NF_MATCH_ECN=m |
| 319 | 326 | CONFIG_IP_NF_MATCH_RPFILTER=m |
| 320 | 327 | CONFIG_IP_NF_MATCH_TTL=m |
| 321 | −CONFIG_IP_NF_FILTER=m | |
| 322 | 328 | CONFIG_IP_NF_TARGET_REJECT=m |
| 323 | −CONFIG_IP_NF_NAT=m | |
| 324 | −CONFIG_IP_NF_TARGET_MASQUERADE=m | |
| 325 | −CONFIG_IP_NF_MANGLE=m | |
| 326 | 329 | CONFIG_IP_NF_TARGET_ECN=m |
| 327 | −CONFIG_IP_NF_TARGET_TTL=m | |
| 328 | −CONFIG_IP_NF_RAW=m | |
| 329 | −CONFIG_IP_NF_SECURITY=m | |
| 330 | −CONFIG_IP_NF_ARPFILTER=m | |
| 331 | 330 | CONFIG_IP_NF_ARP_MANGLE=m |
| 332 | 331 | CONFIG_NFT_FIB_IPV6=m |
| 333 | 332 | CONFIG_IP6_NF_IPTABLES=m |
| @@ -340,15 +339,9 @@ CONFIG_IP6_NF_MATCH_IPV6HEADER=m · 6 unmodified lines | ||
| 340 | 339 | CONFIG_IP6_NF_MATCH_MH=m |
| 341 | 340 | CONFIG_IP6_NF_MATCH_RPFILTER=m |
| 342 | 341 | CONFIG_IP6_NF_MATCH_RT=m |
| 343 | −CONFIG_IP6_NF_TARGET_HL=m | |
| 344 | −CONFIG_IP6_NF_FILTER=m | |
| 345 | 342 | CONFIG_IP6_NF_TARGET_REJECT=m |
| 346 | −CONFIG_IP6_NF_MANGLE=m | |
| 347 | −CONFIG_IP6_NF_RAW=m | |
| 348 | −CONFIG_IP6_NF_SECURITY=m | |
| 349 | −CONFIG_IP6_NF_NAT=m | |
| 350 | −CONFIG_IP6_NF_TARGET_MASQUERADE=m | |
| 351 | 343 | CONFIG_NF_TABLES_BRIDGE=m |
| 344 | +CONFIG_IP_SCTP=m | |
| 352 | 345 | CONFIG_RDS=m |
| 353 | 346 | CONFIG_RDS_RDMA=m |
| 354 | 347 | CONFIG_RDS_TCP=m |
| @@ -383,6 +376,7 @@ CONFIG_NET_SCH_FQ_CODEL=m · 28 unmodified lines | ||
| 383 | 376 | CONFIG_NET_SCH_INGRESS=m |
| 384 | 377 | CONFIG_NET_SCH_PLUG=m |
| 385 | 378 | CONFIG_NET_SCH_ETS=m |
| 379 | +CONFIG_NET_SCH_DUALPI2=m | |
| 386 | 380 | CONFIG_NET_CLS_BASIC=m |
| 387 | 381 | CONFIG_NET_CLS_ROUTE4=m |
| 388 | 382 | CONFIG_NET_CLS_FW=m |
| @@ -504,6 +498,7 @@ CONFIG_DM_VDO=m · 115 unmodified lines | ||
| 504 | 498 | CONFIG_NETDEVICES=y |
| 505 | 499 | CONFIG_BONDING=m |
| 506 | 500 | CONFIG_DUMMY=m |
| 501 | +CONFIG_OVPN=m | |
| 507 | 502 | CONFIG_EQUALIZER=m |
| 508 | 503 | CONFIG_IFB=m |
| 509 | 504 | CONFIG_MACVLAN=m |
| @@ -641,6 +636,7 @@ CONFIG_VP_VDPA=m · 131 unmodified lines | ||
| 641 | 636 | CONFIG_VHOST_NET=m |
| 642 | 637 | CONFIG_VHOST_VSOCK=m |
| 643 | 638 | CONFIG_VHOST_VDPA=m |
| 639 | +CONFIG_DEV_DAX=m | |
| 644 | 640 | CONFIG_EXT4_FS=y |
| 645 | 641 | CONFIG_EXT4_FS_POSIX_ACL=y |
| 646 | 642 | CONFIG_EXT4_FS_SECURITY=y |
| @@ -665,6 +661,7 @@ CONFIG_NILFS2_FS=m · 18 unmodified lines | ||
| 665 | 661 | CONFIG_BCACHEFS_FS=y |
| 666 | 662 | CONFIG_BCACHEFS_QUOTA=y |
| 667 | 663 | CONFIG_BCACHEFS_POSIX_ACL=y |
| 664 | +CONFIG_FS_DAX=y | |
| 668 | 665 | CONFIG_EXPORTFS_BLOCK_OPS=y |
| 669 | 666 | CONFIG_FS_ENCRYPTION=y |
| 670 | 667 | CONFIG_FS_VERITY=y |
| @@ -755,6 +752,8 @@ CONFIG_HARDENED_USERCOPY=y · 84 unmodified lines | ||
| 755 | 752 | CONFIG_BUG_ON_DATA_CORRUPTION=y |
| 756 | 753 | CONFIG_CRYPTO_USER=m |
| 757 | 754 | CONFIG_CRYPTO_SELFTESTS=y |
| 755 | +CONFIG_CRYPTO_SELFTESTS_FULL=y | |
| 756 | +CONFIG_CRYPTO_NULL=y | |
| 758 | 757 | CONFIG_CRYPTO_PCRYPT=m |
| 759 | 758 | CONFIG_CRYPTO_CRYPTD=m |
| 760 | 759 | CONFIG_CRYPTO_BENCHMARK=m |
| @@ -783,7 +782,6 @@ CONFIG_CRYPTO_HCTR2=m · 22 unmodified lines | ||
| 783 | 782 | CONFIG_CRYPTO_LRW=m |
| 784 | 783 | CONFIG_CRYPTO_PCBC=m |
| 785 | 784 | CONFIG_CRYPTO_AEGIS128=m |
| 786 | −CONFIG_CRYPTO_CHACHA20POLY1305=m | |
| 787 | 785 | CONFIG_CRYPTO_GCM=y |
| 788 | 786 | CONFIG_CRYPTO_SEQIV=y |
| 789 | 787 | CONFIG_CRYPTO_MD4=m |
| @@ -822,6 +820,7 @@ CONFIG_SYSTEM_BLACKLIST_KEYRING=y · 32 unmodified lines | ||
| 822 | 820 | CONFIG_CRYPTO_KRB5=m |
| 823 | 821 | CONFIG_CRYPTO_KRB5_SELFTESTS=y |
| 824 | 822 | CONFIG_CORDIC=m |
| 823 | +CONFIG_TRACE_MMIO_ACCESS=y | |
| 825 | 824 | CONFIG_RANDOM32_SELFTEST=y |
| 826 | 825 | CONFIG_XZ_DEC_MICROLZMA=y |
| 827 | 826 | CONFIG_DMA_CMA=y |
| @@ -4,6 +4,7 @@ CONFIG_WATCH_QUEUE=y · 3 unmodified lines | ||
| 4 | 4 | CONFIG_AUDIT=y |
| 5 | 5 | CONFIG_NO_HZ_IDLE=y |
| 6 | 6 | CONFIG_HIGH_RES_TIMERS=y |
| 7 | +CONFIG_POSIX_AUX_CLOCKS=y | |
| 7 | 8 | CONFIG_BPF_SYSCALL=y |
| 8 | 9 | CONFIG_BPF_JIT=y |
| 9 | 10 | CONFIG_BPF_JIT_ALWAYS_ON=y |
| @@ -17,6 +18,7 @@ CONFIG_TASK_XACCT=y · 7 unmodified lines | ||
| 17 | 18 | CONFIG_TASK_IO_ACCOUNTING=y |
| 18 | 19 | CONFIG_IKCONFIG=y |
| 19 | 20 | CONFIG_IKCONFIG_PROC=y |
| 21 | +CONFIG_SCHED_PROXY_EXEC=y | |
| 20 | 22 | CONFIG_NUMA_BALANCING=y |
| 21 | 23 | CONFIG_MEMCG=y |
| 22 | 24 | CONFIG_BLK_CGROUP=y |
| @@ -40,11 +42,12 @@ CONFIG_PROFILING=y · 17 unmodified lines | ||
| 40 | 42 | CONFIG_KEXEC=y |
| 41 | 43 | CONFIG_KEXEC_FILE=y |
| 42 | 44 | CONFIG_KEXEC_SIG=y |
| 45 | +CONFIG_CRASH_DM_CRYPT=y | |
| 43 | 46 | CONFIG_LIVEPATCH=y |
| 44 | 47 | CONFIG_MARCH_Z13=y |
| 45 | 48 | CONFIG_NR_CPUS=512 |
| 46 | 49 | CONFIG_NUMA=y |
| 47 | −CONFIG_HZ_100=y | |
| 50 | +CONFIG_HZ_1000=y | |
| 48 | 51 | CONFIG_CERT_STORE=y |
| 49 | 52 | CONFIG_EXPOLINE=y |
| 50 | 53 | CONFIG_EXPOLINE_AUTO=y |
| @@ -97,6 +100,7 @@ CONFIG_CMA_AREAS=7 · 46 unmodified lines | ||
| 97 | 100 | CONFIG_MEM_SOFT_DIRTY=y |
| 98 | 101 | CONFIG_DEFERRED_STRUCT_PAGE_INIT=y |
| 99 | 102 | CONFIG_IDLE_PAGE_TRACKING=y |
| 103 | +CONFIG_ZONE_DEVICE=y | |
| 100 | 104 | CONFIG_PERCPU_STATS=y |
| 101 | 105 | CONFIG_ANON_VMA_NAME=y |
| 102 | 106 | CONFIG_USERFAULTFD=y |
| @@ -214,17 +218,19 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=m · 111 unmodified lines | ||
| 214 | 218 | CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m |
| 215 | 219 | CONFIG_NETFILTER_XT_TARGET_CT=m |
| 216 | 220 | CONFIG_NETFILTER_XT_TARGET_DSCP=m |
| 221 | +CONFIG_NETFILTER_XT_TARGET_HL=m | |
| 217 | 222 | CONFIG_NETFILTER_XT_TARGET_HMARK=m |
| 218 | 223 | CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m |
| 219 | 224 | CONFIG_NETFILTER_XT_TARGET_LOG=m |
| 220 | 225 | CONFIG_NETFILTER_XT_TARGET_MARK=m |
| 226 | +CONFIG_NETFILTER_XT_NAT=m | |
| 221 | 227 | CONFIG_NETFILTER_XT_TARGET_NETMAP=m |
| 222 | 228 | CONFIG_NETFILTER_XT_TARGET_NFLOG=m |
| 223 | 229 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m |
| 224 | 230 | CONFIG_NETFILTER_XT_TARGET_REDIRECT=m |
| 231 | +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m | |
| 225 | 232 | CONFIG_NETFILTER_XT_TARGET_TEE=m |
| 226 | 233 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m |
| 227 | −CONFIG_NETFILTER_XT_TARGET_TRACE=m | |
| 228 | 234 | CONFIG_NETFILTER_XT_TARGET_SECMARK=m |
| 229 | 235 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m |
| 230 | 236 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m |
| @@ -239,6 +245,7 @@ CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m · 8 unmodified lines | ||
| 239 | 245 | CONFIG_NETFILTER_XT_MATCH_CONNMARK=m |
| 240 | 246 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m |
| 241 | 247 | CONFIG_NETFILTER_XT_MATCH_CPU=m |
| 248 | +CONFIG_NETFILTER_XT_MATCH_DCCP=m | |
| 242 | 249 | CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m |
| 243 | 250 | CONFIG_NETFILTER_XT_MATCH_DSCP=m |
| 244 | 251 | CONFIG_NETFILTER_XT_MATCH_ESP=m |
| @@ -309,16 +316,8 @@ CONFIG_IP_NF_MATCH_AH=m · 64 unmodified lines | ||
| 309 | 316 | CONFIG_IP_NF_MATCH_ECN=m |
| 310 | 317 | CONFIG_IP_NF_MATCH_RPFILTER=m |
| 311 | 318 | CONFIG_IP_NF_MATCH_TTL=m |
| 312 | −CONFIG_IP_NF_FILTER=m | |
| 313 | 319 | CONFIG_IP_NF_TARGET_REJECT=m |
| 314 | −CONFIG_IP_NF_NAT=m | |
| 315 | −CONFIG_IP_NF_TARGET_MASQUERADE=m | |
| 316 | −CONFIG_IP_NF_MANGLE=m | |
| 317 | 320 | CONFIG_IP_NF_TARGET_ECN=m |
| 318 | −CONFIG_IP_NF_TARGET_TTL=m | |
| 319 | −CONFIG_IP_NF_RAW=m | |
| 320 | −CONFIG_IP_NF_SECURITY=m | |
| 321 | −CONFIG_IP_NF_ARPFILTER=m | |
| 322 | 321 | CONFIG_IP_NF_ARP_MANGLE=m |
| 323 | 322 | CONFIG_NFT_FIB_IPV6=m |
| 324 | 323 | CONFIG_IP6_NF_IPTABLES=m |
| @@ -331,15 +330,9 @@ CONFIG_IP6_NF_MATCH_IPV6HEADER=m · 6 unmodified lines | ||
| 331 | 330 | CONFIG_IP6_NF_MATCH_MH=m |
| 332 | 331 | CONFIG_IP6_NF_MATCH_RPFILTER=m |
| 333 | 332 | CONFIG_IP6_NF_MATCH_RT=m |
| 334 | −CONFIG_IP6_NF_TARGET_HL=m | |
| 335 | −CONFIG_IP6_NF_FILTER=m | |
| 336 | 333 | CONFIG_IP6_NF_TARGET_REJECT=m |
| 337 | −CONFIG_IP6_NF_MANGLE=m | |
| 338 | −CONFIG_IP6_NF_RAW=m | |
| 339 | −CONFIG_IP6_NF_SECURITY=m | |
| 340 | −CONFIG_IP6_NF_NAT=m | |
| 341 | −CONFIG_IP6_NF_TARGET_MASQUERADE=m | |
| 342 | 334 | CONFIG_NF_TABLES_BRIDGE=m |
| 335 | +CONFIG_IP_SCTP=m | |
| 343 | 336 | CONFIG_RDS=m |
| 344 | 337 | CONFIG_RDS_RDMA=m |
| 345 | 338 | CONFIG_RDS_TCP=m |
| @@ -373,6 +366,7 @@ CONFIG_NET_SCH_FQ_CODEL=m · 27 unmodified lines | ||
| 373 | 366 | CONFIG_NET_SCH_INGRESS=m |
| 374 | 367 | CONFIG_NET_SCH_PLUG=m |
| 375 | 368 | CONFIG_NET_SCH_ETS=m |
| 369 | +CONFIG_NET_SCH_DUALPI2=m | |
| 376 | 370 | CONFIG_NET_CLS_BASIC=m |
| 377 | 371 | CONFIG_NET_CLS_ROUTE4=m |
| 378 | 372 | CONFIG_NET_CLS_FW=m |
| @@ -494,6 +488,7 @@ CONFIG_DM_VDO=m · 115 unmodified lines | ||
| 494 | 488 | CONFIG_NETDEVICES=y |
| 495 | 489 | CONFIG_BONDING=m |
| 496 | 490 | CONFIG_DUMMY=m |
| 491 | +CONFIG_OVPN=m | |
| 497 | 492 | CONFIG_EQUALIZER=m |
| 498 | 493 | CONFIG_IFB=m |
| 499 | 494 | CONFIG_MACVLAN=m |
| @@ -631,6 +626,7 @@ CONFIG_VP_VDPA=m · 131 unmodified lines | ||
| 631 | 626 | CONFIG_VHOST_NET=m |
| 632 | 627 | CONFIG_VHOST_VSOCK=m |
| 633 | 628 | CONFIG_VHOST_VDPA=m |
| 629 | +CONFIG_DEV_DAX=m | |
| 634 | 630 | CONFIG_EXT4_FS=y |
| 635 | 631 | CONFIG_EXT4_FS_POSIX_ACL=y |
| 636 | 632 | CONFIG_EXT4_FS_SECURITY=y |
| @@ -652,6 +648,7 @@ CONFIG_NILFS2_FS=m · 15 unmodified lines | ||
| 652 | 648 | CONFIG_BCACHEFS_FS=m |
| 653 | 649 | CONFIG_BCACHEFS_QUOTA=y |
| 654 | 650 | CONFIG_BCACHEFS_POSIX_ACL=y |
| 651 | +CONFIG_FS_DAX=y | |
| 655 | 652 | CONFIG_EXPORTFS_BLOCK_OPS=y |
| 656 | 653 | CONFIG_FS_ENCRYPTION=y |
| 657 | 654 | CONFIG_FS_VERITY=y |
| @@ -683,7 +680,6 @@ CONFIG_TMPFS_POSIX_ACL=y · 25 unmodified lines | ||
| 683 | 680 | CONFIG_TMPFS_INODE64=y |
| 684 | 681 | CONFIG_TMPFS_QUOTA=y |
| 685 | 682 | CONFIG_HUGETLBFS=y |
| 686 | −CONFIG_CONFIGFS_FS=m | |
| 687 | 683 | CONFIG_ECRYPT_FS=m |
| 688 | 684 | CONFIG_CRAMFS=m |
| 689 | 685 | CONFIG_SQUASHFS=m |
| @@ -741,6 +737,7 @@ CONFIG_BUG_ON_DATA_CORRUPTION=y · 51 unmodified lines | ||
| 741 | 737 | CONFIG_CRYPTO_FIPS=y |
| 742 | 738 | CONFIG_CRYPTO_USER=m |
| 743 | 739 | CONFIG_CRYPTO_SELFTESTS=y |
| 740 | +CONFIG_CRYPTO_NULL=y | |
| 744 | 741 | CONFIG_CRYPTO_PCRYPT=m |
| 745 | 742 | CONFIG_CRYPTO_CRYPTD=m |
| 746 | 743 | CONFIG_CRYPTO_BENCHMARK=m |
| @@ -769,7 +766,6 @@ CONFIG_CRYPTO_HCTR2=m · 22 unmodified lines | ||
| 769 | 766 | CONFIG_CRYPTO_LRW=m |
| 770 | 767 | CONFIG_CRYPTO_PCBC=m |
| 771 | 768 | CONFIG_CRYPTO_AEGIS128=m |
| 772 | −CONFIG_CRYPTO_CHACHA20POLY1305=m | |
| 773 | 769 | CONFIG_CRYPTO_GCM=y |
| 774 | 770 | CONFIG_CRYPTO_SEQIV=y |
| 775 | 771 | CONFIG_CRYPTO_MD4=m |
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | CONFIG_NO_HZ_IDLE=y |
| 2 | 2 | CONFIG_HIGH_RES_TIMERS=y |
| 3 | +CONFIG_POSIX_AUX_CLOCKS=y | |
| 3 | 4 | CONFIG_BPF_SYSCALL=y |
| 4 | 5 | # CONFIG_CPU_ISOLATION is not set |
| 5 | 6 | # CONFIG_UTS_NS is not set |
| @@ -11,7 +12,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y · 5 unmodified lines | ||
| 11 | 12 | CONFIG_KEXEC=y |
| 12 | 13 | CONFIG_MARCH_Z13=y |
| 13 | 14 | CONFIG_NR_CPUS=2 |
| 14 | −CONFIG_HZ_100=y | |
| 15 | +CONFIG_HZ_1000=y | |
| 15 | 16 | # CONFIG_CHSC_SCH is not set |
| 16 | 17 | # CONFIG_SCM_BUS is not set |
| 17 | 18 | # CONFIG_AP is not set |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | +#include <linux/security.h> | |
| 9 | 10 | #include <linux/slab.h> |
| 10 | 11 | #include "hypfs.h" |
| 11 | 12 | |
| @@ -66,23 +67,27 @@ static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 54 unmodified lines | ||
| 66 | 67 | long rc; |
| 67 | 68 | |
| 68 | 69 | mutex_lock(&df->lock); |
| 69 | − if (df->unlocked_ioctl) | |
| 70 | − rc = df->unlocked_ioctl(file, cmd, arg); | |
| 71 | − else | |
| 72 | − rc = -ENOTTY; | |
| 70 | + rc = df->unlocked_ioctl(file, cmd, arg); | |
| 73 | 71 | mutex_unlock(&df->lock); |
| 74 | 72 | return rc; |
| 75 | 73 | } |
| 76 | 74 | |
| 77 | −static const struct file_operations dbfs_ops = { | |
| 75 | +static const struct file_operations dbfs_ops_ioctl = { | |
| 78 | 76 | .read = dbfs_read, |
| 79 | 77 | .unlocked_ioctl = dbfs_ioctl, |
| 80 | 78 | }; |
| 81 | 79 | |
| 80 | +static const struct file_operations dbfs_ops = { | |
| 81 | + .read = dbfs_read, | |
| 82 | +}; | |
| 83 | + | |
| 82 | 84 | void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) |
| 83 | 85 | { |
| 84 | − df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, | |
| 85 | − &dbfs_ops); | |
| 86 | + const struct file_operations *fops = &dbfs_ops; | |
| 87 | + | |
| 88 | + if (df->unlocked_ioctl && !security_locked_down(LOCKDOWN_DEBUGFS)) | |
| 89 | + fops = &dbfs_ops_ioctl; | |
| 90 | + df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, fops); | |
| 86 | 91 | mutex_init(&df->lock); |
| 87 | 92 | } |
| 88 | 93 | |
| @@ -94,12 +94,13 @@ DECLARE_STATIC_CALL(xen_hypercall, xen_hypercall_func); · 93 unmodified lines | ||
| 94 | 94 | #ifdef MODULE |
| 95 | 95 | #define __ADDRESSABLE_xen_hypercall |
| 96 | 96 | #else |
| 97 | −#define __ADDRESSABLE_xen_hypercall __ADDRESSABLE_ASM_STR(__SCK__xen_hypercall) | |
| 97 | +#define __ADDRESSABLE_xen_hypercall \ | |
| 98 | + __stringify(.global STATIC_CALL_KEY(xen_hypercall);) | |
| 98 | 99 | #endif |
| 99 | 100 | |
| 100 | 101 | #define __HYPERCALL \ |
| 101 | 102 | __ADDRESSABLE_xen_hypercall \ |
| 102 | − "call __SCT__xen_hypercall" | |
| 103 | + __stringify(call STATIC_CALL_TRAMP(xen_hypercall)) | |
| 103 | 104 | |
| 104 | 105 | #define __HYPERCALL_ENTRY(x) "a" (x) |
| 105 | 106 | |
| @@ -1326,8 +1326,8 @@ static const char * const s5_reset_reason_txt[] = { · 1325 unmodified lines | ||
| 1326 | 1326 | |
| 1327 | 1327 | static __init int print_s5_reset_status_mmio(void) |
| 1328 | 1328 | { |
| 1329 | − unsigned long value; | |
| 1330 | 1329 | void __iomem *addr; |
| 1330 | + u32 value; | |
| 1331 | 1331 | int i; |
| 1332 | 1332 | |
| 1333 | 1333 | if (!cpu_feature_enabled(X86_FEATURE_ZEN)) |
| @@ -1340,12 +1340,16 @@ static __init int print_s5_reset_status_mmio(void) · 6 unmodified lines | ||
| 1340 | 1340 | value = ioread32(addr); |
| 1341 | 1341 | iounmap(addr); |
| 1342 | 1342 | |
| 1343 | + /* Value with "all bits set" is an error response and should be ignored. */ | |
| 1344 | + if (value == U32_MAX) | |
| 1345 | + return 0; | |
| 1346 | + | |
| 1343 | 1347 | for (i = 0; i < ARRAY_SIZE(s5_reset_reason_txt); i++) { |
| 1344 | 1348 | if (!(value & BIT(i))) |
| 1345 | 1349 | continue; |
| 1346 | 1350 | |
| 1347 | 1351 | if (s5_reset_reason_txt[i]) { |
| 1348 | − pr_info("x86/amd: Previous system reset reason [0x%08lx]: %s\n", | |
| 1352 | + pr_info("x86/amd: Previous system reset reason [0x%08x]: %s\n", | |
| 1349 | 1353 | value, s5_reset_reason_txt[i]); |
| 1350 | 1354 | } |
| 1351 | 1355 | } |
| @@ -1068,10 +1068,8 @@ static void __init gds_select_mitigation(void) · 1067 unmodified lines | ||
| 1068 | 1068 | if (gds_mitigation == GDS_MITIGATION_AUTO) { |
| 1069 | 1069 | if (should_mitigate_vuln(X86_BUG_GDS)) |
| 1070 | 1070 | gds_mitigation = GDS_MITIGATION_FULL; |
| 1071 | − else { | |
| 1071 | + else | |
| 1072 | 1072 | gds_mitigation = GDS_MITIGATION_OFF; |
| 1073 | − return; | |
| 1074 | − } | |
| 1075 | 1073 | } |
| 1076 | 1074 | |
| 1077 | 1075 | /* No microcode */ |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <asm/spec-ctrl.h> |
| 17 | 17 | #include <asm/delay.h> |
| 18 | 18 | #include <asm/msr.h> |
| 19 | +#include <asm/resctrl.h> | |
| 19 | 20 | |
| 20 | 21 | #include "cpu.h" |
| 21 | 22 | |
| @@ -117,6 +118,8 @@ static void bsp_init_hygon(struct cpuinfo_x86 *c) · 95 unmodified lines | ||
| 117 | 118 | x86_amd_ls_cfg_ssbd_mask = 1ULL << 10; |
| 118 | 119 | } |
| 119 | 120 | } |
| 121 | + | |
| 122 | + resctrl_cpu_detect(c); | |
| 120 | 123 | } |
| 121 | 124 | |
| 122 | 125 | static void early_init_hygon(struct cpuinfo_x86 *c) |
| @@ -557,7 +557,7 @@ static inline int bio_check_eod(struct bio *bio) · 556 unmodified lines | ||
| 557 | 557 | sector_t maxsector = bdev_nr_sectors(bio->bi_bdev); |
| 558 | 558 | unsigned int nr_sectors = bio_sectors(bio); |
| 559 | 559 | |
| 560 | − if (nr_sectors && | |
| 560 | + if (nr_sectors && maxsector && | |
| 561 | 561 | (nr_sectors > maxsector || |
| 562 | 562 | bio->bi_iter.bi_sector > maxsector - nr_sectors)) { |
| 563 | 563 | pr_info_ratelimited("%s: attempt to access beyond end of device\n" |
| @@ -95,6 +95,7 @@ static const char *const blk_queue_flag_name[] = { · 94 unmodified lines | ||
| 95 | 95 | QUEUE_FLAG_NAME(SQ_SCHED), |
| 96 | 96 | QUEUE_FLAG_NAME(DISABLE_WBT_DEF), |
| 97 | 97 | QUEUE_FLAG_NAME(NO_ELV_SWITCH), |
| 98 | + QUEUE_FLAG_NAME(QOS_ENABLED), | |
| 98 | 99 | }; |
| 99 | 100 | #undef QUEUE_FLAG_NAME |
| 100 | 101 | |
| @@ -5033,6 +5033,7 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, · 5032 unmodified lines | ||
| 5033 | 5033 | unsigned int memflags; |
| 5034 | 5034 | int i; |
| 5035 | 5035 | struct xarray elv_tbl, et_tbl; |
| 5036 | + bool queues_frozen = false; | |
| 5036 | 5037 | |
| 5037 | 5038 | lockdep_assert_held(&set->tag_list_lock); |
| 5038 | 5039 | |
| @@ -5056,9 +5057,6 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, · 17 unmodified lines | ||
| 5056 | 5057 | blk_mq_sysfs_unregister_hctxs(q); |
| 5057 | 5058 | } |
| 5058 | 5059 | |
| 5059 | − list_for_each_entry(q, &set->tag_list, tag_set_list) | |
| 5060 | − blk_mq_freeze_queue_nomemsave(q); | |
| 5061 | − | |
| 5062 | 5060 | /* |
| 5063 | 5061 | * Switch IO scheduler to 'none', cleaning up the data associated |
| 5064 | 5062 | * with the previous scheduler. We will switch back once we are done |
| @@ -5068,6 +5066,9 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, · 3 unmodified lines | ||
| 5068 | 5066 | if (blk_mq_elv_switch_none(q, &elv_tbl)) |
| 5069 | 5067 | goto switch_back; |
| 5070 | 5068 | |
| 5069 | + list_for_each_entry(q, &set->tag_list, tag_set_list) | |
| 5070 | + blk_mq_freeze_queue_nomemsave(q); | |
| 5071 | + queues_frozen = true; | |
| 5071 | 5072 | if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0) |
| 5072 | 5073 | goto switch_back; |
| 5073 | 5074 | |
| @@ -5091,8 +5092,12 @@ fallback: · 17 unmodified lines | ||
| 5091 | 5092 | } |
| 5092 | 5093 | switch_back: |
| 5093 | 5094 | /* The blk_mq_elv_switch_back unfreezes queue for us. */ |
| 5094 | − list_for_each_entry(q, &set->tag_list, tag_set_list) | |
| 5095 | + list_for_each_entry(q, &set->tag_list, tag_set_list) { | |
| 5096 | + /* switch_back expects queue to be frozen */ | |
| 5097 | + if (!queues_frozen) | |
| 5098 | + blk_mq_freeze_queue_nomemsave(q); | |
| 5095 | 5099 | blk_mq_elv_switch_back(q, &elv_tbl, &et_tbl); |
| 5100 | + } | |
| 5096 | 5101 | |
| 5097 | 5102 | list_for_each_entry(q, &set->tag_list, tag_set_list) { |
| 5098 | 5103 | blk_mq_sysfs_register_hctxs(q); |
| @@ -2,8 +2,6 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | #include "blk-rq-qos.h" |
| 4 | 4 | |
| 5 | −__read_mostly DEFINE_STATIC_KEY_FALSE(block_rq_qos); | |
| 6 | − | |
| 7 | 5 | /* |
| 8 | 6 | * Increment 'v', if 'v' is below 'below'. Returns true if we succeeded, |
| 9 | 7 | * false if 'v' + 1 would be bigger than 'below'. |
| @@ -319,8 +317,8 @@ void rq_qos_exit(struct request_queue *q) · 309 unmodified lines | ||
| 319 | 317 | struct rq_qos *rqos = q->rq_qos; |
| 320 | 318 | q->rq_qos = rqos->next; |
| 321 | 319 | rqos->ops->exit(rqos); |
| 322 | − static_branch_dec(&block_rq_qos); | |
| 323 | 320 | } |
| 321 | + blk_queue_flag_clear(QUEUE_FLAG_QOS_ENABLED, q); | |
| 324 | 322 | mutex_unlock(&q->rq_qos_mutex); |
| 325 | 323 | } |
| 326 | 324 | |
| @@ -346,7 +344,7 @@ int rq_qos_add(struct rq_qos *rqos, struct gendisk *disk, enum rq_qos_id id, · 19 unmodified lines | ||
| 346 | 344 | goto ebusy; |
| 347 | 345 | rqos->next = q->rq_qos; |
| 348 | 346 | q->rq_qos = rqos; |
| 349 | − static_branch_inc(&block_rq_qos); | |
| 347 | + blk_queue_flag_set(QUEUE_FLAG_QOS_ENABLED, q); | |
| 350 | 348 | |
| 351 | 349 | blk_mq_unfreeze_queue(q, memflags); |
| 352 | 350 | |
| @@ -377,6 +375,8 @@ void rq_qos_del(struct rq_qos *rqos) · 24 unmodified lines | ||
| 377 | 375 | break; |
| 378 | 376 | } |
| 379 | 377 | } |
| 378 | + if (!q->rq_qos) | |
| 379 | + blk_queue_flag_clear(QUEUE_FLAG_QOS_ENABLED, q); | |
| 380 | 380 | blk_mq_unfreeze_queue(q, memflags); |
| 381 | 381 | |
| 382 | 382 | mutex_lock(&q->debugfs_mutex); |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include "blk-mq-debugfs.h" |
| 13 | 13 | |
| 14 | 14 | struct blk_mq_debugfs_attr; |
| 15 | −extern struct static_key_false block_rq_qos; | |
| 16 | 15 | |
| 17 | 16 | enum rq_qos_id { |
| 18 | 17 | RQ_QOS_WBT, |
| @@ -113,43 +112,55 @@ void __rq_qos_queue_depth_changed(struct rq_qos *rqos); · 94 unmodified lines | ||
| 113 | 112 | |
| 114 | 113 | static inline void rq_qos_cleanup(struct request_queue *q, struct bio *bio) |
| 115 | 114 | { |
| 116 | − if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) | |
| 115 | + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && | |
| 116 | + q->rq_qos) | |
| 117 | 117 | __rq_qos_cleanup(q->rq_qos, bio); |
| 118 | 118 | } |
| 119 | 119 | |
| 120 | 120 | static inline void rq_qos_done(struct request_queue *q, struct request *rq) |
| 121 | 121 | { |
| 122 | − if (static_branch_unlikely(&block_rq_qos) && q->rq_qos && | |
| 123 | − !blk_rq_is_passthrough(rq)) | |
| 122 | + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && | |
| 123 | + q->rq_qos && !blk_rq_is_passthrough(rq)) | |
| 124 | 124 | __rq_qos_done(q->rq_qos, rq); |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | static inline void rq_qos_issue(struct request_queue *q, struct request *rq) |
| 128 | 128 | { |
| 129 | − if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) | |
| 129 | + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && | |
| 130 | + q->rq_qos) | |
| 130 | 131 | __rq_qos_issue(q->rq_qos, rq); |
| 131 | 132 | } |
| 132 | 133 | |
| 133 | 134 | static inline void rq_qos_requeue(struct request_queue *q, struct request *rq) |
| 134 | 135 | { |
| 135 | − if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) | |
| 136 | + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && | |
| 137 | + q->rq_qos) | |
| 136 | 138 | __rq_qos_requeue(q->rq_qos, rq); |
| 137 | 139 | } |
| 138 | 140 | |
| 139 | 141 | static inline void rq_qos_done_bio(struct bio *bio) |
| 140 | 142 | { |
| 141 | − if (static_branch_unlikely(&block_rq_qos) && | |
| 142 | − bio->bi_bdev && (bio_flagged(bio, BIO_QOS_THROTTLED) || | |
| 143 | − bio_flagged(bio, BIO_QOS_MERGED))) { | |
| 144 | − struct request_queue *q = bdev_get_queue(bio->bi_bdev); | |
| 145 | − if (q->rq_qos) | |
| 146 | − __rq_qos_done_bio(q->rq_qos, bio); | |
| 147 | − } | |
| 143 | + struct request_queue *q; | |
| 144 | + | |
| 145 | + if (!bio->bi_bdev || (!bio_flagged(bio, BIO_QOS_THROTTLED) && | |
| 146 | + !bio_flagged(bio, BIO_QOS_MERGED))) | |
| 147 | + return; | |
| 148 | + | |
| 149 | + q = bdev_get_queue(bio->bi_bdev); | |
| 150 | + | |
| 151 | + /* | |
| 152 | + * If a bio has BIO_QOS_xxx set, it implicitly implies that | |
| 153 | + * q->rq_qos is present. So, we skip re-checking q->rq_qos | |
| 154 | + * here as an extra optimization and directly call | |
| 155 | + * __rq_qos_done_bio(). | |
| 156 | + */ | |
| 157 | + __rq_qos_done_bio(q->rq_qos, bio); | |
| 148 | 158 | } |
| 149 | 159 | |
| 150 | 160 | static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio) |
| 151 | 161 | { |
| 152 | − if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) { | |
| 162 | + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && | |
| 163 | + q->rq_qos) { | |
| 153 | 164 | bio_set_flag(bio, BIO_QOS_THROTTLED); |
| 154 | 165 | __rq_qos_throttle(q->rq_qos, bio); |
| 155 | 166 | } |
| @@ -158,14 +169,16 @@ static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio) · 2 unmodified lines | ||
| 158 | 169 | static inline void rq_qos_track(struct request_queue *q, struct request *rq, |
| 159 | 170 | struct bio *bio) |
| 160 | 171 | { |
| 161 | − if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) | |
| 172 | + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && | |
| 173 | + q->rq_qos) | |
| 162 | 174 | __rq_qos_track(q->rq_qos, rq, bio); |
| 163 | 175 | } |
| 164 | 176 | |
| 165 | 177 | static inline void rq_qos_merge(struct request_queue *q, struct request *rq, |
| 166 | 178 | struct bio *bio) |
| 167 | 179 | { |
| 168 | − if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) { | |
| 180 | + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && | |
| 181 | + q->rq_qos) { | |
| 169 | 182 | bio_set_flag(bio, BIO_QOS_MERGED); |
| 170 | 183 | __rq_qos_merge(q->rq_qos, rq, bio); |
| 171 | 184 | } |
| @@ -173,7 +186,8 @@ static inline void rq_qos_merge(struct request_queue *q, struct request *rq, · 1 unmodified line | ||
| 173 | 186 | |
| 174 | 187 | static inline void rq_qos_queue_depth_changed(struct request_queue *q) |
| 175 | 188 | { |
| 176 | − if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) | |
| 189 | + if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && | |
| 190 | + q->rq_qos) | |
| 177 | 191 | __rq_qos_queue_depth_changed(q->rq_qos); |
| 178 | 192 | } |
| 179 | 193 | |
| @@ -157,16 +157,14 @@ static int blk_validate_integrity_limits(struct queue_limits *lim) · 156 unmodified lines | ||
| 157 | 157 | switch (bi->csum_type) { |
| 158 | 158 | case BLK_INTEGRITY_CSUM_NONE: |
| 159 | 159 | if (bi->pi_tuple_size) { |
| 160 | − pr_warn("pi_tuple_size must be 0 when checksum type \ | |
| 161 | − is none\n"); | |
| 160 | + pr_warn("pi_tuple_size must be 0 when checksum type is none\n"); | |
| 162 | 161 | return -EINVAL; |
| 163 | 162 | } |
| 164 | 163 | break; |
| 165 | 164 | case BLK_INTEGRITY_CSUM_CRC: |
| 166 | 165 | case BLK_INTEGRITY_CSUM_IP: |
| 167 | 166 | if (bi->pi_tuple_size != sizeof(struct t10_pi_tuple)) { |
| 168 | − pr_warn("pi_tuple_size mismatch for T10 PI: expected \ | |
| 169 | − %zu, got %u\n", | |
| 167 | + pr_warn("pi_tuple_size mismatch for T10 PI: expected %zu, got %u\n", | |
| 170 | 168 | sizeof(struct t10_pi_tuple), |
| 171 | 169 | bi->pi_tuple_size); |
| 172 | 170 | return -EINVAL; |
| @@ -174,8 +172,7 @@ static int blk_validate_integrity_limits(struct queue_limits *lim) · 1 unmodified line | ||
| 174 | 172 | break; |
| 175 | 173 | case BLK_INTEGRITY_CSUM_CRC64: |
| 176 | 174 | if (bi->pi_tuple_size != sizeof(struct crc64_pi_tuple)) { |
| 177 | − pr_warn("pi_tuple_size mismatch for CRC64 PI: \ | |
| 178 | − expected %zu, got %u\n", | |
| 175 | + pr_warn("pi_tuple_size mismatch for CRC64 PI: expected %zu, got %u\n", | |
| 179 | 176 | sizeof(struct crc64_pi_tuple), |
| 180 | 177 | bi->pi_tuple_size); |
| 181 | 178 | return -EINVAL; |
| @@ -972,6 +969,8 @@ bool queue_limits_stack_integrity(struct queue_limits *t, · 790 unmodified lines | ||
| 972 | 969 | goto incompatible; |
| 973 | 970 | if (ti->csum_type != bi->csum_type) |
| 974 | 971 | goto incompatible; |
| 972 | + if (ti->pi_tuple_size != bi->pi_tuple_size) | |
| 973 | + goto incompatible; | |
| 975 | 974 | if ((ti->flags & BLK_INTEGRITY_REF_TAG) != |
| 976 | 975 | (bi->flags & BLK_INTEGRITY_REF_TAG)) |
| 977 | 976 | goto incompatible; |
| @@ -980,6 +979,7 @@ bool queue_limits_stack_integrity(struct queue_limits *t, · 2 unmodified lines | ||
| 980 | 979 | ti->flags |= (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE) | |
| 981 | 980 | (bi->flags & BLK_INTEGRITY_REF_TAG); |
| 982 | 981 | ti->csum_type = bi->csum_type; |
| 982 | + ti->pi_tuple_size = bi->pi_tuple_size; | |
| 983 | 983 | ti->metadata_size = bi->metadata_size; |
| 984 | 984 | ti->pi_offset = bi->pi_offset; |
| 985 | 985 | ti->interval_exp = bi->interval_exp; |
| @@ -10437,7 +10437,7 @@ end: · 10436 unmodified lines | ||
| 10437 | 10437 | (u64 *)(lin_dma_pkts_arr), DEBUGFS_WRITE64); |
| 10438 | 10438 | WREG32(sob_addr, 0); |
| 10439 | 10439 | |
| 10440 | − kfree(lin_dma_pkts_arr); | |
| 10440 | + kvfree(lin_dma_pkts_arr); | |
| 10441 | 10441 | |
| 10442 | 10442 | return rc; |
| 10443 | 10443 | } |
| @@ -315,7 +315,7 @@ static void __iomem *einj_get_parameter_address(void) · 314 unmodified lines | ||
| 315 | 315 | memcpy_fromio(&v5param, p, v5param_size); |
| 316 | 316 | acpi5 = 1; |
| 317 | 317 | check_vendor_extension(pa_v5, &v5param); |
| 318 | − if (available_error_type & ACPI65_EINJV2_SUPP) { | |
| 318 | + if (is_v2 && available_error_type & ACPI65_EINJV2_SUPP) { | |
| 319 | 319 | len = v5param.einjv2_struct.length; |
| 320 | 320 | offset = offsetof(struct einjv2_extension_struct, component_arr); |
| 321 | 321 | max_nr_components = (len - offset) / |
| @@ -540,6 +540,9 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, · 218 unmodified lines | ||
| 540 | 540 | struct set_error_type_with_address *v5param; |
| 541 | 541 | |
| 542 | 542 | v5param = kmalloc(v5param_size, GFP_KERNEL); |
| 543 | + if (!v5param) | |
| 544 | + return -ENOMEM; | |
| 545 | + | |
| 543 | 546 | memcpy_fromio(v5param, einj_param, v5param_size); |
| 544 | 547 | v5param->type = type; |
| 545 | 548 | if (type & ACPI5_VENDOR_BIT) { |
| @@ -1091,7 +1094,7 @@ err_put_table: · 545 unmodified lines | ||
| 1091 | 1094 | return rc; |
| 1092 | 1095 | } |
| 1093 | 1096 | |
| 1094 | −static void __exit einj_remove(struct faux_device *fdev) | |
| 1097 | +static void einj_remove(struct faux_device *fdev) | |
| 1095 | 1098 | { |
| 1096 | 1099 | struct apei_exec_context ctx; |
| 1097 | 1100 | |
| @@ -1114,15 +1117,9 @@ static void __exit einj_remove(struct faux_device *fdev) · 16 unmodified lines | ||
| 1114 | 1117 | } |
| 1115 | 1118 | |
| 1116 | 1119 | static struct faux_device *einj_dev; |
| 1117 | −/* | |
| 1118 | − * einj_remove() lives in .exit.text. For drivers registered via | |
| 1119 | − * platform_driver_probe() this is ok because they cannot get unbound at | |
| 1120 | − * runtime. So mark the driver struct with __refdata to prevent modpost | |
| 1121 | − * triggering a section mismatch warning. | |
| 1122 | − */ | |
| 1123 | −static struct faux_device_ops einj_device_ops __refdata = { | |
| 1120 | +static struct faux_device_ops einj_device_ops = { | |
| 1124 | 1121 | .probe = einj_probe, |
| 1125 | − .remove = __exit_p(einj_remove), | |
| 1122 | + .remove = einj_remove, | |
| 1126 | 1123 | }; |
| 1127 | 1124 | |
| 1128 | 1125 | static int __init einj_init(void) |
| @@ -329,7 +329,7 @@ static bool applicable_image(const void *data, struct pfru_update_cap_info *cap, · 328 unmodified lines | ||
| 329 | 329 | if (type == PFRU_CODE_INJECT_TYPE) |
| 330 | 330 | return payload_hdr->rt_ver >= cap->code_rt_version; |
| 331 | 331 | |
| 332 | − return payload_hdr->rt_ver >= cap->drv_rt_version; | |
| 332 | + return payload_hdr->svn_ver >= cap->drv_svn; | |
| 333 | 333 | } |
| 334 | 334 | |
| 335 | 335 | static void print_update_debug_info(struct pfru_updated_result *result, |
| @@ -279,6 +279,19 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) · 278 unmodified lines | ||
| 279 | 279 | return NULL; |
| 280 | 280 | } |
| 281 | 281 | |
| 282 | +static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb) | |
| 283 | +{ | |
| 284 | + struct atmtcp_hdr *hdr; | |
| 285 | + | |
| 286 | + if (skb->len < sizeof(struct atmtcp_hdr)) | |
| 287 | + return -EINVAL; | |
| 288 | + | |
| 289 | + hdr = (struct atmtcp_hdr *)skb->data; | |
| 290 | + if (hdr->length == ATMTCP_HDR_MAGIC) | |
| 291 | + return -EINVAL; | |
| 292 | + | |
| 293 | + return 0; | |
| 294 | +} | |
| 282 | 295 | |
| 283 | 296 | static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) |
| 284 | 297 | { |
| @@ -288,9 +301,6 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) · 3 unmodified lines | ||
| 288 | 301 | struct sk_buff *new_skb; |
| 289 | 302 | int result = 0; |
| 290 | 303 | |
| 291 | − if (skb->len < sizeof(struct atmtcp_hdr)) | |
| 292 | − goto done; | |
| 293 | − | |
| 294 | 304 | dev = vcc->dev_data; |
| 295 | 305 | hdr = (struct atmtcp_hdr *) skb->data; |
| 296 | 306 | if (hdr->length == ATMTCP_HDR_MAGIC) { |
| @@ -347,6 +357,7 @@ static const struct atmdev_ops atmtcp_v_dev_ops = { · 50 unmodified lines | ||
| 347 | 357 | |
| 348 | 358 | static const struct atmdev_ops atmtcp_c_dev_ops = { |
| 349 | 359 | .close = atmtcp_c_close, |
| 360 | + .pre_send = atmtcp_c_pre_send, | |
| 350 | 361 | .send = atmtcp_c_send |
| 351 | 362 | }; |
| 352 | 363 | |
| @@ -675,7 +675,7 @@ static void dpm_async_resume_subordinate(struct device *dev, async_func_t func) · 674 unmodified lines | ||
| 675 | 675 | idx = device_links_read_lock(); |
| 676 | 676 | |
| 677 | 677 | /* Start processing the device's "async" consumers. */ |
| 678 | − list_for_each_entry_rcu(link, &dev->links.consumers, s_node) | |
| 678 | + list_for_each_entry_rcu_locked(link, &dev->links.consumers, s_node) | |
| 679 | 679 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
| 680 | 680 | dpm_async_with_cleanup(link->consumer, func); |
| 681 | 681 | |
| @@ -1330,7 +1330,7 @@ static void dpm_async_suspend_superior(struct device *dev, async_func_t func) · 648 unmodified lines | ||
| 1330 | 1330 | idx = device_links_read_lock(); |
| 1331 | 1331 | |
| 1332 | 1332 | /* Start processing the device's "async" suppliers. */ |
| 1333 | − list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) | |
| 1333 | + list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) | |
| 1334 | 1334 | if (READ_ONCE(link->status) != DL_STATE_DORMANT) |
| 1335 | 1335 | dpm_async_with_cleanup(link->supplier, func); |
| 1336 | 1336 | |
| @@ -137,20 +137,29 @@ static void loop_global_unlock(struct loop_device *lo, bool global) · 136 unmodified lines | ||
| 137 | 137 | static int max_part; |
| 138 | 138 | static int part_shift; |
| 139 | 139 | |
| 140 | −static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file) | |
| 140 | +static loff_t lo_calculate_size(struct loop_device *lo, struct file *file) | |
| 141 | 141 | { |
| 142 | + struct kstat stat; | |
| 142 | 143 | loff_t loopsize; |
| 144 | + int ret; | |
| 143 | 145 | |
| 144 | − /* Compute loopsize in bytes */ | |
| 145 | − loopsize = i_size_read(file->f_mapping->host); | |
| 146 | − if (offset > 0) | |
| 147 | − loopsize -= offset; | |
| 146 | + /* | |
| 147 | + * Get the accurate file size. This provides better results than | |
| 148 | + * cached inode data, particularly for network filesystems where | |
| 149 | + * metadata may be stale. | |
| 150 | + */ | |
| 151 | + ret = vfs_getattr_nosec(&file->f_path, &stat, STATX_SIZE, 0); | |
| 152 | + if (ret) | |
| 153 | + return 0; | |
| 154 | + | |
| 155 | + loopsize = stat.size; | |
| 156 | + if (lo->lo_offset > 0) | |
| 157 | + loopsize -= lo->lo_offset; | |
| 148 | 158 | /* offset is beyond i_size, weird but possible */ |
| 149 | 159 | if (loopsize < 0) |
| 150 | 160 | return 0; |
| 151 | − | |
| 152 | − if (sizelimit > 0 && sizelimit < loopsize) | |
| 153 | − loopsize = sizelimit; | |
| 161 | + if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize) | |
| 162 | + loopsize = lo->lo_sizelimit; | |
| 154 | 163 | /* |
| 155 | 164 | * Unfortunately, if we want to do I/O on the device, |
| 156 | 165 | * the number of 512-byte sectors has to fit into a sector_t. |
| @@ -158,11 +167,6 @@ static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file) · 1 unmodified line | ||
| 158 | 167 | return loopsize >> 9; |
| 159 | 168 | } |
| 160 | 169 | |
| 161 | −static loff_t get_loop_size(struct loop_device *lo, struct file *file) | |
| 162 | −{ | |
| 163 | − return get_size(lo->lo_offset, lo->lo_sizelimit, file); | |
| 164 | −} | |
| 165 | − | |
| 166 | 170 | /* |
| 167 | 171 | * We support direct I/O only if lo_offset is aligned with the logical I/O size |
| 168 | 172 | * of backing device, and the logical block size of loop is bigger than that of |
| @@ -569,7 +573,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, · 400 unmodified lines | ||
| 569 | 573 | error = -EINVAL; |
| 570 | 574 | |
| 571 | 575 | /* size of the new backing store needs to be the same */ |
| 572 | − if (get_loop_size(lo, file) != get_loop_size(lo, old_file)) | |
| 576 | + if (lo_calculate_size(lo, file) != lo_calculate_size(lo, old_file)) | |
| 573 | 577 | goto out_err; |
| 574 | 578 | |
| 575 | 579 | /* |
| @@ -1063,7 +1067,7 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode, · 487 unmodified lines | ||
| 1063 | 1067 | loop_update_dio(lo); |
| 1064 | 1068 | loop_sysfs_init(lo); |
| 1065 | 1069 | |
| 1066 | − size = get_loop_size(lo, file); | |
| 1070 | + size = lo_calculate_size(lo, file); | |
| 1067 | 1071 | loop_set_size(lo, size); |
| 1068 | 1072 | |
| 1069 | 1073 | /* Order wrt reading lo_state in loop_validate_file(). */ |
| @@ -1255,8 +1259,7 @@ out_unfreeze: · 185 unmodified lines | ||
| 1255 | 1259 | if (partscan) |
| 1256 | 1260 | clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); |
| 1257 | 1261 | if (!err && size_changed) { |
| 1258 | − loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit, | |
| 1259 | − lo->lo_backing_file); | |
| 1262 | + loff_t new_size = lo_calculate_size(lo, lo->lo_backing_file); | |
| 1260 | 1263 | loop_set_size(lo, new_size); |
| 1261 | 1264 | } |
| 1262 | 1265 | out_unlock: |
| @@ -1399,7 +1402,7 @@ static int loop_set_capacity(struct loop_device *lo) · 136 unmodified lines | ||
| 1399 | 1402 | if (unlikely(lo->lo_state != Lo_bound)) |
| 1400 | 1403 | return -ENXIO; |
| 1401 | 1404 | |
| 1402 | − size = get_loop_size(lo, lo->lo_backing_file); | |
| 1405 | + size = lo_calculate_size(lo, lo->lo_backing_file); | |
| 1403 | 1406 | loop_set_size(lo, size); |
| 1404 | 1407 | |
| 1405 | 1408 | return 0; |
| @@ -129,8 +129,7 @@ static int cdx_rpmsg_probe(struct rpmsg_device *rpdev) · 128 unmodified lines | ||
| 129 | 129 | |
| 130 | 130 | chinfo.src = RPMSG_ADDR_ANY; |
| 131 | 131 | chinfo.dst = rpdev->dst; |
| 132 | − strscpy(chinfo.name, cdx_rpmsg_id_table[0].name, | |
| 133 | − strlen(cdx_rpmsg_id_table[0].name)); | |
| 132 | + strscpy(chinfo.name, cdx_rpmsg_id_table[0].name, sizeof(chinfo.name)); | |
| 134 | 133 | |
| 135 | 134 | cdx_mcdi->ept = rpmsg_create_ept(rpdev, cdx_rpmsg_cb, NULL, chinfo); |
| 136 | 135 | if (!cdx_mcdi->ept) { |
| @@ -1587,6 +1587,9 @@ static int do_insnlist_ioctl(struct comedi_device *dev, · 1586 unmodified lines | ||
| 1587 | 1587 | memset(&data[n], 0, (MIN_SAMPLES - n) * |
| 1588 | 1588 | sizeof(unsigned int)); |
| 1589 | 1589 | } |
| 1590 | + } else { | |
| 1591 | + memset(data, 0, max_t(unsigned int, n, MIN_SAMPLES) * | |
| 1592 | + sizeof(unsigned int)); | |
| 1590 | 1593 | } |
| 1591 | 1594 | ret = parse_insn(dev, insns + i, data, file); |
| 1592 | 1595 | if (ret < 0) |
| @@ -1670,6 +1673,8 @@ static int do_insn_ioctl(struct comedi_device *dev, · 77 unmodified lines | ||
| 1670 | 1673 | memset(&data[insn->n], 0, |
| 1671 | 1674 | (MIN_SAMPLES - insn->n) * sizeof(unsigned int)); |
| 1672 | 1675 | } |
| 1676 | + } else { | |
| 1677 | + memset(data, 0, n_data * sizeof(unsigned int)); | |
| 1673 | 1678 | } |
| 1674 | 1679 | ret = parse_insn(dev, insn, data, file); |
| 1675 | 1680 | if (ret < 0) |
| @@ -620,11 +620,9 @@ static int insn_rw_emulate_bits(struct comedi_device *dev, · 619 unmodified lines | ||
| 620 | 620 | unsigned int chan = CR_CHAN(insn->chanspec); |
| 621 | 621 | unsigned int base_chan = (chan < 32) ? 0 : chan; |
| 622 | 622 | unsigned int _data[2]; |
| 623 | + unsigned int i; | |
| 623 | 624 | int ret; |
| 624 | 625 | |
| 625 | − if (insn->n == 0) | |
| 626 | − return 0; | |
| 627 | − | |
| 628 | 626 | memset(_data, 0, sizeof(_data)); |
| 629 | 627 | memset(&_insn, 0, sizeof(_insn)); |
| 630 | 628 | _insn.insn = INSN_BITS; |
| @@ -635,18 +633,21 @@ static int insn_rw_emulate_bits(struct comedi_device *dev, · 4 unmodified lines | ||
| 635 | 633 | if (insn->insn == INSN_WRITE) { |
| 636 | 634 | if (!(s->subdev_flags & SDF_WRITABLE)) |
| 637 | 635 | return -EINVAL; |
| 638 | − _data[0] = 1U << (chan - base_chan); /* mask */ | |
| 639 | − _data[1] = data[0] ? (1U << (chan - base_chan)) : 0; /* bits */ | |
| 636 | + _data[0] = 1U << (chan - base_chan); /* mask */ | |
| 640 | 637 | } |
| 638 | + for (i = 0; i < insn->n; i++) { | |
| 639 | + if (insn->insn == INSN_WRITE) | |
| 640 | + _data[1] = data[i] ? _data[0] : 0; /* bits */ | |
| 641 | 641 | |
| 642 | − ret = s->insn_bits(dev, s, &_insn, _data); | |
| 643 | − if (ret < 0) | |
| 644 | − return ret; | |
| 642 | + ret = s->insn_bits(dev, s, &_insn, _data); | |
| 643 | + if (ret < 0) | |
| 644 | + return ret; | |
| 645 | 645 | |
| 646 | − if (insn->insn == INSN_READ) | |
| 647 | − data[0] = (_data[1] >> (chan - base_chan)) & 1; | |
| 646 | + if (insn->insn == INSN_READ) | |
| 647 | + data[i] = (_data[1] >> (chan - base_chan)) & 1; | |
| 648 | + } | |
| 648 | 649 | |
| 649 | − return 1; | |
| 650 | + return insn->n; | |
| 650 | 651 | } |
| 651 | 652 | |
| 652 | 653 | static int __comedi_device_postconfig_async(struct comedi_device *dev, |
| @@ -328,7 +328,8 @@ static int pcl726_attach(struct comedi_device *dev, · 327 unmodified lines | ||
| 328 | 328 | * Hook up the external trigger source interrupt only if the |
| 329 | 329 | * user config option is valid and the board supports interrupts. |
| 330 | 330 | */ |
| 331 | − if (it->options[1] && (board->irq_mask & (1 << it->options[1]))) { | |
| 331 | + if (it->options[1] > 0 && it->options[1] < 16 && | |
| 332 | + (board->irq_mask & (1U << it->options[1]))) { | |
| 332 | 333 | ret = request_irq(it->options[1], pcl726_interrupt, 0, |
| 333 | 334 | dev->board_name, dev); |
| 334 | 335 | if (ret == 0) { |
| @@ -287,20 +287,15 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, · 286 unmodified lines | ||
| 287 | 287 | return 0; |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | − if (tick_nohz_tick_stopped()) { | |
| 291 | − /* | |
| 292 | − * If the tick is already stopped, the cost of possible short | |
| 293 | − * idle duration misprediction is much higher, because the CPU | |
| 294 | − * may be stuck in a shallow idle state for a long time as a | |
| 295 | − * result of it. In that case say we might mispredict and use | |
| 296 | − * the known time till the closest timer event for the idle | |
| 297 | − * state selection. | |
| 298 | − */ | |
| 299 | − if (predicted_ns < TICK_NSEC) | |
| 300 | − predicted_ns = data->next_timer_ns; | |
| 301 | − } else if (latency_req > predicted_ns) { | |
| 302 | − latency_req = predicted_ns; | |
| 303 | − } | |
| 290 | + /* | |
| 291 | + * If the tick is already stopped, the cost of possible short idle | |
| 292 | + * duration misprediction is much higher, because the CPU may be stuck | |
| 293 | + * in a shallow idle state for a long time as a result of it. In that | |
| 294 | + * case, say we might mispredict and use the known time till the closest | |
| 295 | + * timer event for the idle state selection. | |
| 296 | + */ | |
| 297 | + if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC) | |
| 298 | + predicted_ns = data->next_timer_ns; | |
| 304 | 299 | |
| 305 | 300 | /* |
| 306 | 301 | * Find the idle state with the lowest power while satisfying |
| @@ -316,13 +311,15 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, · 9 unmodified lines | ||
| 316 | 311 | if (idx == -1) |
| 317 | 312 | idx = i; /* first enabled state */ |
| 318 | 313 | |
| 314 | + if (s->exit_latency_ns > latency_req) | |
| 315 | + break; | |
| 316 | + | |
| 319 | 317 | if (s->target_residency_ns > predicted_ns) { |
| 320 | 318 | /* |
| 321 | 319 | * Use a physical idle state, not busy polling, unless |
| 322 | 320 | * a timer is going to trigger soon enough. |
| 323 | 321 | */ |
| 324 | 322 | if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) && |
| 325 | − s->exit_latency_ns <= latency_req && | |
| 326 | 323 | s->target_residency_ns <= data->next_timer_ns) { |
| 327 | 324 | predicted_ns = s->target_residency_ns; |
| 328 | 325 | idx = i; |
| @@ -354,8 +351,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, · 25 unmodified lines | ||
| 354 | 351 | |
| 355 | 352 | return idx; |
| 356 | 353 | } |
| 357 | − if (s->exit_latency_ns > latency_req) | |
| 358 | − break; | |
| 359 | 354 | |
| 360 | 355 | idx = i; |
| 361 | 356 | } |
| @@ -405,12 +405,12 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt) · 404 unmodified lines | ||
| 405 | 405 | } |
| 406 | 406 | } |
| 407 | 407 | |
| 408 | − priv->dma_nelms = | |
| 409 | − dma_map_sgtable(mgr->dev.parent, sgt, DMA_TO_DEVICE, 0); | |
| 410 | − if (priv->dma_nelms == 0) { | |
| 408 | + err = dma_map_sgtable(mgr->dev.parent, sgt, DMA_TO_DEVICE, 0); | |
| 409 | + if (err) { | |
| 411 | 410 | dev_err(&mgr->dev, "Unable to DMA map (TO_DEVICE)\n"); |
| 412 | − return -ENOMEM; | |
| 411 | + return err; | |
| 413 | 412 | } |
| 413 | + priv->dma_nelms = sgt->nents; | |
| 414 | 414 | |
| 415 | 415 | /* enable clock */ |
| 416 | 416 | err = clk_enable(priv->clk); |
| @@ -344,6 +344,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { · 343 unmodified lines | ||
| 344 | 344 | .ignore_interrupt = "AMDI0030:00@8", |
| 345 | 345 | }, |
| 346 | 346 | }, |
| 347 | + { | |
| 348 | + /* | |
| 349 | + * Spurious wakeups from TP_ATTN# pin | |
| 350 | + * Found in BIOS 5.35 | |
| 351 | + * https://gitlab.freedesktop.org/drm/amd/-/issues/4482 | |
| 352 | + */ | |
| 353 | + .matches = { | |
| 354 | + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | |
| 355 | + DMI_MATCH(DMI_PRODUCT_FAMILY, "ProArt PX13"), | |
| 356 | + }, | |
| 357 | + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { | |
| 358 | + .ignore_wake = "ASCP1A00:00@8", | |
| 359 | + }, | |
| 360 | + }, | |
| 347 | 361 | {} /* Terminating entry */ |
| 348 | 362 | }; |
| 349 | 363 | |
| @@ -514,7 +514,7 @@ bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, · 513 unmodified lines | ||
| 514 | 514 | return false; |
| 515 | 515 | |
| 516 | 516 | if (drm_gem_is_imported(obj)) { |
| 517 | − struct dma_buf *dma_buf = obj->dma_buf; | |
| 517 | + struct dma_buf *dma_buf = obj->import_attach->dmabuf; | |
| 518 | 518 | |
| 519 | 519 | if (dma_buf->ops != &amdgpu_dmabuf_ops) |
| 520 | 520 | /* No XGMI with non AMD GPUs */ |
| @@ -317,7 +317,8 @@ static int amdgpu_gem_object_open(struct drm_gem_object *obj, · 316 unmodified lines | ||
| 317 | 317 | */ |
| 318 | 318 | if (!vm->is_compute_context || !vm->process_info) |
| 319 | 319 | return 0; |
| 320 | − if (!drm_gem_is_imported(obj) || !dma_buf_is_dynamic(obj->dma_buf)) | |
| 320 | + if (!drm_gem_is_imported(obj) || | |
| 321 | + !dma_buf_is_dynamic(obj->import_attach->dmabuf)) | |
| 321 | 322 | return 0; |
| 322 | 323 | mutex_lock_nested(&vm->process_info->lock, 1); |
| 323 | 324 | if (!WARN_ON(!vm->process_info->eviction_fence)) { |
| @@ -1283,7 +1283,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, · 1282 unmodified lines | ||
| 1283 | 1283 | struct drm_gem_object *obj = &bo->tbo.base; |
| 1284 | 1284 | |
| 1285 | 1285 | if (drm_gem_is_imported(obj) && bo_va->is_xgmi) { |
| 1286 | − struct dma_buf *dma_buf = obj->dma_buf; | |
| 1286 | + struct dma_buf *dma_buf = obj->import_attach->dmabuf; | |
| 1287 | 1287 | struct drm_gem_object *gobj = dma_buf->priv; |
| 1288 | 1288 | struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj); |
| 1289 | 1289 | |
| @@ -7792,6 +7792,9 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn, · 7791 unmodified lines | ||
| 7792 | 7792 | struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn); |
| 7793 | 7793 | int ret; |
| 7794 | 7794 | |
| 7795 | + if (WARN_ON(unlikely(!old_con_state || !new_con_state))) | |
| 7796 | + return -EINVAL; | |
| 7797 | + | |
| 7795 | 7798 | trace_amdgpu_dm_connector_atomic_check(new_con_state); |
| 7796 | 7799 | |
| 7797 | 7800 | if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { |
| @@ -299,6 +299,25 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable) · 298 unmodified lines | ||
| 299 | 299 | irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id); |
| 300 | 300 | |
| 301 | 301 | if (enable) { |
| 302 | + struct dc *dc = adev->dm.dc; | |
| 303 | + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); | |
| 304 | + struct psr_settings *psr = &acrtc_state->stream->link->psr_settings; | |
| 305 | + struct replay_settings *pr = &acrtc_state->stream->link->replay_settings; | |
| 306 | + bool sr_supported = (psr->psr_version != DC_PSR_VERSION_UNSUPPORTED) || | |
| 307 | + pr->config.replay_supported; | |
| 308 | + | |
| 309 | + /* | |
| 310 | + * IPS & self-refresh feature can cause vblank counter resets between | |
| 311 | + * vblank disable and enable. | |
| 312 | + * It may cause system stuck due to waiting for the vblank counter. | |
| 313 | + * Call this function to estimate missed vblanks by using timestamps and | |
| 314 | + * update the vblank counter in DRM. | |
| 315 | + */ | |
| 316 | + if (dc->caps.ips_support && | |
| 317 | + dc->config.disable_ips != DMUB_IPS_DISABLE_ALL && | |
| 318 | + sr_supported && vblank->config.disable_immediate) | |
| 319 | + drm_crtc_vblank_restore(crtc); | |
| 320 | + | |
| 302 | 321 | /* vblank irq on -> Only need vupdate irq in vrr mode */ |
| 303 | 322 | if (amdgpu_dm_crtc_vrr_active(acrtc_state)) |
| 304 | 323 | rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true); |
| @@ -174,11 +174,8 @@ static struct graphics_object_id bios_parser_get_connector_id( · 173 unmodified lines | ||
| 174 | 174 | return object_id; |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | − if (tbl->ucNumberOfObjects <= i) { | |
| 178 | − dm_error("Can't find connector id %d in connector table of size %d.\n", | |
| 179 | − i, tbl->ucNumberOfObjects); | |
| 177 | + if (tbl->ucNumberOfObjects <= i) | |
| 180 | 178 | return object_id; |
| 181 | − } | |
| 182 | 179 | |
| 183 | 180 | id = le16_to_cpu(tbl->asObjects[i].usObjectID); |
| 184 | 181 | object_id = object_id_from_bios_object_id(id); |
| @@ -993,7 +993,7 @@ static enum bp_result set_pixel_clock_v3( · 992 unmodified lines | ||
| 993 | 993 | allocation.sPCLKInput.usFbDiv = |
| 994 | 994 | cpu_to_le16((uint16_t)bp_params->feedback_divider); |
| 995 | 995 | allocation.sPCLKInput.ucFracFbDiv = |
| 996 | − (uint8_t)bp_params->fractional_feedback_divider; | |
| 996 | + (uint8_t)(bp_params->fractional_feedback_divider / 100000); | |
| 997 | 997 | allocation.sPCLKInput.ucPostDiv = |
| 998 | 998 | (uint8_t)bp_params->pixel_clock_post_divider; |
| 999 | 999 | |
| @@ -72,9 +72,9 @@ static const struct state_dependent_clocks dce80_max_clks_by_state[] = { · 71 unmodified lines | ||
| 72 | 72 | /* ClocksStateLow */ |
| 73 | 73 | { .display_clk_khz = 352000, .pixel_clk_khz = 330000}, |
| 74 | 74 | /* ClocksStateNominal */ |
| 75 | −{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, | |
| 75 | +{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 }, | |
| 76 | 76 | /* ClocksStatePerformance */ |
| 77 | −{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; | |
| 77 | +{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 } }; | |
| 78 | 78 | |
| 79 | 79 | int dentist_get_divider_from_did(int did) |
| 80 | 80 | { |
| @@ -391,8 +391,6 @@ static void dce_pplib_apply_display_requirements( · 310 unmodified lines | ||
| 391 | 391 | { |
| 392 | 392 | struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; |
| 393 | 393 | |
| 394 | − pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); | |
| 395 | − | |
| 396 | 394 | dce110_fill_display_configs(context, pp_display_cfg); |
| 397 | 395 | |
| 398 | 396 | if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) |
| @@ -405,11 +403,9 @@ static void dce_update_clocks(struct clk_mgr *clk_mgr_base, · 6 unmodified lines | ||
| 405 | 403 | { |
| 406 | 404 | struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); |
| 407 | 405 | struct dm_pp_power_level_change_request level_change_req; |
| 408 | − int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; | |
| 409 | − | |
| 410 | − /*TODO: W/A for dal3 linux, investigate why this works */ | |
| 411 | − if (!clk_mgr_dce->dfs_bypass_active) | |
| 412 | − patched_disp_clk = patched_disp_clk * 115 / 100; | |
| 406 | + const int max_disp_clk = | |
| 407 | + clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; | |
| 408 | + int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz); | |
| 413 | 409 | |
| 414 | 410 | level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); |
| 415 | 411 | /* get max clock state from PPLIB */ |
| @@ -120,9 +120,15 @@ void dce110_fill_display_configs( · 119 unmodified lines | ||
| 120 | 120 | const struct dc_state *context, |
| 121 | 121 | struct dm_pp_display_configuration *pp_display_cfg) |
| 122 | 122 | { |
| 123 | + struct dc *dc = context->clk_mgr->ctx->dc; | |
| 123 | 124 | int j; |
| 124 | 125 | int num_cfgs = 0; |
| 125 | 126 | |
| 127 | + pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); | |
| 128 | + pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz; | |
| 129 | + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; | |
| 130 | + pp_display_cfg->crtc_index = dc->res_pool->res_cap->num_timing_generator; | |
| 131 | + | |
| 126 | 132 | for (j = 0; j < context->stream_count; j++) { |
| 127 | 133 | int k; |
| 128 | 134 | |
| @@ -164,6 +170,23 @@ void dce110_fill_display_configs( · 35 unmodified lines | ||
| 164 | 170 | cfg->v_refresh /= stream->timing.h_total; |
| 165 | 171 | cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) |
| 166 | 172 | / stream->timing.v_total; |
| 173 | + | |
| 174 | + /* Find first CRTC index and calculate its line time. | |
| 175 | + * This is necessary for DPM on SI GPUs. | |
| 176 | + */ | |
| 177 | + if (cfg->pipe_idx < pp_display_cfg->crtc_index) { | |
| 178 | + const struct dc_crtc_timing *timing = | |
| 179 | + &context->streams[0]->timing; | |
| 180 | + | |
| 181 | + pp_display_cfg->crtc_index = cfg->pipe_idx; | |
| 182 | + pp_display_cfg->line_time_in_us = | |
| 183 | + timing->h_total * 10000 / timing->pix_clk_100hz; | |
| 184 | + } | |
| 185 | + } | |
| 186 | + | |
| 187 | + if (!num_cfgs) { | |
| 188 | + pp_display_cfg->crtc_index = 0; | |
| 189 | + pp_display_cfg->line_time_in_us = 0; | |
| 167 | 190 | } |
| 168 | 191 | |
| 169 | 192 | pp_display_cfg->display_count = num_cfgs; |
| @@ -223,25 +246,8 @@ void dce11_pplib_apply_display_requirements( · 53 unmodified lines | ||
| 223 | 246 | pp_display_cfg->min_engine_clock_deep_sleep_khz |
| 224 | 247 | = context->bw_ctx.bw.dce.sclk_deep_sleep_khz; |
| 225 | 248 | |
| 226 | − pp_display_cfg->avail_mclk_switch_time_us = | |
| 227 | − dce110_get_min_vblank_time_us(context); | |
| 228 | − /* TODO: dce11.2*/ | |
| 229 | − pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; | |
| 230 | − | |
| 231 | − pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz; | |
| 232 | − | |
| 233 | 249 | dce110_fill_display_configs(context, pp_display_cfg); |
| 234 | 250 | |
| 235 | − /* TODO: is this still applicable?*/ | |
| 236 | − if (pp_display_cfg->display_count == 1) { | |
| 237 | − const struct dc_crtc_timing *timing = | |
| 238 | − &context->streams[0]->timing; | |
| 239 | − | |
| 240 | − pp_display_cfg->crtc_index = | |
| 241 | − pp_display_cfg->disp_configs[0].pipe_idx; | |
| 242 | − pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz; | |
| 243 | − } | |
| 244 | − | |
| 245 | 251 | if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) |
| 246 | 252 | dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); |
| 247 | 253 | } |
| @@ -83,22 +83,13 @@ static const struct state_dependent_clocks dce60_max_clks_by_state[] = { · 82 unmodified lines | ||
| 83 | 83 | static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) |
| 84 | 84 | { |
| 85 | 85 | struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); |
| 86 | − int dprefclk_wdivider; | |
| 87 | − int dp_ref_clk_khz; | |
| 88 | − int target_div; | |
| 86 | + struct dc_context *ctx = clk_mgr_base->ctx; | |
| 87 | + int dp_ref_clk_khz = 0; | |
| 89 | 88 | |
| 90 | − /* DCE6 has no DPREFCLK_CNTL to read DP Reference Clock source */ | |
| 91 | − | |
| 92 | − /* Read the mmDENTIST_DISPCLK_CNTL to get the currently | |
| 93 | − * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ | |
| 94 | − REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); | |
| 95 | − | |
| 96 | − /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ | |
| 97 | − target_div = dentist_get_divider_from_did(dprefclk_wdivider); | |
| 98 | − | |
| 99 | − /* Calculate the current DFS clock, in kHz.*/ | |
| 100 | − dp_ref_clk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR | |
| 101 | − * clk_mgr->base.dentist_vco_freq_khz) / target_div; | |
| 89 | + if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev)) | |
| 90 | + dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency; | |
| 91 | + else | |
| 92 | + dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz; | |
| 102 | 93 | |
| 103 | 94 | return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz); |
| 104 | 95 | } |
| @@ -109,8 +100,6 @@ static void dce60_pplib_apply_display_requirements( · 4 unmodified lines | ||
| 109 | 100 | { |
| 110 | 101 | struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; |
| 111 | 102 | |
| 112 | − pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); | |
| 113 | − | |
| 114 | 103 | dce110_fill_display_configs(context, pp_display_cfg); |
| 115 | 104 | |
| 116 | 105 | if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) |
| @@ -123,11 +112,9 @@ static void dce60_update_clocks(struct clk_mgr *clk_mgr_base, · 6 unmodified lines | ||
| 123 | 112 | { |
| 124 | 113 | struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); |
| 125 | 114 | struct dm_pp_power_level_change_request level_change_req; |
| 126 | − int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; | |
| 127 | − | |
| 128 | − /*TODO: W/A for dal3 linux, investigate why this works */ | |
| 129 | − if (!clk_mgr_dce->dfs_bypass_active) | |
| 130 | − patched_disp_clk = patched_disp_clk * 115 / 100; | |
| 115 | + const int max_disp_clk = | |
| 116 | + clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; | |
| 117 | + int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz); | |
| 131 | 118 | |
| 132 | 119 | level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); |
| 133 | 120 | /* get max clock state from PPLIB */ |
| @@ -217,11 +217,24 @@ static bool create_links( · 216 unmodified lines | ||
| 217 | 217 | connectors_num, |
| 218 | 218 | num_virtual_links); |
| 219 | 219 | |
| 220 | − // condition loop on link_count to allow skipping invalid indices | |
| 220 | + /* When getting the number of connectors, the VBIOS reports the number of valid indices, | |
| 221 | + * but it doesn't say which indices are valid, and not every index has an actual connector. | |
| 222 | + * So, if we don't find a connector on an index, that is not an error. | |
| 223 | + * | |
| 224 | + * - There is no guarantee that the first N indices will be valid | |
| 225 | + * - VBIOS may report a higher amount of valid indices than there are actual connectors | |
| 226 | + * - Some VBIOS have valid configurations for more connectors than there actually are | |
| 227 | + * on the card. This may be because the manufacturer used the same VBIOS for different | |
| 228 | + * variants of the same card. | |
| 229 | + */ | |
| 221 | 230 | for (i = 0; dc->link_count < connectors_num && i < MAX_LINKS; i++) { |
| 231 | + struct graphics_object_id connector_id = bios->funcs->get_connector_id(bios, i); | |
| 222 | 232 | struct link_init_data link_init_params = {0}; |
| 223 | 233 | struct dc_link *link; |
| 224 | 234 | |
| 235 | + if (connector_id.id == CONNECTOR_ID_UNKNOWN) | |
| 236 | + continue; | |
| 237 | + | |
| 225 | 238 | DC_LOG_DC("BIOS object table - printing link object info for connector number: %d, link_index: %d", i, dc->link_count); |
| 226 | 239 | |
| 227 | 240 | link_init_params.ctx = dc->ctx; |
| @@ -896,13 +896,13 @@ void dce110_link_encoder_construct( · 895 unmodified lines | ||
| 896 | 896 | enc110->base.id, &bp_cap_info); |
| 897 | 897 | |
| 898 | 898 | /* Override features with DCE-specific values */ |
| 899 | − if (BP_RESULT_OK == result) { | |
| 899 | + if (result == BP_RESULT_OK) { | |
| 900 | 900 | enc110->base.features.flags.bits.IS_HBR2_CAPABLE = |
| 901 | 901 | bp_cap_info.DP_HBR2_EN; |
| 902 | 902 | enc110->base.features.flags.bits.IS_HBR3_CAPABLE = |
| 903 | 903 | bp_cap_info.DP_HBR3_EN; |
| 904 | 904 | enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; |
| 905 | − } else { | |
| 905 | + } else if (result != BP_RESULT_NORECORD) { | |
| 906 | 906 | DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", |
| 907 | 907 | __func__, |
| 908 | 908 | result); |
| @@ -1798,13 +1798,13 @@ void dce60_link_encoder_construct( · 889 unmodified lines | ||
| 1798 | 1798 | enc110->base.id, &bp_cap_info); |
| 1799 | 1799 | |
| 1800 | 1800 | /* Override features with DCE-specific values */ |
| 1801 | − if (BP_RESULT_OK == result) { | |
| 1801 | + if (result == BP_RESULT_OK) { | |
| 1802 | 1802 | enc110->base.features.flags.bits.IS_HBR2_CAPABLE = |
| 1803 | 1803 | bp_cap_info.DP_HBR2_EN; |
| 1804 | 1804 | enc110->base.features.flags.bits.IS_HBR3_CAPABLE = |
| 1805 | 1805 | bp_cap_info.DP_HBR3_EN; |
| 1806 | 1806 | enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; |
| 1807 | − } else { | |
| 1807 | + } else if (result != BP_RESULT_NORECORD) { | |
| 1808 | 1808 | DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", |
| 1809 | 1809 | __func__, |
| 1810 | 1810 | result); |
| @@ -4,7 +4,6 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #include "dc.h" |
| 6 | 6 | #include "dc_dmub_srv.h" |
| 7 | −#include "dc_dp_types.h" | |
| 8 | 7 | #include "dmub/dmub_srv.h" |
| 9 | 8 | #include "core_types.h" |
| 10 | 9 | #include "dmub_replay.h" |
| @@ -44,45 +43,21 @@ static void dmub_replay_get_state(struct dmub_replay *dmub, enum replay_state *s · 33 unmodified lines | ||
| 44 | 43 | /* |
| 45 | 44 | * Enable/Disable Replay. |
| 46 | 45 | */ |
| 47 | −static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait, uint8_t panel_inst, | |
| 48 | − struct dc_link *link) | |
| 46 | +static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait, uint8_t panel_inst) | |
| 49 | 47 | { |
| 50 | 48 | union dmub_rb_cmd cmd; |
| 51 | 49 | struct dc_context *dc = dmub->ctx; |
| 52 | 50 | uint32_t retry_count; |
| 53 | 51 | enum replay_state state = REPLAY_STATE_0; |
| 54 | − struct pipe_ctx *pipe_ctx = NULL; | |
| 55 | − struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx; | |
| 56 | − uint8_t i; | |
| 57 | 52 | |
| 58 | 53 | memset(&cmd, 0, sizeof(cmd)); |
| 59 | 54 | cmd.replay_enable.header.type = DMUB_CMD__REPLAY; |
| 60 | 55 | cmd.replay_enable.data.panel_inst = panel_inst; |
| 61 | 56 | |
| 62 | 57 | cmd.replay_enable.header.sub_type = DMUB_CMD__REPLAY_ENABLE; |
| 63 | − if (enable) { | |
| 58 | + if (enable) | |
| 64 | 59 | cmd.replay_enable.data.enable = REPLAY_ENABLE; |
| 65 | − // hpo stream/link encoder assignments are not static, need to update everytime we try to enable replay | |
| 66 | − if (link->cur_link_settings.link_rate >= LINK_RATE_UHBR10) { | |
| 67 | − for (i = 0; i < MAX_PIPES; i++) { | |
| 68 | − if (res_ctx && | |
| 69 | − res_ctx->pipe_ctx[i].stream && | |
| 70 | − res_ctx->pipe_ctx[i].stream->link && | |
| 71 | − res_ctx->pipe_ctx[i].stream->link == link && | |
| 72 | − res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) { | |
| 73 | − pipe_ctx = &res_ctx->pipe_ctx[i]; | |
| 74 | − //TODO: refactor for multi edp support | |
| 75 | − break; | |
| 76 | − } | |
| 77 | − } | |
| 78 | − | |
| 79 | − if (!pipe_ctx) | |
| 80 | − return; | |
| 81 | − | |
| 82 | − cmd.replay_enable.data.hpo_stream_enc_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; | |
| 83 | − cmd.replay_enable.data.hpo_link_enc_inst = pipe_ctx->link_res.hpo_dp_link_enc->inst; | |
| 84 | − } | |
| 85 | − } else | |
| 60 | + else | |
| 86 | 61 | cmd.replay_enable.data.enable = REPLAY_DISABLE; |
| 87 | 62 | |
| 88 | 63 | cmd.replay_enable.header.payload_bytes = sizeof(struct dmub_rb_cmd_replay_enable_data); |
| @@ -174,17 +149,6 @@ static bool dmub_replay_copy_settings(struct dmub_replay *dmub, · 85 unmodified lines | ||
| 174 | 149 | copy_settings_data->digbe_inst = replay_context->digbe_inst; |
| 175 | 150 | copy_settings_data->digfe_inst = replay_context->digfe_inst; |
| 176 | 151 | |
| 177 | − if (link->cur_link_settings.link_rate >= LINK_RATE_UHBR10) { | |
| 178 | − if (pipe_ctx->stream_res.hpo_dp_stream_enc) | |
| 179 | − copy_settings_data->hpo_stream_enc_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; | |
| 180 | − else | |
| 181 | − copy_settings_data->hpo_stream_enc_inst = 0; | |
| 182 | − if (pipe_ctx->link_res.hpo_dp_link_enc) | |
| 183 | − copy_settings_data->hpo_link_enc_inst = pipe_ctx->link_res.hpo_dp_link_enc->inst; | |
| 184 | − else | |
| 185 | − copy_settings_data->hpo_link_enc_inst = 0; | |
| 186 | − } | |
| 187 | − | |
| 188 | 152 | if (pipe_ctx->plane_res.dpp) |
| 189 | 153 | copy_settings_data->dpp_inst = pipe_ctx->plane_res.dpp->inst; |
| 190 | 154 | else |
| @@ -247,7 +211,6 @@ static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub, · 56 unmodified lines | ||
| 247 | 211 | pCmd->header.type = DMUB_CMD__REPLAY; |
| 248 | 212 | pCmd->header.sub_type = DMUB_CMD__REPLAY_SET_COASTING_VTOTAL; |
| 249 | 213 | pCmd->header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data); |
| 250 | − pCmd->replay_set_coasting_vtotal_data.panel_inst = panel_inst; | |
| 251 | 214 | pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF); |
| 252 | 215 | pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16; |
| 253 | 216 | |
| @@ -19,7 +19,7 @@ struct dmub_replay_funcs { · 18 unmodified lines | ||
| 19 | 19 | void (*replay_get_state)(struct dmub_replay *dmub, enum replay_state *state, |
| 20 | 20 | uint8_t panel_inst); |
| 21 | 21 | void (*replay_enable)(struct dmub_replay *dmub, bool enable, bool wait, |
| 22 | − uint8_t panel_inst, struct dc_link *link); | |
| 22 | + uint8_t panel_inst); | |
| 23 | 23 | bool (*replay_copy_settings)(struct dmub_replay *dmub, struct dc_link *link, |
| 24 | 24 | struct replay_context *replay_context, uint8_t panel_inst); |
| 25 | 25 | void (*replay_set_power_opt)(struct dmub_replay *dmub, unsigned int power_opt, |
| @@ -944,7 +944,7 @@ bool edp_set_replay_allow_active(struct dc_link *link, const bool *allow_active, · 943 unmodified lines | ||
| 944 | 944 | // TODO: Handle mux change case if force_static is set |
| 945 | 945 | // If force_static is set, just change the replay_allow_active state directly |
| 946 | 946 | if (replay != NULL && link->replay_settings.replay_feature_enabled) |
| 947 | − replay->funcs->replay_enable(replay, *allow_active, wait, panel_inst, link); | |
| 947 | + replay->funcs->replay_enable(replay, *allow_active, wait, panel_inst); | |
| 948 | 948 | link->replay_settings.replay_allow_active = *allow_active; |
| 949 | 949 | } |
| 950 | 950 | |
| @@ -4047,14 +4047,6 @@ struct dmub_cmd_replay_copy_settings_data { · 4046 unmodified lines | ||
| 4047 | 4047 | * DIG BE HW instance. |
| 4048 | 4048 | */ |
| 4049 | 4049 | uint8_t digbe_inst; |
| 4050 | − /** | |
| 4051 | − * @hpo_stream_enc_inst: HPO stream encoder instance | |
| 4052 | − */ | |
| 4053 | − uint8_t hpo_stream_enc_inst; | |
| 4054 | − /** | |
| 4055 | − * @hpo_link_enc_inst: HPO link encoder instance | |
| 4056 | − */ | |
| 4057 | − uint8_t hpo_link_enc_inst; | |
| 4058 | 4050 | /** |
| 4059 | 4051 | * AUX HW instance. |
| 4060 | 4052 | */ |
| @@ -4159,18 +4151,6 @@ struct dmub_rb_cmd_replay_enable_data { · 98 unmodified lines | ||
| 4159 | 4151 | * This does not support HDMI/DP2 for now. |
| 4160 | 4152 | */ |
| 4161 | 4153 | uint8_t phy_rate; |
| 4162 | − /** | |
| 4163 | − * @hpo_stream_enc_inst: HPO stream encoder instance | |
| 4164 | − */ | |
| 4165 | − uint8_t hpo_stream_enc_inst; | |
| 4166 | − /** | |
| 4167 | − * @hpo_link_enc_inst: HPO link encoder instance | |
| 4168 | − */ | |
| 4169 | − uint8_t hpo_link_enc_inst; | |
| 4170 | − /** | |
| 4171 | − * @pad: Align structure to 4 byte boundary. | |
| 4172 | − */ | |
| 4173 | − uint8_t pad[2]; | |
| 4174 | 4154 | }; |
| 4175 | 4155 | |
| 4176 | 4156 | /** |
| @@ -260,6 +260,9 @@ enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp) · 259 unmodified lines | ||
| 260 | 260 | return MOD_HDCP_STATUS_FAILURE; |
| 261 | 261 | } |
| 262 | 262 | |
| 263 | + if (!display) | |
| 264 | + return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; | |
| 265 | + | |
| 263 | 266 | hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf; |
| 264 | 267 | |
| 265 | 268 | mutex_lock(&psp->hdcp_context.mutex); |
| @@ -1697,9 +1697,11 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu, · 1696 unmodified lines | ||
| 1697 | 1697 | uint32_t *min_power_limit) |
| 1698 | 1698 | { |
| 1699 | 1699 | struct smu_table_context *table_context = &smu->smu_table; |
| 1700 | + struct smu_14_0_2_powerplay_table *powerplay_table = | |
| 1701 | + table_context->power_play_table; | |
| 1700 | 1702 | PPTable_t *pptable = table_context->driver_pptable; |
| 1701 | 1703 | CustomSkuTable_t *skutable = &pptable->CustomSkuTable; |
| 1702 | − uint32_t power_limit; | |
| 1704 | + uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0; | |
| 1703 | 1705 | uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; |
| 1704 | 1706 | |
| 1705 | 1707 | if (smu_v14_0_get_current_power_limit(smu, &power_limit)) |
| @@ -1712,11 +1714,29 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu, · 6 unmodified lines | ||
| 1712 | 1714 | if (default_power_limit) |
| 1713 | 1715 | *default_power_limit = power_limit; |
| 1714 | 1716 | |
| 1715 | − if (max_power_limit) | |
| 1716 | − *max_power_limit = msg_limit; | |
| 1717 | + if (powerplay_table) { | |
| 1718 | + if (smu->od_enabled && | |
| 1719 | + smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { | |
| 1720 | + od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt; | |
| 1721 | + od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; | |
| 1722 | + } else if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { | |
| 1723 | + od_percent_upper = 0; | |
| 1724 | + od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; | |
| 1725 | + } | |
| 1726 | + } | |
| 1727 | + | |
| 1728 | + dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n", | |
| 1729 | + od_percent_upper, od_percent_lower, power_limit); | |
| 1730 | + | |
| 1731 | + if (max_power_limit) { | |
| 1732 | + *max_power_limit = msg_limit * (100 + od_percent_upper); | |
| 1733 | + *max_power_limit /= 100; | |
| 1734 | + } | |
| 1717 | 1735 | |
| 1718 | − if (min_power_limit) | |
| 1719 | − *min_power_limit = 0; | |
| 1736 | + if (min_power_limit) { | |
| 1737 | + *min_power_limit = power_limit * (100 + od_percent_lower); | |
| 1738 | + *min_power_limit /= 100; | |
| 1739 | + } | |
| 1720 | 1740 | |
| 1721 | 1741 | return 0; |
| 1722 | 1742 | } |
| @@ -1474,8 +1474,8 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data) · 1473 unmodified lines | ||
| 1474 | 1474 | |
| 1475 | 1475 | dp = devm_drm_bridge_alloc(dev, struct analogix_dp_device, bridge, |
| 1476 | 1476 | &analogix_dp_bridge_funcs); |
| 1477 | − if (!dp) | |
| 1478 | − return ERR_PTR(-ENOMEM); | |
| 1477 | + if (IS_ERR(dp)) | |
| 1478 | + return ERR_CAST(dp); | |
| 1479 | 1479 | |
| 1480 | 1480 | dp->dev = &pdev->dev; |
| 1481 | 1481 | dp->dpms_mode = DRM_MODE_DPMS_OFF; |
| @@ -2432,6 +2432,8 @@ static const struct drm_gpuvm_ops lock_ops = { · 2431 unmodified lines | ||
| 2432 | 2432 | * |
| 2433 | 2433 | * The expected usage is: |
| 2434 | 2434 | * |
| 2435 | + * .. code-block:: c | |
| 2436 | + * | |
| 2435 | 2437 | * vm_bind { |
| 2436 | 2438 | * struct drm_exec exec; |
| 2437 | 2439 | * |
| @@ -381,6 +381,26 @@ struct DecFifo { · 380 unmodified lines | ||
| 381 | 381 | len: usize, |
| 382 | 382 | } |
| 383 | 383 | |
| 384 | +// On arm32 architecture, dividing an `u64` by a constant will generate a call | |
| 385 | +// to `__aeabi_uldivmod` which is not present in the kernel. | |
| 386 | +// So use the multiply by inverse method for this architecture. | |
| 387 | +fn div10(val: u64) -> u64 { | |
| 388 | + if cfg!(target_arch = "arm") { | |
| 389 | + let val_h = val >> 32; | |
| 390 | + let val_l = val & 0xFFFFFFFF; | |
| 391 | + let b_h: u64 = 0x66666666; | |
| 392 | + let b_l: u64 = 0x66666667; | |
| 393 | + | |
| 394 | + let tmp1 = val_h * b_l + ((val_l * b_l) >> 32); | |
| 395 | + let tmp2 = val_l * b_h + (tmp1 & 0xffffffff); | |
| 396 | + let tmp3 = val_h * b_h + (tmp1 >> 32) + (tmp2 >> 32); | |
| 397 | + | |
| 398 | + tmp3 >> 2 | |
| 399 | + } else { | |
| 400 | + val / 10 | |
| 401 | + } | |
| 402 | +} | |
| 403 | + | |
| 384 | 404 | impl DecFifo { |
| 385 | 405 | fn push(&mut self, data: u64, len: usize) { |
| 386 | 406 | let mut chunk = data; |
| @@ -389,7 +409,7 @@ impl DecFifo { · 2 unmodified lines | ||
| 389 | 409 | } |
| 390 | 410 | for i in 0..len { |
| 391 | 411 | self.decimals[i] = (chunk % 10) as u8; |
| 392 | − chunk /= 10; | |
| 412 | + chunk = div10(chunk); | |
| 393 | 413 | } |
| 394 | 414 | self.len += len; |
| 395 | 415 | } |
| @@ -325,6 +325,17 @@ static int hibmc_dp_link_downgrade_training_eq(struct hibmc_dp_dev *dp) · 324 unmodified lines | ||
| 325 | 325 | return hibmc_dp_link_reduce_rate(dp); |
| 326 | 326 | } |
| 327 | 327 | |
| 328 | +static void hibmc_dp_update_caps(struct hibmc_dp_dev *dp) | |
| 329 | +{ | |
| 330 | + dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE]; | |
| 331 | + if (dp->link.cap.link_rate > DP_LINK_BW_8_1 || !dp->link.cap.link_rate) | |
| 332 | + dp->link.cap.link_rate = DP_LINK_BW_8_1; | |
| 333 | + | |
| 334 | + dp->link.cap.lanes = dp->dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; | |
| 335 | + if (dp->link.cap.lanes > HIBMC_DP_LANE_NUM_MAX) | |
| 336 | + dp->link.cap.lanes = HIBMC_DP_LANE_NUM_MAX; | |
| 337 | +} | |
| 338 | + | |
| 328 | 339 | int hibmc_dp_link_training(struct hibmc_dp_dev *dp) |
| 329 | 340 | { |
| 330 | 341 | struct hibmc_dp_link *link = &dp->link; |
| @@ -334,8 +345,7 @@ int hibmc_dp_link_training(struct hibmc_dp_dev *dp) · 3 unmodified lines | ||
| 334 | 345 | if (ret) |
| 335 | 346 | drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret); |
| 336 | 347 | |
| 337 | − dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE]; | |
| 338 | − dp->link.cap.lanes = 0x2; | |
| 348 | + hibmc_dp_update_caps(dp); | |
| 339 | 349 | |
| 340 | 350 | ret = hibmc_dp_get_serdes_rate_cfg(dp); |
| 341 | 351 | if (ret < 0) |
| @@ -32,7 +32,7 @@ · 31 unmodified lines | ||
| 32 | 32 | |
| 33 | 33 | DEFINE_DRM_GEM_FOPS(hibmc_fops); |
| 34 | 34 | |
| 35 | −static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "vblank", "hpd" }; | |
| 35 | +static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "hibmc-vblank", "hibmc-hpd" }; | |
| 36 | 36 | |
| 37 | 37 | static irqreturn_t hibmc_interrupt(int irq, void *arg) |
| 38 | 38 | { |
| @@ -115,6 +115,8 @@ static const struct drm_mode_config_funcs hibmc_mode_funcs = { · 76 unmodified lines | ||
| 115 | 115 | static int hibmc_kms_init(struct hibmc_drm_private *priv) |
| 116 | 116 | { |
| 117 | 117 | struct drm_device *dev = &priv->dev; |
| 118 | + struct drm_encoder *encoder; | |
| 119 | + u32 clone_mask = 0; | |
| 118 | 120 | int ret; |
| 119 | 121 | |
| 120 | 122 | ret = drmm_mode_config_init(dev); |
| @@ -154,6 +156,12 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv) · 33 unmodified lines | ||
| 154 | 156 | return ret; |
| 155 | 157 | } |
| 156 | 158 | |
| 159 | + drm_for_each_encoder(encoder, dev) | |
| 160 | + clone_mask |= drm_encoder_mask(encoder); | |
| 161 | + | |
| 162 | + drm_for_each_encoder(encoder, dev) | |
| 163 | + encoder->possible_clones = clone_mask; | |
| 164 | + | |
| 157 | 165 | return 0; |
| 158 | 166 | } |
| 159 | 167 | |
| @@ -277,7 +285,6 @@ static void hibmc_unload(struct drm_device *dev) · 117 unmodified lines | ||
| 277 | 285 | static int hibmc_msi_init(struct drm_device *dev) |
| 278 | 286 | { |
| 279 | 287 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 280 | − char name[32] = {0}; | |
| 281 | 288 | int valid_irq_num; |
| 282 | 289 | int irq; |
| 283 | 290 | int ret; |
| @@ -292,9 +299,6 @@ static int hibmc_msi_init(struct drm_device *dev) · 8 unmodified lines | ||
| 292 | 299 | valid_irq_num = ret; |
| 293 | 300 | |
| 294 | 301 | for (int i = 0; i < valid_irq_num; i++) { |
| 295 | − snprintf(name, ARRAY_SIZE(name) - 1, "%s-%s-%s", | |
| 296 | − dev->driver->name, pci_name(pdev), g_irqs_names_map[i]); | |
| 297 | − | |
| 298 | 302 | irq = pci_irq_vector(pdev, i); |
| 299 | 303 | |
| 300 | 304 | if (i) |
| @@ -302,10 +306,10 @@ static int hibmc_msi_init(struct drm_device *dev) · 1 unmodified line | ||
| 302 | 306 | ret = devm_request_threaded_irq(&pdev->dev, irq, |
| 303 | 307 | hibmc_dp_interrupt, |
| 304 | 308 | hibmc_dp_hpd_isr, |
| 305 | − IRQF_SHARED, name, dev); | |
| 309 | + IRQF_SHARED, g_irqs_names_map[i], dev); | |
| 306 | 310 | else |
| 307 | 311 | ret = devm_request_irq(&pdev->dev, irq, hibmc_interrupt, |
| 308 | − IRQF_SHARED, name, dev); | |
| 312 | + IRQF_SHARED, g_irqs_names_map[i], dev); | |
| 309 | 313 | if (ret) { |
| 310 | 314 | drm_err(dev, "install irq failed: %d\n", ret); |
| 311 | 315 | return ret; |
| @@ -323,13 +327,13 @@ static int hibmc_load(struct drm_device *dev) · 11 unmodified lines | ||
| 323 | 327 | |
| 324 | 328 | ret = hibmc_hw_init(priv); |
| 325 | 329 | if (ret) |
| 326 | − goto err; | |
| 330 | + return ret; | |
| 327 | 331 | |
| 328 | 332 | ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0), |
| 329 | 333 | pci_resource_len(pdev, 0)); |
| 330 | 334 | if (ret) { |
| 331 | 335 | drm_err(dev, "Error initializing VRAM MM; %d\n", ret); |
| 332 | − goto err; | |
| 336 | + return ret; | |
| 333 | 337 | } |
| 334 | 338 | |
| 335 | 339 | ret = hibmc_kms_init(priv); |
| @@ -69,6 +69,7 @@ int hibmc_de_init(struct hibmc_drm_private *priv); · 68 unmodified lines | ||
| 69 | 69 | int hibmc_vdac_init(struct hibmc_drm_private *priv); |
| 70 | 70 | |
| 71 | 71 | int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *connector); |
| 72 | +void hibmc_ddc_del(struct hibmc_vdac *vdac); | |
| 72 | 73 | |
| 73 | 74 | int hibmc_dp_init(struct hibmc_drm_private *priv); |
| 74 | 75 | |
| @@ -95,3 +95,8 @@ int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *vdac) · 94 unmodified lines | ||
| 95 | 95 | |
| 96 | 96 | return i2c_bit_add_bus(&vdac->adapter); |
| 97 | 97 | } |
| 98 | + | |
| 99 | +void hibmc_ddc_del(struct hibmc_vdac *vdac) | |
| 100 | +{ | |
| 101 | + i2c_del_adapter(&vdac->adapter); | |
| 102 | +} | |
| @@ -53,7 +53,7 @@ static void hibmc_connector_destroy(struct drm_connector *connector) · 52 unmodified lines | ||
| 53 | 53 | { |
| 54 | 54 | struct hibmc_vdac *vdac = to_hibmc_vdac(connector); |
| 55 | 55 | |
| 56 | − i2c_del_adapter(&vdac->adapter); | |
| 56 | + hibmc_ddc_del(vdac); | |
| 57 | 57 | drm_connector_cleanup(connector); |
| 58 | 58 | } |
| 59 | 59 | |
| @@ -110,7 +110,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv) · 50 unmodified lines | ||
| 110 | 110 | ret = drmm_encoder_init(dev, encoder, NULL, DRM_MODE_ENCODER_DAC, NULL); |
| 111 | 111 | if (ret) { |
| 112 | 112 | drm_err(dev, "failed to init encoder: %d\n", ret); |
| 113 | − return ret; | |
| 113 | + goto err; | |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | 116 | drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs); |
| @@ -121,7 +121,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv) · 4 unmodified lines | ||
| 121 | 121 | &vdac->adapter); |
| 122 | 122 | if (ret) { |
| 123 | 123 | drm_err(dev, "failed to init connector: %d\n", ret); |
| 124 | − return ret; | |
| 124 | + goto err; | |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | drm_connector_helper_add(connector, &hibmc_connector_helper_funcs); |
| @@ -131,4 +131,9 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv) · 3 unmodified lines | ||
| 131 | 131 | connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; |
| 132 | 132 | |
| 133 | 133 | return 0; |
| 134 | + | |
| 135 | +err: | |
| 136 | + hibmc_ddc_del(vdac); | |
| 137 | + | |
| 138 | + return ret; | |
| 134 | 139 | } |
| @@ -1506,10 +1506,14 @@ u32 gen11_gu_misc_irq_ack(struct intel_display *display, const u32 master_ctl) · 1505 unmodified lines | ||
| 1506 | 1506 | if (!(master_ctl & GEN11_GU_MISC_IRQ)) |
| 1507 | 1507 | return 0; |
| 1508 | 1508 | |
| 1509 | + intel_display_rpm_assert_block(display); | |
| 1510 | + | |
| 1509 | 1511 | iir = intel_de_read(display, GEN11_GU_MISC_IIR); |
| 1510 | 1512 | if (likely(iir)) |
| 1511 | 1513 | intel_de_write(display, GEN11_GU_MISC_IIR, iir); |
| 1512 | 1514 | |
| 1515 | + intel_display_rpm_assert_unblock(display); | |
| 1516 | + | |
| 1513 | 1517 | return iir; |
| 1514 | 1518 | } |
| 1515 | 1519 | |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include "intel_modeset_lock.h" |
| 24 | 24 | #include "intel_tc.h" |
| 25 | 25 | |
| 26 | +#define DP_PIN_ASSIGNMENT_NONE 0x0 | |
| 26 | 27 | #define DP_PIN_ASSIGNMENT_C 0x3 |
| 27 | 28 | #define DP_PIN_ASSIGNMENT_D 0x4 |
| 28 | 29 | #define DP_PIN_ASSIGNMENT_E 0x5 |
| @@ -66,6 +67,7 @@ struct intel_tc_port { · 37 unmodified lines | ||
| 66 | 67 | enum tc_port_mode init_mode; |
| 67 | 68 | enum phy_fia phy_fia; |
| 68 | 69 | u8 phy_fia_idx; |
| 70 | + u8 max_lane_count; | |
| 69 | 71 | }; |
| 70 | 72 | |
| 71 | 73 | static enum intel_display_power_domain |
| @@ -307,6 +309,8 @@ static int lnl_tc_port_get_max_lane_count(struct intel_digital_port *dig_port) · 235 unmodified lines | ||
| 307 | 309 | REG_FIELD_GET(TCSS_DDI_STATUS_PIN_ASSIGNMENT_MASK, val); |
| 308 | 310 | |
| 309 | 311 | switch (pin_assignment) { |
| 312 | + case DP_PIN_ASSIGNMENT_NONE: | |
| 313 | + return 0; | |
| 310 | 314 | default: |
| 311 | 315 | MISSING_CASE(pin_assignment); |
| 312 | 316 | fallthrough; |
| @@ -365,12 +369,12 @@ static int intel_tc_port_get_max_lane_count(struct intel_digital_port *dig_port) · 52 unmodified lines | ||
| 365 | 369 | } |
| 366 | 370 | } |
| 367 | 371 | |
| 368 | −int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) | |
| 372 | +static int get_max_lane_count(struct intel_tc_port *tc) | |
| 369 | 373 | { |
| 370 | − struct intel_display *display = to_intel_display(dig_port); | |
| 371 | − struct intel_tc_port *tc = to_tc_port(dig_port); | |
| 374 | + struct intel_display *display = to_intel_display(tc->dig_port); | |
| 375 | + struct intel_digital_port *dig_port = tc->dig_port; | |
| 372 | 376 | |
| 373 | − if (!intel_encoder_is_tc(&dig_port->base) || tc->mode != TC_PORT_DP_ALT) | |
| 377 | + if (tc->mode != TC_PORT_DP_ALT) | |
| 374 | 378 | return 4; |
| 375 | 379 | |
| 376 | 380 | assert_tc_cold_blocked(tc); |
| @@ -384,6 +388,25 @@ int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) · 7 unmodified lines | ||
| 384 | 388 | return intel_tc_port_get_max_lane_count(dig_port); |
| 385 | 389 | } |
| 386 | 390 | |
| 391 | +static void read_pin_configuration(struct intel_tc_port *tc) | |
| 392 | +{ | |
| 393 | + tc->max_lane_count = get_max_lane_count(tc); | |
| 394 | +} | |
| 395 | + | |
| 396 | +int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) | |
| 397 | +{ | |
| 398 | + struct intel_display *display = to_intel_display(dig_port); | |
| 399 | + struct intel_tc_port *tc = to_tc_port(dig_port); | |
| 400 | + | |
| 401 | + if (!intel_encoder_is_tc(&dig_port->base)) | |
| 402 | + return 4; | |
| 403 | + | |
| 404 | + if (DISPLAY_VER(display) < 20) | |
| 405 | + return get_max_lane_count(tc); | |
| 406 | + | |
| 407 | + return tc->max_lane_count; | |
| 408 | +} | |
| 409 | + | |
| 387 | 410 | void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, |
| 388 | 411 | int required_lanes) |
| 389 | 412 | { |
| @@ -596,9 +619,12 @@ static void icl_tc_phy_get_hw_state(struct intel_tc_port *tc) · 206 unmodified lines | ||
| 596 | 619 | tc_cold_wref = __tc_cold_block(tc, &domain); |
| 597 | 620 | |
| 598 | 621 | tc->mode = tc_phy_get_current_mode(tc); |
| 599 | − if (tc->mode != TC_PORT_DISCONNECTED) | |
| 622 | + if (tc->mode != TC_PORT_DISCONNECTED) { | |
| 600 | 623 | tc->lock_wakeref = tc_cold_block(tc); |
| 601 | 624 | |
| 625 | + read_pin_configuration(tc); | |
| 626 | + } | |
| 627 | + | |
| 602 | 628 | __tc_cold_unblock(tc, domain, tc_cold_wref); |
| 603 | 629 | } |
| 604 | 630 | |
| @@ -656,8 +682,11 @@ static bool icl_tc_phy_connect(struct intel_tc_port *tc, · 51 unmodified lines | ||
| 656 | 682 | |
| 657 | 683 | tc->lock_wakeref = tc_cold_block(tc); |
| 658 | 684 | |
| 659 | − if (tc->mode == TC_PORT_TBT_ALT) | |
| 685 | + if (tc->mode == TC_PORT_TBT_ALT) { | |
| 686 | + read_pin_configuration(tc); | |
| 687 | + | |
| 660 | 688 | return true; |
| 689 | + } | |
| 661 | 690 | |
| 662 | 691 | if ((!tc_phy_is_ready(tc) || |
| 663 | 692 | !icl_tc_phy_take_ownership(tc, true)) && |
| @@ -668,6 +697,7 @@ static bool icl_tc_phy_connect(struct intel_tc_port *tc, · 4 unmodified lines | ||
| 668 | 697 | goto out_unblock_tc_cold; |
| 669 | 698 | } |
| 670 | 699 | |
| 700 | + read_pin_configuration(tc); | |
| 671 | 701 | |
| 672 | 702 | if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) |
| 673 | 703 | goto out_release_phy; |
| @@ -858,9 +888,12 @@ static void adlp_tc_phy_get_hw_state(struct intel_tc_port *tc) · 184 unmodified lines | ||
| 858 | 888 | port_wakeref = intel_display_power_get(display, port_power_domain); |
| 859 | 889 | |
| 860 | 890 | tc->mode = tc_phy_get_current_mode(tc); |
| 861 | − if (tc->mode != TC_PORT_DISCONNECTED) | |
| 891 | + if (tc->mode != TC_PORT_DISCONNECTED) { | |
| 862 | 892 | tc->lock_wakeref = tc_cold_block(tc); |
| 863 | 893 | |
| 894 | + read_pin_configuration(tc); | |
| 895 | + } | |
| 896 | + | |
| 864 | 897 | intel_display_power_put(display, port_power_domain, port_wakeref); |
| 865 | 898 | } |
| 866 | 899 | |
| @@ -873,6 +906,9 @@ static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes) · 6 unmodified lines | ||
| 873 | 906 | |
| 874 | 907 | if (tc->mode == TC_PORT_TBT_ALT) { |
| 875 | 908 | tc->lock_wakeref = tc_cold_block(tc); |
| 909 | + | |
| 910 | + read_pin_configuration(tc); | |
| 911 | + | |
| 876 | 912 | return true; |
| 877 | 913 | } |
| 878 | 914 | |
| @@ -894,6 +930,8 @@ static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes) · 15 unmodified lines | ||
| 894 | 930 | |
| 895 | 931 | tc->lock_wakeref = tc_cold_block(tc); |
| 896 | 932 | |
| 933 | + read_pin_configuration(tc); | |
| 934 | + | |
| 897 | 935 | if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) |
| 898 | 936 | goto out_unblock_tc_cold; |
| 899 | 937 | |
| @@ -1124,9 +1162,18 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc) · 224 unmodified lines | ||
| 1124 | 1162 | tc_cold_wref = __tc_cold_block(tc, &domain); |
| 1125 | 1163 | |
| 1126 | 1164 | tc->mode = tc_phy_get_current_mode(tc); |
| 1127 | − if (tc->mode != TC_PORT_DISCONNECTED) | |
| 1165 | + if (tc->mode != TC_PORT_DISCONNECTED) { | |
| 1128 | 1166 | tc->lock_wakeref = tc_cold_block(tc); |
| 1129 | 1167 | |
| 1168 | + read_pin_configuration(tc); | |
| 1169 | + /* | |
| 1170 | + * Set a valid lane count value for a DP-alt sink which got | |
| 1171 | + * disconnected. The driver can only disable the output on this PHY. | |
| 1172 | + */ | |
| 1173 | + if (tc->max_lane_count == 0) | |
| 1174 | + tc->max_lane_count = 4; | |
| 1175 | + } | |
| 1176 | + | |
| 1130 | 1177 | drm_WARN_ON(display->drm, |
| 1131 | 1178 | (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) && |
| 1132 | 1179 | !xelpdp_tc_phy_tcss_power_is_enabled(tc)); |
| @@ -1138,14 +1185,19 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes) · 5 unmodified lines | ||
| 1138 | 1185 | { |
| 1139 | 1186 | tc->lock_wakeref = tc_cold_block(tc); |
| 1140 | 1187 | |
| 1141 | − if (tc->mode == TC_PORT_TBT_ALT) | |
| 1188 | + if (tc->mode == TC_PORT_TBT_ALT) { | |
| 1189 | + read_pin_configuration(tc); | |
| 1190 | + | |
| 1142 | 1191 | return true; |
| 1192 | + } | |
| 1143 | 1193 | |
| 1144 | 1194 | if (!xelpdp_tc_phy_enable_tcss_power(tc, true)) |
| 1145 | 1195 | goto out_unblock_tccold; |
| 1146 | 1196 | |
| 1147 | 1197 | xelpdp_tc_phy_take_ownership(tc, true); |
| 1148 | 1198 | |
| 1199 | + read_pin_configuration(tc); | |
| 1200 | + | |
| 1149 | 1201 | if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) |
| 1150 | 1202 | goto out_release_phy; |
| 1151 | 1203 | |
| @@ -1226,14 +1278,19 @@ static void tc_phy_get_hw_state(struct intel_tc_port *tc) · 74 unmodified lines | ||
| 1226 | 1278 | tc->phy_ops->get_hw_state(tc); |
| 1227 | 1279 | } |
| 1228 | 1280 | |
| 1229 | −static bool tc_phy_is_ready_and_owned(struct intel_tc_port *tc, | |
| 1230 | − bool phy_is_ready, bool phy_is_owned) | |
| 1281 | +/* Is the PHY owned by display i.e. is it in legacy or DP-alt mode? */ | |
| 1282 | +static bool tc_phy_owned_by_display(struct intel_tc_port *tc, | |
| 1283 | + bool phy_is_ready, bool phy_is_owned) | |
| 1231 | 1284 | { |
| 1232 | 1285 | struct intel_display *display = to_intel_display(tc->dig_port); |
| 1233 | 1286 | |
| 1234 | − drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready); | |
| 1287 | + if (DISPLAY_VER(display) < 20) { | |
| 1288 | + drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready); | |
| 1235 | 1289 | |
| 1236 | − return phy_is_ready && phy_is_owned; | |
| 1290 | + return phy_is_ready && phy_is_owned; | |
| 1291 | + } else { | |
| 1292 | + return phy_is_owned; | |
| 1293 | + } | |
| 1237 | 1294 | } |
| 1238 | 1295 | |
| 1239 | 1296 | static bool tc_phy_is_connected(struct intel_tc_port *tc, |
| @@ -1244,7 +1301,7 @@ static bool tc_phy_is_connected(struct intel_tc_port *tc, · 4 unmodified lines | ||
| 1244 | 1301 | bool phy_is_owned = tc_phy_is_owned(tc); |
| 1245 | 1302 | bool is_connected; |
| 1246 | 1303 | |
| 1247 | − if (tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) | |
| 1304 | + if (tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned)) | |
| 1248 | 1305 | is_connected = port_pll_type == ICL_PORT_DPLL_MG_PHY; |
| 1249 | 1306 | else |
| 1250 | 1307 | is_connected = port_pll_type == ICL_PORT_DPLL_DEFAULT; |
| @@ -1352,7 +1409,7 @@ tc_phy_get_current_mode(struct intel_tc_port *tc) · 101 unmodified lines | ||
| 1352 | 1409 | phy_is_ready = tc_phy_is_ready(tc); |
| 1353 | 1410 | phy_is_owned = tc_phy_is_owned(tc); |
| 1354 | 1411 | |
| 1355 | − if (!tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) { | |
| 1412 | + if (!tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned)) { | |
| 1356 | 1413 | mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode); |
| 1357 | 1414 | } else { |
| 1358 | 1415 | drm_WARN_ON(display->drm, live_mode == TC_PORT_TBT_ALT); |
| @@ -1441,11 +1498,11 @@ static void intel_tc_port_reset_mode(struct intel_tc_port *tc, · 82 unmodified lines | ||
| 1441 | 1498 | intel_display_power_flush_work(display); |
| 1442 | 1499 | if (!intel_tc_cold_requires_aux_pw(dig_port)) { |
| 1443 | 1500 | enum intel_display_power_domain aux_domain; |
| 1444 | − bool aux_powered; | |
| 1445 | 1501 | |
| 1446 | 1502 | aux_domain = intel_aux_power_domain(dig_port); |
| 1447 | − aux_powered = intel_display_power_is_enabled(display, aux_domain); | |
| 1448 | − drm_WARN_ON(display->drm, aux_powered); | |
| 1503 | + if (intel_display_power_is_enabled(display, aux_domain)) | |
| 1504 | + drm_dbg_kms(display->drm, "Port %s: AUX unexpectedly powered\n", | |
| 1505 | + tc->port_name); | |
| 1449 | 1506 | } |
| 1450 | 1507 | |
| 1451 | 1508 | tc_phy_disconnect(tc); |
| @@ -634,6 +634,8 @@ static void cfl_ctx_workarounds_init(struct intel_engine_cs *engine, · 633 unmodified lines | ||
| 634 | 634 | static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, |
| 635 | 635 | struct i915_wa_list *wal) |
| 636 | 636 | { |
| 637 | + struct drm_i915_private *i915 = engine->i915; | |
| 638 | + | |
| 637 | 639 | /* Wa_1406697149 (WaDisableBankHangMode:icl) */ |
| 638 | 640 | wa_write(wal, GEN8_L3CNTLREG, GEN8_ERRDETBCTRL); |
| 639 | 641 | |
| @@ -669,6 +671,15 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, · 29 unmodified lines | ||
| 669 | 671 | |
| 670 | 672 | /* Wa_1406306137:icl,ehl */ |
| 671 | 673 | wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU); |
| 674 | + | |
| 675 | + if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) { | |
| 676 | + /* | |
| 677 | + * Disable Repacking for Compression (masked R/W access) | |
| 678 | + * before rendering compressed surfaces for display. | |
| 679 | + */ | |
| 680 | + wa_masked_en(wal, CACHE_MODE_0_GEN7, | |
| 681 | + DISABLE_REPACKING_FOR_COMPRESSION); | |
| 682 | + } | |
| 672 | 683 | } |
| 673 | 684 | |
| 674 | 685 | /* |
| @@ -2306,15 +2317,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) · 1631 unmodified lines | ||
| 2306 | 2317 | GEN8_RC_SEMA_IDLE_MSG_DISABLE); |
| 2307 | 2318 | } |
| 2308 | 2319 | |
| 2309 | − if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) { | |
| 2310 | − /* | |
| 2311 | − * "Disable Repacking for Compression (masked R/W access) | |
| 2312 | − * before rendering compressed surfaces for display." | |
| 2313 | − */ | |
| 2314 | − wa_masked_en(wal, CACHE_MODE_0_GEN7, | |
| 2315 | − DISABLE_REPACKING_FOR_COMPRESSION); | |
| 2316 | − } | |
| 2317 | − | |
| 2318 | 2320 | if (GRAPHICS_VER(i915) == 11) { |
| 2319 | 2321 | /* This is not an Wa. Enable for better image quality */ |
| 2320 | 2322 | wa_masked_en(wal, |
| @@ -60,14 +60,14 @@ · 59 unmodified lines | ||
| 60 | 60 | * virtual address in the GPU's VA space there is no guarantee that the actual |
| 61 | 61 | * mappings are created in the GPU's MMU. If the given memory is swapped out |
| 62 | 62 | * at the time the bind operation is executed the kernel will stash the mapping |
| 63 | − * details into it's internal alloctor and create the actual MMU mappings once | |
| 63 | + * details into it's internal allocator and create the actual MMU mappings once | |
| 64 | 64 | * the memory is swapped back in. While this is transparent for userspace, it is |
| 65 | 65 | * guaranteed that all the backing memory is swapped back in and all the memory |
| 66 | 66 | * mappings, as requested by userspace previously, are actually mapped once the |
| 67 | 67 | * DRM_NOUVEAU_EXEC ioctl is called to submit an exec job. |
| 68 | 68 | * |
| 69 | 69 | * A VM_BIND job can be executed either synchronously or asynchronously. If |
| 70 | − * exectued asynchronously, userspace may provide a list of syncobjs this job | |
| 70 | + * executed asynchronously, userspace may provide a list of syncobjs this job | |
| 71 | 71 | * will wait for and/or a list of syncobj the kernel will signal once the |
| 72 | 72 | * VM_BIND job finished execution. If executed synchronously the ioctl will |
| 73 | 73 | * block until the bind job is finished. For synchronous jobs the kernel will |
| @@ -82,7 +82,7 @@ · 8 unmodified lines | ||
| 82 | 82 | * Since VM_BIND jobs update the GPU's VA space on job submit, EXEC jobs do have |
| 83 | 83 | * an up to date view of the VA space. However, the actual mappings might still |
| 84 | 84 | * be pending. Hence, EXEC jobs require to have the particular fences - of |
| 85 | − * the corresponding VM_BIND jobs they depent on - attached to them. | |
| 85 | + * the corresponding VM_BIND jobs they depend on - attached to them. | |
| 86 | 86 | */ |
| 87 | 87 | |
| 88 | 88 | static int |
| @@ -219,7 +219,8 @@ nvif_vmm_ctor(struct nvif_mmu *mmu, const char *name, s32 oclass, · 218 unmodified lines | ||
| 219 | 219 | case RAW: args->type = NVIF_VMM_V0_TYPE_RAW; break; |
| 220 | 220 | default: |
| 221 | 221 | WARN_ON(1); |
| 222 | − return -EINVAL; | |
| 222 | + ret = -EINVAL; | |
| 223 | + goto done; | |
| 223 | 224 | } |
| 224 | 225 | |
| 225 | 226 | memcpy(args->data, argv, argc); |
| @@ -325,7 +325,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) · 324 unmodified lines | ||
| 325 | 325 | |
| 326 | 326 | rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), info.retries); |
| 327 | 327 | if (IS_ERR_OR_NULL(rpc)) { |
| 328 | − kfree(buf); | |
| 328 | + kvfree(buf); | |
| 329 | 329 | return rpc; |
| 330 | 330 | } |
| 331 | 331 | |
| @@ -334,7 +334,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) · 2 unmodified lines | ||
| 334 | 334 | |
| 335 | 335 | rpc = r535_gsp_msgq_recv_one_elem(gsp, &info); |
| 336 | 336 | if (IS_ERR_OR_NULL(rpc)) { |
| 337 | − kfree(buf); | |
| 337 | + kvfree(buf); | |
| 338 | 338 | return rpc; |
| 339 | 339 | } |
| 340 | 340 | |
| @@ -39,7 +39,8 @@ impl File { · 38 unmodified lines | ||
| 39 | 39 | _ => return Err(EINVAL), |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | − getparam.set_value(value); | |
| 42 | + #[allow(clippy::useless_conversion)] | |
| 43 | + getparam.set_value(value.into()); | |
| 43 | 44 | |
| 44 | 45 | Ok(0) |
| 45 | 46 | } |
| @@ -53,6 +53,7 @@ config ROCKCHIP_CDN_DP · 52 unmodified lines | ||
| 53 | 53 | bool "Rockchip cdn DP" |
| 54 | 54 | depends on EXTCON=y || (EXTCON=m && DRM_ROCKCHIP=m) |
| 55 | 55 | select DRM_DISPLAY_HELPER |
| 56 | + select DRM_BRIDGE_CONNECTOR | |
| 56 | 57 | select DRM_DISPLAY_DP_HELPER |
| 57 | 58 | help |
| 58 | 59 | This selects support for Rockchip SoC specific extensions |
| @@ -2579,12 +2579,13 @@ static int vop2_win_init(struct vop2 *vop2) · 2578 unmodified lines | ||
| 2579 | 2579 | } |
| 2580 | 2580 | |
| 2581 | 2581 | /* |
| 2582 | − * The window registers are only updated when config done is written. | |
| 2583 | − * Until that they read back the old value. As we read-modify-write | |
| 2584 | − * these registers mark them as non-volatile. This makes sure we read | |
| 2585 | − * the new values from the regmap register cache. | |
| 2582 | + * The window and video port registers are only updated when config | |
| 2583 | + * done is written. Until that they read back the old value. As we | |
| 2584 | + * read-modify-write these registers mark them as non-volatile. This | |
| 2585 | + * makes sure we read the new values from the regmap register cache. | |
| 2586 | 2586 | */ |
| 2587 | 2587 | static const struct regmap_range vop2_nonvolatile_range[] = { |
| 2588 | + regmap_reg_range(RK3568_VP0_CTRL_BASE, RK3588_VP3_CTRL_BASE + 255), | |
| 2588 | 2589 | regmap_reg_range(0x1000, 0x23ff), |
| 2589 | 2590 | }; |
| 2590 | 2591 | |
| @@ -1033,13 +1033,14 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) · 1032 unmodified lines | ||
| 1033 | 1033 | NULL : &result->dst_pitch; |
| 1034 | 1034 | |
| 1035 | 1035 | drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); |
| 1036 | − buf = le32buf_to_cpu(test, buf, dst_size / sizeof(u32)); | |
| 1036 | + buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); | |
| 1037 | 1037 | KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); |
| 1038 | 1038 | |
| 1039 | 1039 | buf = dst.vaddr; /* restore original value of buf */ |
| 1040 | 1040 | memset(buf, 0, dst_size); |
| 1041 | 1041 | |
| 1042 | 1042 | drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); |
| 1043 | + buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); | |
| 1043 | 1044 | KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); |
| 1044 | 1045 | } |
| 1045 | 1046 | |
| @@ -408,7 +408,7 @@ struct xe_migrate *xe_migrate_init(struct xe_tile *tile) · 407 unmodified lines | ||
| 408 | 408 | |
| 409 | 409 | /* Special layout, prepared below.. */ |
| 410 | 410 | vm = xe_vm_create(xe, XE_VM_FLAG_MIGRATION | |
| 411 | − XE_VM_FLAG_SET_TILE_ID(tile)); | |
| 411 | + XE_VM_FLAG_SET_TILE_ID(tile), NULL); | |
| 412 | 412 | if (IS_ERR(vm)) |
| 413 | 413 | return ERR_CAST(vm); |
| 414 | 414 | |
| @@ -101,7 +101,7 @@ static int allocate_gsc_client_resources(struct xe_gt *gt, · 100 unmodified lines | ||
| 101 | 101 | xe_assert(xe, hwe); |
| 102 | 102 | |
| 103 | 103 | /* PXP instructions must be issued from PPGTT */ |
| 104 | − vm = xe_vm_create(xe, XE_VM_FLAG_GSC); | |
| 104 | + vm = xe_vm_create(xe, XE_VM_FLAG_GSC, NULL); | |
| 105 | 105 | if (IS_ERR(vm)) |
| 106 | 106 | return PTR_ERR(vm); |
| 107 | 107 | |
| @@ -1640,7 +1640,7 @@ static void xe_vm_free_scratch(struct xe_vm *vm) · 1639 unmodified lines | ||
| 1640 | 1640 | } |
| 1641 | 1641 | } |
| 1642 | 1642 | |
| 1643 | −struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) | |
| 1643 | +struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef) | |
| 1644 | 1644 | { |
| 1645 | 1645 | struct drm_gem_object *vm_resv_obj; |
| 1646 | 1646 | struct xe_vm *vm; |
| @@ -1661,9 +1661,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) · 14 unmodified lines | ||
| 1661 | 1661 | vm->xe = xe; |
| 1662 | 1662 | |
| 1663 | 1663 | vm->size = 1ull << xe->info.va_bits; |
| 1664 | − | |
| 1665 | 1664 | vm->flags = flags; |
| 1666 | 1665 | |
| 1666 | + if (xef) | |
| 1667 | + vm->xef = xe_file_get(xef); | |
| 1667 | 1668 | /** |
| 1668 | 1669 | * GSC VMs are kernel-owned, only used for PXP ops and can sometimes be |
| 1669 | 1670 | * manipulated under the PXP mutex. However, the PXP mutex can be taken |
| @@ -1794,6 +1795,20 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) · 124 unmodified lines | ||
| 1794 | 1795 | if (number_tiles > 1) |
| 1795 | 1796 | vm->composite_fence_ctx = dma_fence_context_alloc(1); |
| 1796 | 1797 | |
| 1798 | + if (xef && xe->info.has_asid) { | |
| 1799 | + u32 asid; | |
| 1800 | + | |
| 1801 | + down_write(&xe->usm.lock); | |
| 1802 | + err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm, | |
| 1803 | + XA_LIMIT(1, XE_MAX_ASID - 1), | |
| 1804 | + &xe->usm.next_asid, GFP_KERNEL); | |
| 1805 | + up_write(&xe->usm.lock); | |
| 1806 | + if (err < 0) | |
| 1807 | + goto err_unlock_close; | |
| 1808 | + | |
| 1809 | + vm->usm.asid = asid; | |
| 1810 | + } | |
| 1811 | + | |
| 1797 | 1812 | trace_xe_vm_create(vm); |
| 1798 | 1813 | |
| 1799 | 1814 | return vm; |
| @@ -1814,6 +1829,8 @@ err_no_resv: · 14 unmodified lines | ||
| 1814 | 1829 | for_each_tile(tile, xe, id) |
| 1815 | 1830 | xe_range_fence_tree_fini(&vm->rftree[id]); |
| 1816 | 1831 | ttm_lru_bulk_move_fini(&xe->ttm, &vm->lru_bulk_move); |
| 1832 | + if (vm->xef) | |
| 1833 | + xe_file_put(vm->xef); | |
| 1817 | 1834 | kfree(vm); |
| 1818 | 1835 | if (flags & XE_VM_FLAG_LR_MODE) |
| 1819 | 1836 | xe_pm_runtime_put(xe); |
| @@ -2059,9 +2076,8 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, · 239 unmodified lines | ||
| 2059 | 2076 | struct xe_device *xe = to_xe_device(dev); |
| 2060 | 2077 | struct xe_file *xef = to_xe_file(file); |
| 2061 | 2078 | struct drm_xe_vm_create *args = data; |
| 2062 | − struct xe_tile *tile; | |
| 2063 | 2079 | struct xe_vm *vm; |
| 2064 | − u32 id, asid; | |
| 2080 | + u32 id; | |
| 2065 | 2081 | int err; |
| 2066 | 2082 | u32 flags = 0; |
| 2067 | 2083 | |
| @@ -2097,29 +2113,10 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, · 29 unmodified lines | ||
| 2097 | 2113 | if (args->flags & DRM_XE_VM_CREATE_FLAG_FAULT_MODE) |
| 2098 | 2114 | flags |= XE_VM_FLAG_FAULT_MODE; |
| 2099 | 2115 | |
| 2100 | − vm = xe_vm_create(xe, flags); | |
| 2116 | + vm = xe_vm_create(xe, flags, xef); | |
| 2101 | 2117 | if (IS_ERR(vm)) |
| 2102 | 2118 | return PTR_ERR(vm); |
| 2103 | 2119 | |
| 2104 | − if (xe->info.has_asid) { | |
| 2105 | − down_write(&xe->usm.lock); | |
| 2106 | − err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm, | |
| 2107 | − XA_LIMIT(1, XE_MAX_ASID - 1), | |
| 2108 | − &xe->usm.next_asid, GFP_KERNEL); | |
| 2109 | − up_write(&xe->usm.lock); | |
| 2110 | − if (err < 0) | |
| 2111 | − goto err_close_and_put; | |
| 2112 | − | |
| 2113 | − vm->usm.asid = asid; | |
| 2114 | − } | |
| 2115 | − | |
| 2116 | − vm->xef = xe_file_get(xef); | |
| 2117 | − | |
| 2118 | − /* Record BO memory for VM pagetable created against client */ | |
| 2119 | − for_each_tile(tile, xe, id) | |
| 2120 | − if (vm->pt_root[id]) | |
| 2121 | − xe_drm_client_add_bo(vm->xef->client, vm->pt_root[id]->bo); | |
| 2122 | − | |
| 2123 | 2120 | #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_MEM) |
| 2124 | 2121 | /* Warning: Security issue - never enable by default */ |
| 2125 | 2122 | args->reserved[0] = xe_bo_main_addr(vm->pt_root[0]->bo, XE_PAGE_SIZE); |
| @@ -3421,6 +3418,7 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, · 1295 unmodified lines | ||
| 3421 | 3418 | free_bind_ops: |
| 3422 | 3419 | if (args->num_binds > 1) |
| 3423 | 3420 | kvfree(*bind_ops); |
| 3421 | + *bind_ops = NULL; | |
| 3424 | 3422 | return err; |
| 3425 | 3423 | } |
| 3426 | 3424 | |
| @@ -3527,7 +3525,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 100 unmodified lines | ||
| 3527 | 3525 | struct xe_exec_queue *q = NULL; |
| 3528 | 3526 | u32 num_syncs, num_ufence = 0; |
| 3529 | 3527 | struct xe_sync_entry *syncs = NULL; |
| 3530 | − struct drm_xe_vm_bind_op *bind_ops; | |
| 3528 | + struct drm_xe_vm_bind_op *bind_ops = NULL; | |
| 3531 | 3529 | struct xe_vma_ops vops; |
| 3532 | 3530 | struct dma_fence *fence; |
| 3533 | 3531 | int err; |
| @@ -26,7 +26,7 @@ struct xe_sync_entry; · 25 unmodified lines | ||
| 26 | 26 | struct xe_svm_range; |
| 27 | 27 | struct drm_exec; |
| 28 | 28 | |
| 29 | −struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags); | |
| 29 | +struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef); | |
| 30 | 30 | |
| 31 | 31 | struct xe_vm *xe_vm_lookup(struct xe_file *xef, u32 id); |
| 32 | 32 | int xe_vma_cmp_vma_cb(const void *key, const struct rb_node *node); |
| @@ -143,10 +143,10 @@ static int rtl9300_i2c_write(struct rtl9300_i2c *i2c, u8 *buf, int len) · 142 unmodified lines | ||
| 143 | 143 | return -EIO; |
| 144 | 144 | |
| 145 | 145 | for (i = 0; i < len; i++) { |
| 146 | − if (i % 4 == 0) | |
| 147 | − vals[i/4] = 0; | |
| 148 | − vals[i/4] <<= 8; | |
| 149 | − vals[i/4] |= buf[i]; | |
| 146 | + unsigned int shift = (i % 4) * 8; | |
| 147 | + unsigned int reg = i / 4; | |
| 148 | + | |
| 149 | + vals[reg] |= buf[i] << shift; | |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | 152 | return regmap_bulk_write(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, |
| @@ -175,7 +175,7 @@ static int rtl9300_i2c_execute_xfer(struct rtl9300_i2c *i2c, char read_write, · 22 unmodified lines | ||
| 175 | 175 | return ret; |
| 176 | 176 | |
| 177 | 177 | ret = regmap_read_poll_timeout(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1, |
| 178 | − val, !(val & RTL9300_I2C_MST_CTRL1_I2C_TRIG), 100, 2000); | |
| 178 | + val, !(val & RTL9300_I2C_MST_CTRL1_I2C_TRIG), 100, 100000); | |
| 179 | 179 | if (ret) |
| 180 | 180 | return ret; |
| 181 | 181 | |
| @@ -281,15 +281,19 @@ static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned s · 99 unmodified lines | ||
| 281 | 281 | ret = rtl9300_i2c_reg_addr_set(i2c, command, 1); |
| 282 | 282 | if (ret) |
| 283 | 283 | goto out_unlock; |
| 284 | − ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0]); | |
| 284 | + if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) { | |
| 285 | + ret = -EINVAL; | |
| 286 | + goto out_unlock; | |
| 287 | + } | |
| 288 | + ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0] + 1); | |
| 285 | 289 | if (ret) |
| 286 | 290 | goto out_unlock; |
| 287 | 291 | if (read_write == I2C_SMBUS_WRITE) { |
| 288 | − ret = rtl9300_i2c_write(i2c, &data->block[1], data->block[0]); | |
| 292 | + ret = rtl9300_i2c_write(i2c, &data->block[0], data->block[0] + 1); | |
| 289 | 293 | if (ret) |
| 290 | 294 | goto out_unlock; |
| 291 | 295 | } |
| 292 | − len = data->block[0]; | |
| 296 | + len = data->block[0] + 1; | |
| 293 | 297 | break; |
| 294 | 298 | |
| 295 | 299 | default: |
| @@ -477,7 +477,7 @@ static irqreturn_t sca3300_trigger_handler(int irq, void *p) · 476 unmodified lines | ||
| 477 | 477 | struct iio_dev *indio_dev = pf->indio_dev; |
| 478 | 478 | struct sca3300_data *data = iio_priv(indio_dev); |
| 479 | 479 | int bit, ret, val, i = 0; |
| 480 | − IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX); | |
| 480 | + IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX) = { }; | |
| 481 | 481 | |
| 482 | 482 | iio_for_each_active_channel(indio_dev, bit) { |
| 483 | 483 | ret = sca3300_read_reg(data, indio_dev->channels[bit].address, &val); |
| @@ -1300,7 +1300,7 @@ config RN5T618_ADC · 1299 unmodified lines | ||
| 1300 | 1300 | |
| 1301 | 1301 | config ROHM_BD79124 |
| 1302 | 1302 | tristate "Rohm BD79124 ADC driver" |
| 1303 | − depends on I2C | |
| 1303 | + depends on I2C && GPIOLIB | |
| 1304 | 1304 | select REGMAP_I2C |
| 1305 | 1305 | select IIO_ADC_HELPER |
| 1306 | 1306 | help |
| @@ -849,7 +849,7 @@ enum { · 848 unmodified lines | ||
| 849 | 849 | static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan_spec *chan) |
| 850 | 850 | { |
| 851 | 851 | struct device *dev = &st->sd.spi->dev; |
| 852 | − struct ad7124_channel *ch = &st->channels[chan->channel]; | |
| 852 | + struct ad7124_channel *ch = &st->channels[chan->address]; | |
| 853 | 853 | int ret; |
| 854 | 854 | |
| 855 | 855 | if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) { |
| @@ -865,8 +865,8 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan · 9 unmodified lines | ||
| 865 | 865 | if (ret < 0) |
| 866 | 866 | return ret; |
| 867 | 867 | |
| 868 | − dev_dbg(dev, "offset for channel %d after zero-scale calibration: 0x%x\n", | |
| 869 | − chan->channel, ch->cfg.calibration_offset); | |
| 868 | + dev_dbg(dev, "offset for channel %lu after zero-scale calibration: 0x%x\n", | |
| 869 | + chan->address, ch->cfg.calibration_offset); | |
| 870 | 870 | } else { |
| 871 | 871 | ch->cfg.calibration_gain = st->gain_default; |
| 872 | 872 | |
| @@ -880,8 +880,8 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan · 7 unmodified lines | ||
| 880 | 880 | if (ret < 0) |
| 881 | 881 | return ret; |
| 882 | 882 | |
| 883 | − dev_dbg(dev, "gain for channel %d after full-scale calibration: 0x%x\n", | |
| 884 | − chan->channel, ch->cfg.calibration_gain); | |
| 883 | + dev_dbg(dev, "gain for channel %lu after full-scale calibration: 0x%x\n", | |
| 884 | + chan->address, ch->cfg.calibration_gain); | |
| 885 | 885 | } |
| 886 | 886 | |
| 887 | 887 | return 0; |
| @@ -924,7 +924,7 @@ static int ad7124_set_syscalib_mode(struct iio_dev *indio_dev, · 36 unmodified lines | ||
| 924 | 924 | { |
| 925 | 925 | struct ad7124_state *st = iio_priv(indio_dev); |
| 926 | 926 | |
| 927 | − st->channels[chan->channel].syscalib_mode = mode; | |
| 927 | + st->channels[chan->address].syscalib_mode = mode; | |
| 928 | 928 | |
| 929 | 929 | return 0; |
| 930 | 930 | } |
| @@ -934,7 +934,7 @@ static int ad7124_get_syscalib_mode(struct iio_dev *indio_dev, · 3 unmodified lines | ||
| 934 | 934 | { |
| 935 | 935 | struct ad7124_state *st = iio_priv(indio_dev); |
| 936 | 936 | |
| 937 | − return st->channels[chan->channel].syscalib_mode; | |
| 937 | + return st->channels[chan->address].syscalib_mode; | |
| 938 | 938 | } |
| 939 | 939 | |
| 940 | 940 | static const struct iio_enum ad7124_syscalib_mode_enum = { |
| @@ -200,7 +200,7 @@ struct ad7173_channel_config { · 199 unmodified lines | ||
| 200 | 200 | /* |
| 201 | 201 | * Following fields are used to compare equality. If you |
| 202 | 202 | * make adaptations in it, you most likely also have to adapt |
| 203 | − * ad7173_find_live_config(), too. | |
| 203 | + * ad7173_is_setup_equal(), too. | |
| 204 | 204 | */ |
| 205 | 205 | struct_group(config_props, |
| 206 | 206 | bool bipolar; |
| @@ -561,12 +561,19 @@ static void ad7173_reset_usage_cnts(struct ad7173_state *st) · 354 unmodified lines | ||
| 561 | 561 | st->config_usage_counter = 0; |
| 562 | 562 | } |
| 563 | 563 | |
| 564 | −static struct ad7173_channel_config * | |
| 565 | −ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg) | |
| 564 | +/** | |
| 565 | + * ad7173_is_setup_equal - Compare two channel setups | |
| 566 | + * @cfg1: First channel configuration | |
| 567 | + * @cfg2: Second channel configuration | |
| 568 | + * | |
| 569 | + * Compares all configuration options that affect the registers connected to | |
| 570 | + * SETUP_SEL, namely CONFIGx, FILTERx, GAINx and OFFSETx. | |
| 571 | + * | |
| 572 | + * Returns: true if the setups are identical, false otherwise | |
| 573 | + */ | |
| 574 | +static bool ad7173_is_setup_equal(const struct ad7173_channel_config *cfg1, | |
| 575 | + const struct ad7173_channel_config *cfg2) | |
| 566 | 576 | { |
| 567 | − struct ad7173_channel_config *cfg_aux; | |
| 568 | − int i; | |
| 569 | − | |
| 570 | 577 | /* |
| 571 | 578 | * This is just to make sure that the comparison is adapted after |
| 572 | 579 | * struct ad7173_channel_config was changed. |
| @@ -579,14 +586,22 @@ ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *c · 6 unmodified lines | ||
| 579 | 586 | u8 ref_sel; |
| 580 | 587 | })); |
| 581 | 588 | |
| 589 | + return cfg1->bipolar == cfg2->bipolar && | |
| 590 | + cfg1->input_buf == cfg2->input_buf && | |
| 591 | + cfg1->odr == cfg2->odr && | |
| 592 | + cfg1->ref_sel == cfg2->ref_sel; | |
| 593 | +} | |
| 594 | + | |
| 595 | +static struct ad7173_channel_config * | |
| 596 | +ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg) | |
| 597 | +{ | |
| 598 | + struct ad7173_channel_config *cfg_aux; | |
| 599 | + int i; | |
| 600 | + | |
| 582 | 601 | for (i = 0; i < st->num_channels; i++) { |
| 583 | 602 | cfg_aux = &st->channels[i].cfg; |
| 584 | 603 | |
| 585 | − if (cfg_aux->live && | |
| 586 | − cfg->bipolar == cfg_aux->bipolar && | |
| 587 | − cfg->input_buf == cfg_aux->input_buf && | |
| 588 | − cfg->odr == cfg_aux->odr && | |
| 589 | − cfg->ref_sel == cfg_aux->ref_sel) | |
| 604 | + if (cfg_aux->live && ad7173_is_setup_equal(cfg, cfg_aux)) | |
| 590 | 605 | return cfg_aux; |
| 591 | 606 | } |
| 592 | 607 | return NULL; |
| @@ -1228,7 +1243,7 @@ static int ad7173_update_scan_mode(struct iio_dev *indio_dev, · 635 unmodified lines | ||
| 1228 | 1243 | const unsigned long *scan_mask) |
| 1229 | 1244 | { |
| 1230 | 1245 | struct ad7173_state *st = iio_priv(indio_dev); |
| 1231 | − int i, ret; | |
| 1246 | + int i, j, k, ret; | |
| 1232 | 1247 | |
| 1233 | 1248 | for (i = 0; i < indio_dev->num_channels; i++) { |
| 1234 | 1249 | if (test_bit(i, scan_mask)) |
| @@ -1239,6 +1254,54 @@ static int ad7173_update_scan_mode(struct iio_dev *indio_dev, · 4 unmodified lines | ||
| 1239 | 1254 | return ret; |
| 1240 | 1255 | } |
| 1241 | 1256 | |
| 1257 | + /* | |
| 1258 | + * On some chips, there are more channels that setups, so if there were | |
| 1259 | + * more unique setups requested than the number of available slots, | |
| 1260 | + * ad7173_set_channel() will have written over some of the slots. We | |
| 1261 | + * can detect this by making sure each assigned cfg_slot matches the | |
| 1262 | + * requested configuration. If it doesn't, we know that the slot was | |
| 1263 | + * overwritten by a different channel. | |
| 1264 | + */ | |
| 1265 | + for_each_set_bit(i, scan_mask, indio_dev->num_channels) { | |
| 1266 | + const struct ad7173_channel_config *cfg1, *cfg2; | |
| 1267 | + | |
| 1268 | + cfg1 = &st->channels[i].cfg; | |
| 1269 | + | |
| 1270 | + for_each_set_bit(j, scan_mask, indio_dev->num_channels) { | |
| 1271 | + cfg2 = &st->channels[j].cfg; | |
| 1272 | + | |
| 1273 | + /* | |
| 1274 | + * Only compare configs that are assigned to the same | |
| 1275 | + * SETUP_SEL slot and don't compare channel to itself. | |
| 1276 | + */ | |
| 1277 | + if (i == j || cfg1->cfg_slot != cfg2->cfg_slot) | |
| 1278 | + continue; | |
| 1279 | + | |
| 1280 | + /* | |
| 1281 | + * If we find two different configs trying to use the | |
| 1282 | + * same SETUP_SEL slot, then we know that the that we | |
| 1283 | + * have too many unique configurations requested for | |
| 1284 | + * the available slots and at least one was overwritten. | |
| 1285 | + */ | |
| 1286 | + if (!ad7173_is_setup_equal(cfg1, cfg2)) { | |
| 1287 | + /* | |
| 1288 | + * At this point, there isn't a way to tell | |
| 1289 | + * which setups are actually programmed in the | |
| 1290 | + * ADC anymore, so we could read them back to | |
| 1291 | + * see, but it is simpler to just turn off all | |
| 1292 | + * of the live flags so that everything gets | |
| 1293 | + * reprogramed on the next attempt read a sample. | |
| 1294 | + */ | |
| 1295 | + for (k = 0; k < st->num_channels; k++) | |
| 1296 | + st->channels[k].cfg.live = false; | |
| 1297 | + | |
| 1298 | + dev_err(&st->sd.spi->dev, | |
| 1299 | + "Too many unique channel configurations requested for scan\n"); | |
| 1300 | + return -EINVAL; | |
| 1301 | + } | |
| 1302 | + } | |
| 1303 | + } | |
| 1304 | + | |
| 1242 | 1305 | return 0; |
| 1243 | 1306 | } |
| 1244 | 1307 | |
| @@ -873,6 +873,7 @@ static const struct ad7380_chip_info adaq4381_4_chip_info = { · 872 unmodified lines | ||
| 873 | 873 | .has_hardware_gain = true, |
| 874 | 874 | .available_scan_masks = ad7380_4_channel_scan_masks, |
| 875 | 875 | .timing_specs = &ad7380_4_timing, |
| 876 | + .max_conversion_rate_hz = 4 * MEGA, | |
| 876 | 877 | }; |
| 877 | 878 | |
| 878 | 879 | static const struct spi_offload_config ad7380_offload_config = { |
| @@ -89,7 +89,6 @@ struct rzg2l_adc { · 88 unmodified lines | ||
| 89 | 89 | struct completion completion; |
| 90 | 90 | struct mutex lock; |
| 91 | 91 | u16 last_val[RZG2L_ADC_MAX_CHANNELS]; |
| 92 | − bool was_rpm_active; | |
| 93 | 92 | }; |
| 94 | 93 | |
| 95 | 94 | /** |
| @@ -428,6 +427,8 @@ static int rzg2l_adc_probe(struct platform_device *pdev) · 332 unmodified lines | ||
| 428 | 427 | if (!indio_dev) |
| 429 | 428 | return -ENOMEM; |
| 430 | 429 | |
| 430 | + platform_set_drvdata(pdev, indio_dev); | |
| 431 | + | |
| 431 | 432 | adc = iio_priv(indio_dev); |
| 432 | 433 | |
| 433 | 434 | adc->hw_params = device_get_match_data(dev); |
| @@ -460,8 +461,6 @@ static int rzg2l_adc_probe(struct platform_device *pdev) · 26 unmodified lines | ||
| 460 | 461 | if (ret) |
| 461 | 462 | return ret; |
| 462 | 463 | |
| 463 | − platform_set_drvdata(pdev, indio_dev); | |
| 464 | − | |
| 465 | 464 | ret = rzg2l_adc_hw_init(dev, adc); |
| 466 | 465 | if (ret) |
| 467 | 466 | return dev_err_probe(&pdev->dev, ret, |
| @@ -541,14 +540,9 @@ static int rzg2l_adc_suspend(struct device *dev) · 73 unmodified lines | ||
| 541 | 540 | }; |
| 542 | 541 | int ret; |
| 543 | 542 | |
| 544 | − if (pm_runtime_suspended(dev)) { | |
| 545 | − adc->was_rpm_active = false; | |
| 546 | − } else { | |
| 547 | − ret = pm_runtime_force_suspend(dev); | |
| 548 | − if (ret) | |
| 549 | − return ret; | |
| 550 | − adc->was_rpm_active = true; | |
| 551 | − } | |
| 543 | + ret = pm_runtime_force_suspend(dev); | |
| 544 | + if (ret) | |
| 545 | + return ret; | |
| 552 | 546 | |
| 553 | 547 | ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets); |
| 554 | 548 | if (ret) |
| @@ -557,9 +551,7 @@ static int rzg2l_adc_suspend(struct device *dev) · 2 unmodified lines | ||
| 557 | 551 | return 0; |
| 558 | 552 | |
| 559 | 553 | rpm_restore: |
| 560 | − if (adc->was_rpm_active) | |
| 561 | − pm_runtime_force_resume(dev); | |
| 562 | − | |
| 554 | + pm_runtime_force_resume(dev); | |
| 563 | 555 | return ret; |
| 564 | 556 | } |
| 565 | 557 | |
| @@ -577,11 +569,9 @@ static int rzg2l_adc_resume(struct device *dev) · 11 unmodified lines | ||
| 577 | 569 | if (ret) |
| 578 | 570 | return ret; |
| 579 | 571 | |
| 580 | − if (adc->was_rpm_active) { | |
| 581 | − ret = pm_runtime_force_resume(dev); | |
| 582 | − if (ret) | |
| 583 | − goto resets_restore; | |
| 584 | − } | |
| 572 | + ret = pm_runtime_force_resume(dev); | |
| 573 | + if (ret) | |
| 574 | + goto resets_restore; | |
| 585 | 575 | |
| 586 | 576 | ret = rzg2l_adc_hw_init(dev, adc); |
| 587 | 577 | if (ret) |
| @@ -590,10 +580,7 @@ static int rzg2l_adc_resume(struct device *dev) · 2 unmodified lines | ||
| 590 | 580 | return 0; |
| 591 | 581 | |
| 592 | 582 | rpm_restore: |
| 593 | − if (adc->was_rpm_active) { | |
| 594 | − pm_runtime_mark_last_busy(dev); | |
| 595 | − pm_runtime_put_autosuspend(dev); | |
| 596 | − } | |
| 583 | + pm_runtime_force_suspend(dev); | |
| 597 | 584 | resets_restore: |
| 598 | 585 | reset_control_bulk_assert(ARRAY_SIZE(resets), resets); |
| 599 | 586 | return ret; |
| @@ -32,8 +32,12 @@ static int inv_icm42600_temp_read(struct inv_icm42600_state *st, s16 *temp) · 31 unmodified lines | ||
| 32 | 32 | goto exit; |
| 33 | 33 | |
| 34 | 34 | *temp = (s16)be16_to_cpup(raw); |
| 35 | + /* | |
| 36 | + * Temperature data is invalid if both accel and gyro are off. | |
| 37 | + * Return -EBUSY in this case. | |
| 38 | + */ | |
| 35 | 39 | if (*temp == INV_ICM42600_DATA_INVALID) |
| 36 | − ret = -EINVAL; | |
| 40 | + ret = -EBUSY; | |
| 37 | 41 | |
| 38 | 42 | exit: |
| 39 | 43 | mutex_unlock(&st->lock); |
| @@ -639,7 +639,7 @@ static irqreturn_t as73211_trigger_handler(int irq __always_unused, void *p) · 638 unmodified lines | ||
| 639 | 639 | struct { |
| 640 | 640 | __le16 chan[4]; |
| 641 | 641 | aligned_s64 ts; |
| 642 | − } scan; | |
| 642 | + } scan = { }; | |
| 643 | 643 | int data_result, ret; |
| 644 | 644 | |
| 645 | 645 | mutex_lock(&data->mutex); |
| @@ -3213,11 +3213,12 @@ int bmp280_common_probe(struct device *dev, · 3212 unmodified lines | ||
| 3213 | 3213 | |
| 3214 | 3214 | /* Bring chip out of reset if there is an assigned GPIO line */ |
| 3215 | 3215 | gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); |
| 3216 | + if (IS_ERR(gpiod)) | |
| 3217 | + return dev_err_probe(dev, PTR_ERR(gpiod), "failed to get reset GPIO\n"); | |
| 3218 | + | |
| 3216 | 3219 | /* Deassert the signal */ |
| 3217 | − if (gpiod) { | |
| 3218 | − dev_info(dev, "release reset\n"); | |
| 3219 | − gpiod_set_value(gpiod, 0); | |
| 3220 | − } | |
| 3220 | + dev_info(dev, "release reset\n"); | |
| 3221 | + gpiod_set_value(gpiod, 0); | |
| 3221 | 3222 | |
| 3222 | 3223 | data->regmap = regmap; |
| 3223 | 3224 | |
| @@ -938,12 +938,18 @@ static irqreturn_t isl29501_trigger_handler(int irq, void *p) · 937 unmodified lines | ||
| 938 | 938 | struct iio_dev *indio_dev = pf->indio_dev; |
| 939 | 939 | struct isl29501_private *isl29501 = iio_priv(indio_dev); |
| 940 | 940 | const unsigned long *active_mask = indio_dev->active_scan_mask; |
| 941 | − u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */ | |
| 942 | − | |
| 943 | − if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) | |
| 944 | − isl29501_register_read(isl29501, REG_DISTANCE, buffer); | |
| 941 | + u32 value; | |
| 942 | + struct { | |
| 943 | + u16 data; | |
| 944 | + aligned_s64 ts; | |
| 945 | + } scan = { }; | |
| 946 | + | |
| 947 | + if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) { | |
| 948 | + isl29501_register_read(isl29501, REG_DISTANCE, &value); | |
| 949 | + scan.data = value; | |
| 950 | + } | |
| 945 | 951 | |
| 946 | − iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp); | |
| 952 | + iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); | |
| 947 | 953 | iio_trigger_notify_done(indio_dev->trig); |
| 948 | 954 | |
| 949 | 955 | return IRQ_HANDLED; |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/module.h> |
| 12 | 12 | #include <linux/err.h> |
| 13 | 13 | #include <linux/spi/spi.h> |
| 14 | +#include <linux/types.h> | |
| 14 | 15 | #include <linux/iio/iio.h> |
| 15 | 16 | #include <linux/iio/sysfs.h> |
| 16 | 17 | #include <linux/iio/trigger.h> |
| @@ -121,8 +122,15 @@ struct maxim_thermocouple_data { · 104 unmodified lines | ||
| 121 | 122 | struct spi_device *spi; |
| 122 | 123 | const struct maxim_thermocouple_chip *chip; |
| 123 | 124 | char tc_type; |
| 124 | − | |
| 125 | − u8 buffer[16] __aligned(IIO_DMA_MINALIGN); | |
| 125 | + /* Buffer for reading up to 2 hardware channels. */ | |
| 126 | + struct { | |
| 127 | + union { | |
| 128 | + __be16 raw16; | |
| 129 | + __be32 raw32; | |
| 130 | + __be16 raw[2]; | |
| 131 | + }; | |
| 132 | + aligned_s64 timestamp; | |
| 133 | + } buffer __aligned(IIO_DMA_MINALIGN); | |
| 126 | 134 | }; |
| 127 | 135 | |
| 128 | 136 | static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, |
| @@ -130,18 +138,16 @@ static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, · 1 unmodified line | ||
| 130 | 138 | { |
| 131 | 139 | unsigned int storage_bytes = data->chip->read_size; |
| 132 | 140 | unsigned int shift = chan->scan_type.shift + (chan->address * 8); |
| 133 | − __be16 buf16; | |
| 134 | − __be32 buf32; | |
| 135 | 141 | int ret; |
| 136 | 142 | |
| 137 | 143 | switch (storage_bytes) { |
| 138 | 144 | case 2: |
| 139 | − ret = spi_read(data->spi, (void *)&buf16, storage_bytes); | |
| 140 | − *val = be16_to_cpu(buf16); | |
| 145 | + ret = spi_read(data->spi, &data->buffer.raw16, storage_bytes); | |
| 146 | + *val = be16_to_cpu(data->buffer.raw16); | |
| 141 | 147 | break; |
| 142 | 148 | case 4: |
| 143 | − ret = spi_read(data->spi, (void *)&buf32, storage_bytes); | |
| 144 | − *val = be32_to_cpu(buf32); | |
| 149 | + ret = spi_read(data->spi, &data->buffer.raw32, storage_bytes); | |
| 150 | + *val = be32_to_cpu(data->buffer.raw32); | |
| 145 | 151 | break; |
| 146 | 152 | default: |
| 147 | 153 | ret = -EINVAL; |
| @@ -166,9 +172,9 @@ static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private) · 18 unmodified lines | ||
| 166 | 172 | struct maxim_thermocouple_data *data = iio_priv(indio_dev); |
| 167 | 173 | int ret; |
| 168 | 174 | |
| 169 | − ret = spi_read(data->spi, data->buffer, data->chip->read_size); | |
| 175 | + ret = spi_read(data->spi, data->buffer.raw, data->chip->read_size); | |
| 170 | 176 | if (!ret) { |
| 171 | − iio_push_to_buffers_with_ts(indio_dev, data->buffer, | |
| 177 | + iio_push_to_buffers_with_ts(indio_dev, &data->buffer, | |
| 172 | 178 | sizeof(data->buffer), |
| 173 | 179 | iio_get_time_ns(indio_dev)); |
| 174 | 180 | } |
| @@ -115,7 +115,7 @@ static int ib_init_umem_odp(struct ib_umem_odp *umem_odp, · 114 unmodified lines | ||
| 115 | 115 | |
| 116 | 116 | out_free_map: |
| 117 | 117 | if (ib_uses_virt_dma(dev)) |
| 118 | − kfree(map->pfn_list); | |
| 118 | + kvfree(map->pfn_list); | |
| 119 | 119 | else |
| 120 | 120 | hmm_dma_map_free(dev->dma_device, map); |
| 121 | 121 | return ret; |
| @@ -287,7 +287,7 @@ static void ib_umem_odp_free(struct ib_umem_odp *umem_odp) · 165 unmodified lines | ||
| 287 | 287 | mutex_unlock(&umem_odp->umem_mutex); |
| 288 | 288 | mmu_interval_notifier_remove(&umem_odp->notifier); |
| 289 | 289 | if (ib_uses_virt_dma(dev)) |
| 290 | − kfree(umem_odp->map.pfn_list); | |
| 290 | + kvfree(umem_odp->map.pfn_list); | |
| 291 | 291 | else |
| 292 | 292 | hmm_dma_map_free(dev->dma_device, &umem_odp->map); |
| 293 | 293 | } |
| @@ -1921,7 +1921,6 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr, · 1920 unmodified lines | ||
| 1921 | 1921 | struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq, |
| 1922 | 1922 | ib_srq); |
| 1923 | 1923 | struct bnxt_re_dev *rdev = srq->rdev; |
| 1924 | − int rc; | |
| 1925 | 1924 | |
| 1926 | 1925 | switch (srq_attr_mask) { |
| 1927 | 1926 | case IB_SRQ_MAX_WR: |
| @@ -1933,11 +1932,8 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr, · 5 unmodified lines | ||
| 1933 | 1932 | return -EINVAL; |
| 1934 | 1933 | |
| 1935 | 1934 | srq->qplib_srq.threshold = srq_attr->srq_limit; |
| 1936 | − rc = bnxt_qplib_modify_srq(&rdev->qplib_res, &srq->qplib_srq); | |
| 1937 | − if (rc) { | |
| 1938 | − ibdev_err(&rdev->ibdev, "Modify HW SRQ failed!"); | |
| 1939 | − return rc; | |
| 1940 | − } | |
| 1935 | + bnxt_qplib_srq_arm_db(&srq->qplib_srq.dbinfo, srq->qplib_srq.threshold); | |
| 1936 | + | |
| 1941 | 1937 | /* On success, update the shadow */ |
| 1942 | 1938 | srq->srq_limit = srq_attr->srq_limit; |
| 1943 | 1939 | /* No need to Build and send response back to udata */ |
| @@ -2017,6 +2017,28 @@ static void bnxt_re_free_nqr_mem(struct bnxt_re_dev *rdev) · 2016 unmodified lines | ||
| 2017 | 2017 | rdev->nqr = NULL; |
| 2018 | 2018 | } |
| 2019 | 2019 | |
| 2020 | +/* When DEL_GID fails, driver is not freeing GID ctx memory. | |
| 2021 | + * To avoid the memory leak, free the memory during unload | |
| 2022 | + */ | |
| 2023 | +static void bnxt_re_free_gid_ctx(struct bnxt_re_dev *rdev) | |
| 2024 | +{ | |
| 2025 | + struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl; | |
| 2026 | + struct bnxt_re_gid_ctx *ctx, **ctx_tbl; | |
| 2027 | + int i; | |
| 2028 | + | |
| 2029 | + if (!sgid_tbl->active) | |
| 2030 | + return; | |
| 2031 | + | |
| 2032 | + ctx_tbl = sgid_tbl->ctx; | |
| 2033 | + for (i = 0; i < sgid_tbl->max; i++) { | |
| 2034 | + if (sgid_tbl->hw_id[i] == 0xFFFF) | |
| 2035 | + continue; | |
| 2036 | + | |
| 2037 | + ctx = ctx_tbl[i]; | |
| 2038 | + kfree(ctx); | |
| 2039 | + } | |
| 2040 | +} | |
| 2041 | + | |
| 2020 | 2042 | static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type) |
| 2021 | 2043 | { |
| 2022 | 2044 | u8 type; |
| @@ -2030,6 +2052,7 @@ static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type) · 7 unmodified lines | ||
| 2030 | 2052 | if (test_and_clear_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags)) |
| 2031 | 2053 | cancel_delayed_work_sync(&rdev->worker); |
| 2032 | 2054 | |
| 2055 | + bnxt_re_free_gid_ctx(rdev); | |
| 2033 | 2056 | if (test_and_clear_bit(BNXT_RE_FLAG_RESOURCES_INITIALIZED, |
| 2034 | 2057 | &rdev->flags)) |
| 2035 | 2058 | bnxt_re_cleanup_res(rdev); |
| @@ -705,9 +705,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, · 704 unmodified lines | ||
| 705 | 705 | srq->dbinfo.db = srq->dpi->dbr; |
| 706 | 706 | srq->dbinfo.max_slot = 1; |
| 707 | 707 | srq->dbinfo.priv_db = res->dpi_tbl.priv_db; |
| 708 | − if (srq->threshold) | |
| 709 | − bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); | |
| 710 | − srq->arm_req = false; | |
| 708 | + bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); | |
| 711 | 709 | |
| 712 | 710 | return 0; |
| 713 | 711 | fail: |
| @@ -717,24 +715,6 @@ fail: · 3 unmodified lines | ||
| 717 | 715 | return rc; |
| 718 | 716 | } |
| 719 | 717 | |
| 720 | −int bnxt_qplib_modify_srq(struct bnxt_qplib_res *res, | |
| 721 | − struct bnxt_qplib_srq *srq) | |
| 722 | −{ | |
| 723 | − struct bnxt_qplib_hwq *srq_hwq = &srq->hwq; | |
| 724 | − u32 count; | |
| 725 | − | |
| 726 | − count = __bnxt_qplib_get_avail(srq_hwq); | |
| 727 | − if (count > srq->threshold) { | |
| 728 | − srq->arm_req = false; | |
| 729 | − bnxt_qplib_srq_arm_db(&srq->dbinfo, srq->threshold); | |
| 730 | − } else { | |
| 731 | − /* Deferred arming */ | |
| 732 | − srq->arm_req = true; | |
| 733 | − } | |
| 734 | − | |
| 735 | − return 0; | |
| 736 | −} | |
| 737 | − | |
| 738 | 718 | int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, |
| 739 | 719 | struct bnxt_qplib_srq *srq) |
| 740 | 720 | { |
| @@ -776,7 +756,6 @@ int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq, · 35 unmodified lines | ||
| 776 | 756 | struct bnxt_qplib_hwq *srq_hwq = &srq->hwq; |
| 777 | 757 | struct rq_wqe *srqe; |
| 778 | 758 | struct sq_sge *hw_sge; |
| 779 | − u32 count = 0; | |
| 780 | 759 | int i, next; |
| 781 | 760 | |
| 782 | 761 | spin_lock(&srq_hwq->lock); |
| @@ -808,15 +787,8 @@ int bnxt_qplib_post_srq_recv(struct bnxt_qplib_srq *srq, · 25 unmodified lines | ||
| 808 | 787 | |
| 809 | 788 | bnxt_qplib_hwq_incr_prod(&srq->dbinfo, srq_hwq, srq->dbinfo.max_slot); |
| 810 | 789 | |
| 811 | − spin_lock(&srq_hwq->lock); | |
| 812 | − count = __bnxt_qplib_get_avail(srq_hwq); | |
| 813 | − spin_unlock(&srq_hwq->lock); | |
| 814 | 790 | /* Ring DB */ |
| 815 | 791 | bnxt_qplib_ring_prod_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ); |
| 816 | − if (srq->arm_req == true && count > srq->threshold) { | |
| 817 | − srq->arm_req = false; | |
| 818 | − bnxt_qplib_srq_arm_db(&srq->dbinfo, srq->threshold); | |
| 819 | − } | |
| 820 | 792 | |
| 821 | 793 | return 0; |
| 822 | 794 | } |
| @@ -546,8 +546,6 @@ int bnxt_qplib_enable_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq, · 545 unmodified lines | ||
| 546 | 546 | srqn_handler_t srq_handler); |
| 547 | 547 | int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, |
| 548 | 548 | struct bnxt_qplib_srq *srq); |
| 549 | −int bnxt_qplib_modify_srq(struct bnxt_qplib_res *res, | |
| 550 | − struct bnxt_qplib_srq *srq); | |
| 551 | 549 | int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, |
| 552 | 550 | struct bnxt_qplib_srq *srq); |
| 553 | 551 | void bnxt_qplib_destroy_srq(struct bnxt_qplib_res *res, |
| @@ -121,6 +121,7 @@ static int __alloc_pbl(struct bnxt_qplib_res *res, · 120 unmodified lines | ||
| 121 | 121 | pbl->pg_arr = vmalloc_array(pages, sizeof(void *)); |
| 122 | 122 | if (!pbl->pg_arr) |
| 123 | 123 | return -ENOMEM; |
| 124 | + memset(pbl->pg_arr, 0, pages * sizeof(void *)); | |
| 124 | 125 | |
| 125 | 126 | pbl->pg_map_arr = vmalloc_array(pages, sizeof(dma_addr_t)); |
| 126 | 127 | if (!pbl->pg_map_arr) { |
| @@ -128,6 +129,7 @@ static int __alloc_pbl(struct bnxt_qplib_res *res, · 1 unmodified line | ||
| 128 | 129 | pbl->pg_arr = NULL; |
| 129 | 130 | return -ENOMEM; |
| 130 | 131 | } |
| 132 | + memset(pbl->pg_map_arr, 0, pages * sizeof(dma_addr_t)); | |
| 131 | 133 | pbl->pg_count = 0; |
| 132 | 134 | pbl->pg_size = sginfo->pgsize; |
| 133 | 135 | |
| @@ -994,6 +994,8 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, · 993 unmodified lines | ||
| 994 | 994 | old_entry = xa_store(&dev->qp_xa, 1, qp, GFP_KERNEL); |
| 995 | 995 | if (xa_is_err(old_entry)) |
| 996 | 996 | ret = xa_err(old_entry); |
| 997 | + else | |
| 998 | + qp->ibqp.qp_num = 1; | |
| 997 | 999 | } else { |
| 998 | 1000 | ret = xa_alloc_cyclic(&dev->qp_xa, &qp->ibqp.qp_num, qp, |
| 999 | 1001 | XA_LIMIT(1, dev->attrs.max_qp - 1), |
| @@ -1031,7 +1033,9 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, · 31 unmodified lines | ||
| 1031 | 1033 | if (ret) |
| 1032 | 1034 | goto err_out_cmd; |
| 1033 | 1035 | } else { |
| 1034 | − init_kernel_qp(dev, qp, attrs); | |
| 1036 | + ret = init_kernel_qp(dev, qp, attrs); | |
| 1037 | + if (ret) | |
| 1038 | + goto err_out_xa; | |
| 1035 | 1039 | } |
| 1036 | 1040 | |
| 1037 | 1041 | qp->attrs.max_send_sge = attrs->cap.max_send_sge; |
| @@ -3043,7 +3043,7 @@ static void hns_roce_v2_exit(struct hns_roce_dev *hr_dev) · 3042 unmodified lines | ||
| 3043 | 3043 | if (!hr_dev->is_vf) |
| 3044 | 3044 | hns_roce_free_link_table(hr_dev); |
| 3045 | 3045 | |
| 3046 | − if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP09) | |
| 3046 | + if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) | |
| 3047 | 3047 | free_dip_entry(hr_dev); |
| 3048 | 3048 | } |
| 3049 | 3049 | |
| @@ -5476,7 +5476,7 @@ out: · 2426 unmodified lines | ||
| 5476 | 5476 | return ret; |
| 5477 | 5477 | } |
| 5478 | 5478 | |
| 5479 | −static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 qpn, | |
| 5479 | +static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 sccn, | |
| 5480 | 5480 | void *buffer) |
| 5481 | 5481 | { |
| 5482 | 5482 | struct hns_roce_v2_scc_context *context; |
| @@ -5488,7 +5488,7 @@ static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 qpn, · 5 unmodified lines | ||
| 5488 | 5488 | return PTR_ERR(mailbox); |
| 5489 | 5489 | |
| 5490 | 5490 | ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, HNS_ROCE_CMD_QUERY_SCCC, |
| 5491 | − qpn); | |
| 5491 | + sccn); | |
| 5492 | 5492 | if (ret) |
| 5493 | 5493 | goto out; |
| 5494 | 5494 | |
| @@ -100,6 +100,7 @@ int hns_roce_fill_res_qp_entry_raw(struct sk_buff *msg, struct ib_qp *ib_qp) · 99 unmodified lines | ||
| 100 | 100 | struct hns_roce_v2_qp_context qpc; |
| 101 | 101 | struct hns_roce_v2_scc_context sccc; |
| 102 | 102 | } context = {}; |
| 103 | + u32 sccn = hr_qp->qpn; | |
| 103 | 104 | int ret; |
| 104 | 105 | |
| 105 | 106 | if (!hr_dev->hw->query_qpc) |
| @@ -116,7 +117,13 @@ int hns_roce_fill_res_qp_entry_raw(struct sk_buff *msg, struct ib_qp *ib_qp) · 10 unmodified lines | ||
| 116 | 117 | !hr_dev->hw->query_sccc) |
| 117 | 118 | goto out; |
| 118 | 119 | |
| 119 | − ret = hr_dev->hw->query_sccc(hr_dev, hr_qp->qpn, &context.sccc); | |
| 120 | + if (hr_qp->cong_type == CONG_TYPE_DIP) { | |
| 121 | + if (!hr_qp->dip) | |
| 122 | + goto out; | |
| 123 | + sccn = hr_qp->dip->dip_idx; | |
| 124 | + } | |
| 125 | + | |
| 126 | + ret = hr_dev->hw->query_sccc(hr_dev, sccn, &context.sccc); | |
| 120 | 127 | if (ret) |
| 121 | 128 | ibdev_warn_ratelimited(&hr_dev->ib_dev, |
| 122 | 129 | "failed to query SCCC, ret = %d.\n", |
| @@ -345,33 +345,15 @@ int rxe_prepare(struct rxe_av *av, struct rxe_pkt_info *pkt, · 344 unmodified lines | ||
| 345 | 345 | |
| 346 | 346 | static void rxe_skb_tx_dtor(struct sk_buff *skb) |
| 347 | 347 | { |
| 348 | − struct net_device *ndev = skb->dev; | |
| 349 | − struct rxe_dev *rxe; | |
| 350 | − unsigned int qp_index; | |
| 351 | − struct rxe_qp *qp; | |
| 348 | + struct rxe_qp *qp = skb->sk->sk_user_data; | |
| 352 | 349 | int skb_out; |
| 353 | 350 | |
| 354 | − rxe = rxe_get_dev_from_net(ndev); | |
| 355 | − if (!rxe && is_vlan_dev(ndev)) | |
| 356 | − rxe = rxe_get_dev_from_net(vlan_dev_real_dev(ndev)); | |
| 357 | − if (WARN_ON(!rxe)) | |
| 358 | − return; | |
| 359 | − | |
| 360 | − qp_index = (int)(uintptr_t)skb->sk->sk_user_data; | |
| 361 | − if (!qp_index) | |
| 362 | − return; | |
| 363 | − | |
| 364 | − qp = rxe_pool_get_index(&rxe->qp_pool, qp_index); | |
| 365 | − if (!qp) | |
| 366 | − goto put_dev; | |
| 367 | − | |
| 368 | 351 | skb_out = atomic_dec_return(&qp->skb_out); |
| 369 | − if (qp->need_req_skb && skb_out < RXE_INFLIGHT_SKBS_PER_QP_LOW) | |
| 352 | + if (unlikely(qp->need_req_skb && | |
| 353 | + skb_out < RXE_INFLIGHT_SKBS_PER_QP_LOW)) | |
| 370 | 354 | rxe_sched_task(&qp->send_task); |
| 371 | 355 | |
| 372 | 356 | rxe_put(qp); |
| 373 | −put_dev: | |
| 374 | − ib_device_put(&rxe->ib_dev); | |
| 375 | 357 | sock_put(skb->sk); |
| 376 | 358 | } |
| 377 | 359 | |
| @@ -383,6 +365,7 @@ static int rxe_send(struct sk_buff *skb, struct rxe_pkt_info *pkt) · 5 unmodified lines | ||
| 383 | 365 | sock_hold(sk); |
| 384 | 366 | skb->sk = sk; |
| 385 | 367 | skb->destructor = rxe_skb_tx_dtor; |
| 368 | + rxe_get(pkt->qp); | |
| 386 | 369 | atomic_inc(&pkt->qp->skb_out); |
| 387 | 370 | |
| 388 | 371 | if (skb->protocol == htons(ETH_P_IP)) |
| @@ -405,6 +388,7 @@ static int rxe_loopback(struct sk_buff *skb, struct rxe_pkt_info *pkt) · 16 unmodified lines | ||
| 405 | 388 | sock_hold(sk); |
| 406 | 389 | skb->sk = sk; |
| 407 | 390 | skb->destructor = rxe_skb_tx_dtor; |
| 391 | + rxe_get(pkt->qp); | |
| 408 | 392 | atomic_inc(&pkt->qp->skb_out); |
| 409 | 393 | |
| 410 | 394 | if (skb->protocol == htons(ETH_P_IP)) |
| @@ -497,6 +481,9 @@ struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av, · 86 unmodified lines | ||
| 497 | 481 | goto out; |
| 498 | 482 | } |
| 499 | 483 | |
| 484 | + /* Add time stamp to skb. */ | |
| 485 | + skb->tstamp = ktime_get(); | |
| 486 | + | |
| 500 | 487 | skb_reserve(skb, hdr_len + LL_RESERVED_SPACE(ndev)); |
| 501 | 488 | |
| 502 | 489 | /* FIXME: hold reference to this netdev until life of this skb. */ |
| @@ -244,7 +244,7 @@ static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp, · 243 unmodified lines | ||
| 244 | 244 | err = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM, 0, &qp->sk); |
| 245 | 245 | if (err < 0) |
| 246 | 246 | return err; |
| 247 | − qp->sk->sk->sk_user_data = (void *)(uintptr_t)qp->elem.index; | |
| 247 | + qp->sk->sk->sk_user_data = qp; | |
| 248 | 248 | |
| 249 | 249 | /* pick a source UDP port number for this QP based on |
| 250 | 250 | * the source QPN. this spreads traffic for different QPs |
| @@ -3638,7 +3638,7 @@ static int __init parse_ivrs_acpihid(char *str) · 3637 unmodified lines | ||
| 3638 | 3638 | { |
| 3639 | 3639 | u32 seg = 0, bus, dev, fn; |
| 3640 | 3640 | char *hid, *uid, *p, *addr; |
| 3641 | − char acpiid[ACPIID_LEN] = {0}; | |
| 3641 | + char acpiid[ACPIID_LEN + 1] = { }; /* size with NULL terminator */ | |
| 3642 | 3642 | int i; |
| 3643 | 3643 | |
| 3644 | 3644 | addr = strchr(str, '@'); |
| @@ -3664,7 +3664,7 @@ static int __init parse_ivrs_acpihid(char *str) · 19 unmodified lines | ||
| 3664 | 3664 | /* We have the '@', make it the terminator to get just the acpiid */ |
| 3665 | 3665 | *addr++ = 0; |
| 3666 | 3666 | |
| 3667 | − if (strlen(str) > ACPIID_LEN + 1) | |
| 3667 | + if (strlen(str) > ACPIID_LEN) | |
| 3668 | 3668 | goto not_found; |
| 3669 | 3669 | |
| 3670 | 3670 | if (sscanf(str, "=%s", acpiid) != 1) |
| @@ -2997,9 +2997,9 @@ void arm_smmu_attach_commit(struct arm_smmu_attach_state *state) · 2996 unmodified lines | ||
| 2997 | 2997 | /* ATS is being switched off, invalidate the entire ATC */ |
| 2998 | 2998 | arm_smmu_atc_inv_master(master, IOMMU_NO_PASID); |
| 2999 | 2999 | } |
| 3000 | − master->ats_enabled = state->ats_enabled; | |
| 3001 | 3000 | |
| 3002 | 3001 | arm_smmu_remove_master_domain(master, state->old_domain, state->ssid); |
| 3002 | + master->ats_enabled = state->ats_enabled; | |
| 3003 | 3003 | } |
| 3004 | 3004 | |
| 3005 | 3005 | static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) |
| @@ -301,9 +301,11 @@ static void tegra241_vintf_user_handle_error(struct tegra241_vintf *vintf) · 300 unmodified lines | ||
| 301 | 301 | struct iommu_vevent_tegra241_cmdqv vevent_data; |
| 302 | 302 | int i; |
| 303 | 303 | |
| 304 | − for (i = 0; i < LVCMDQ_ERR_MAP_NUM_64; i++) | |
| 305 | − vevent_data.lvcmdq_err_map[i] = | |
| 306 | − readq_relaxed(REG_VINTF(vintf, LVCMDQ_ERR_MAP_64(i))); | |
| 304 | + for (i = 0; i < LVCMDQ_ERR_MAP_NUM_64; i++) { | |
| 305 | + u64 err = readq_relaxed(REG_VINTF(vintf, LVCMDQ_ERR_MAP_64(i))); | |
| 306 | + | |
| 307 | + vevent_data.lvcmdq_err_map[i] = cpu_to_le64(err); | |
| 308 | + } | |
| 307 | 309 | |
| 308 | 310 | iommufd_viommu_report_event(viommu, IOMMU_VEVENTQ_TYPE_TEGRA241_CMDQV, |
| 309 | 311 | &vevent_data, sizeof(vevent_data)); |
| @@ -339,7 +339,7 @@ iommufd_hw_queue_alloc_phys(struct iommu_hw_queue_alloc *cmd, · 338 unmodified lines | ||
| 339 | 339 | } |
| 340 | 340 | |
| 341 | 341 | *base_pa = (page_to_pfn(pages[0]) << PAGE_SHIFT) + offset; |
| 342 | − kfree(pages); | |
| 342 | + kvfree(pages); | |
| 343 | 343 | return access; |
| 344 | 344 | |
| 345 | 345 | out_unpin: |
| @@ -349,7 +349,7 @@ out_detach: · 3 unmodified lines | ||
| 349 | 349 | out_destroy: |
| 350 | 350 | iommufd_access_destroy_internal(viommu->ictx, access); |
| 351 | 351 | out_free: |
| 352 | − kfree(pages); | |
| 352 | + kvfree(pages); | |
| 353 | 353 | return ERR_PTR(rc); |
| 354 | 354 | } |
| 355 | 355 | |
| @@ -1283,7 +1283,7 @@ static phys_addr_t riscv_iommu_iova_to_phys(struct iommu_domain *iommu_domain, · 1282 unmodified lines | ||
| 1283 | 1283 | unsigned long *ptr; |
| 1284 | 1284 | |
| 1285 | 1285 | ptr = riscv_iommu_pte_fetch(domain, iova, &pte_size); |
| 1286 | − if (_io_pte_none(*ptr) || !_io_pte_present(*ptr)) | |
| 1286 | + if (!ptr) | |
| 1287 | 1287 | return 0; |
| 1288 | 1288 | |
| 1289 | 1289 | return pfn_to_phys(__page_val_to_pfn(*ptr)) | (iova & (pte_size - 1)); |
| @@ -998,8 +998,7 @@ static void viommu_get_resv_regions(struct device *dev, struct list_head *head) · 997 unmodified lines | ||
| 998 | 998 | iommu_dma_get_resv_regions(dev, head); |
| 999 | 999 | } |
| 1000 | 1000 | |
| 1001 | −static const struct iommu_ops viommu_ops; | |
| 1002 | −static struct virtio_driver virtio_iommu_drv; | |
| 1001 | +static const struct bus_type *virtio_bus_type; | |
| 1003 | 1002 | |
| 1004 | 1003 | static int viommu_match_node(struct device *dev, const void *data) |
| 1005 | 1004 | { |
| @@ -1008,8 +1007,9 @@ static int viommu_match_node(struct device *dev, const void *data) · 2 unmodified lines | ||
| 1008 | 1007 | |
| 1009 | 1008 | static struct viommu_dev *viommu_get_by_fwnode(struct fwnode_handle *fwnode) |
| 1010 | 1009 | { |
| 1011 | − struct device *dev = driver_find_device(&virtio_iommu_drv.driver, NULL, | |
| 1012 | − fwnode, viommu_match_node); | |
| 1010 | + struct device *dev = bus_find_device(virtio_bus_type, NULL, fwnode, | |
| 1011 | + viommu_match_node); | |
| 1012 | + | |
| 1013 | 1013 | put_device(dev); |
| 1014 | 1014 | |
| 1015 | 1015 | return dev ? dev_to_virtio(dev)->priv : NULL; |
| @@ -1160,6 +1160,9 @@ static int viommu_probe(struct virtio_device *vdev) · 144 unmodified lines | ||
| 1160 | 1160 | if (!viommu) |
| 1161 | 1161 | return -ENOMEM; |
| 1162 | 1162 | |
| 1163 | + /* Borrow this for easy lookups later */ | |
| 1164 | + virtio_bus_type = dev->bus; | |
| 1165 | + | |
| 1163 | 1166 | spin_lock_init(&viommu->request_lock); |
| 1164 | 1167 | ida_init(&viommu->domain_ids); |
| 1165 | 1168 | viommu->dev = dev; |
| @@ -1229,10 +1232,10 @@ static int viommu_probe(struct virtio_device *vdev) · 63 unmodified lines | ||
| 1229 | 1232 | if (ret) |
| 1230 | 1233 | goto err_free_vqs; |
| 1231 | 1234 | |
| 1232 | − iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev); | |
| 1233 | − | |
| 1234 | 1235 | vdev->priv = viommu; |
| 1235 | 1236 | |
| 1237 | + iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev); | |
| 1238 | + | |
| 1236 | 1239 | dev_info(dev, "input address: %u bits\n", |
| 1237 | 1240 | order_base_2(viommu->geometry.aperture_end)); |
| 1238 | 1241 | dev_info(dev, "page mask: %#llx\n", viommu->pgsize_bitmap); |
| @@ -39,12 +39,13 @@ · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | #include "hfc_pci.h" |
| 41 | 41 | |
| 42 | +static void hfcpci_softirq(struct timer_list *unused); | |
| 42 | 43 | static const char *hfcpci_revision = "2.0"; |
| 43 | 44 | |
| 44 | 45 | static int HFC_cnt; |
| 45 | 46 | static uint debug; |
| 46 | 47 | static uint poll, tics; |
| 47 | −static struct timer_list hfc_tl; | |
| 48 | +static DEFINE_TIMER(hfc_tl, hfcpci_softirq); | |
| 48 | 49 | static unsigned long hfc_jiffies; |
| 49 | 50 | |
| 50 | 51 | MODULE_AUTHOR("Karsten Keil"); |
| @@ -2305,8 +2306,7 @@ hfcpci_softirq(struct timer_list *unused) · 2254 unmodified lines | ||
| 2305 | 2306 | hfc_jiffies = jiffies + 1; |
| 2306 | 2307 | else |
| 2307 | 2308 | hfc_jiffies += tics; |
| 2308 | − hfc_tl.expires = hfc_jiffies; | |
| 2309 | − add_timer(&hfc_tl); | |
| 2309 | + mod_timer(&hfc_tl, hfc_jiffies); | |
| 2310 | 2310 | } |
| 2311 | 2311 | |
| 2312 | 2312 | static int __init |
| @@ -2332,10 +2332,8 @@ HFC_init(void) · 19 unmodified lines | ||
| 2332 | 2332 | if (poll != HFCPCI_BTRANS_THRESHOLD) { |
| 2333 | 2333 | printk(KERN_INFO "%s: Using alternative poll value of %d\n", |
| 2334 | 2334 | __func__, poll); |
| 2335 | − timer_setup(&hfc_tl, hfcpci_softirq, 0); | |
| 2336 | − hfc_tl.expires = jiffies + tics; | |
| 2337 | − hfc_jiffies = hfc_tl.expires; | |
| 2338 | − add_timer(&hfc_tl); | |
| 2335 | + hfc_jiffies = jiffies + tics; | |
| 2336 | + mod_timer(&hfc_tl, hfc_jiffies); | |
| 2339 | 2337 | } else |
| 2340 | 2338 | tics = 0; /* indicate the use of controller's timer */ |
| 2341 | 2339 | |
| @@ -339,6 +339,7 @@ static int start_readonly; · 338 unmodified lines | ||
| 339 | 339 | * so all the races disappear. |
| 340 | 340 | */ |
| 341 | 341 | static bool create_on_open = true; |
| 342 | +static bool legacy_async_del_gendisk = true; | |
| 342 | 343 | |
| 343 | 344 | /* |
| 344 | 345 | * We have a system wide 'event count' that is incremented |
| @@ -877,15 +878,18 @@ void mddev_unlock(struct mddev *mddev) · 532 unmodified lines | ||
| 877 | 878 | export_rdev(rdev, mddev); |
| 878 | 879 | } |
| 879 | 880 | |
| 880 | − /* Call del_gendisk after release reconfig_mutex to avoid | |
| 881 | − * deadlock (e.g. call del_gendisk under the lock and an | |
| 882 | − * access to sysfs files waits the lock) | |
| 883 | − * And MD_DELETED is only used for md raid which is set in | |
| 884 | − * do_md_stop. dm raid only uses md_stop to stop. So dm raid | |
| 885 | − * doesn't need to check MD_DELETED when getting reconfig lock | |
| 886 | − */ | |
| 887 | − if (test_bit(MD_DELETED, &mddev->flags)) | |
| 888 | − del_gendisk(mddev->gendisk); | |
| 881 | + if (!legacy_async_del_gendisk) { | |
| 882 | + /* | |
| 883 | + * Call del_gendisk after release reconfig_mutex to avoid | |
| 884 | + * deadlock (e.g. call del_gendisk under the lock and an | |
| 885 | + * access to sysfs files waits the lock) | |
| 886 | + * And MD_DELETED is only used for md raid which is set in | |
| 887 | + * do_md_stop. dm raid only uses md_stop to stop. So dm raid | |
| 888 | + * doesn't need to check MD_DELETED when getting reconfig lock | |
| 889 | + */ | |
| 890 | + if (test_bit(MD_DELETED, &mddev->flags)) | |
| 891 | + del_gendisk(mddev->gendisk); | |
| 892 | + } | |
| 889 | 893 | } |
| 890 | 894 | EXPORT_SYMBOL_GPL(mddev_unlock); |
| 891 | 895 | |
| @@ -1419,7 +1423,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *freshest, stru · 527 unmodified lines | ||
| 1419 | 1423 | else { |
| 1420 | 1424 | if (sb->events_hi == sb->cp_events_hi && |
| 1421 | 1425 | sb->events_lo == sb->cp_events_lo) { |
| 1422 | − mddev->resync_offset = sb->resync_offset; | |
| 1426 | + mddev->resync_offset = sb->recovery_cp; | |
| 1423 | 1427 | } else |
| 1424 | 1428 | mddev->resync_offset = 0; |
| 1425 | 1429 | } |
| @@ -1547,13 +1551,13 @@ static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev) · 121 unmodified lines | ||
| 1547 | 1551 | mddev->minor_version = sb->minor_version; |
| 1548 | 1552 | if (mddev->in_sync) |
| 1549 | 1553 | { |
| 1550 | − sb->resync_offset = mddev->resync_offset; | |
| 1554 | + sb->recovery_cp = mddev->resync_offset; | |
| 1551 | 1555 | sb->cp_events_hi = (mddev->events>>32); |
| 1552 | 1556 | sb->cp_events_lo = (u32)mddev->events; |
| 1553 | 1557 | if (mddev->resync_offset == MaxSector) |
| 1554 | 1558 | sb->state = (1<< MD_SB_CLEAN); |
| 1555 | 1559 | } else |
| 1556 | − sb->resync_offset = 0; | |
| 1560 | + sb->recovery_cp = 0; | |
| 1557 | 1561 | |
| 1558 | 1562 | sb->layout = mddev->layout; |
| 1559 | 1563 | sb->chunk_size = mddev->chunk_sectors << 9; |
| @@ -4835,9 +4839,42 @@ out_unlock: · 3275 unmodified lines | ||
| 4835 | 4839 | static struct md_sysfs_entry md_metadata = |
| 4836 | 4840 | __ATTR_PREALLOC(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store); |
| 4837 | 4841 | |
| 4842 | +static bool rdev_needs_recovery(struct md_rdev *rdev, sector_t sectors) | |
| 4843 | +{ | |
| 4844 | + return rdev->raid_disk >= 0 && | |
| 4845 | + !test_bit(Journal, &rdev->flags) && | |
| 4846 | + !test_bit(Faulty, &rdev->flags) && | |
| 4847 | + !test_bit(In_sync, &rdev->flags) && | |
| 4848 | + rdev->recovery_offset < sectors; | |
| 4849 | +} | |
| 4850 | + | |
| 4851 | +static enum sync_action md_get_active_sync_action(struct mddev *mddev) | |
| 4852 | +{ | |
| 4853 | + struct md_rdev *rdev; | |
| 4854 | + bool is_recover = false; | |
| 4855 | + | |
| 4856 | + if (mddev->resync_offset < MaxSector) | |
| 4857 | + return ACTION_RESYNC; | |
| 4858 | + | |
| 4859 | + if (mddev->reshape_position != MaxSector) | |
| 4860 | + return ACTION_RESHAPE; | |
| 4861 | + | |
| 4862 | + rcu_read_lock(); | |
| 4863 | + rdev_for_each_rcu(rdev, mddev) { | |
| 4864 | + if (rdev_needs_recovery(rdev, MaxSector)) { | |
| 4865 | + is_recover = true; | |
| 4866 | + break; | |
| 4867 | + } | |
| 4868 | + } | |
| 4869 | + rcu_read_unlock(); | |
| 4870 | + | |
| 4871 | + return is_recover ? ACTION_RECOVER : ACTION_IDLE; | |
| 4872 | +} | |
| 4873 | + | |
| 4838 | 4874 | enum sync_action md_sync_action(struct mddev *mddev) |
| 4839 | 4875 | { |
| 4840 | 4876 | unsigned long recovery = mddev->recovery; |
| 4877 | + enum sync_action active_action; | |
| 4841 | 4878 | |
| 4842 | 4879 | /* |
| 4843 | 4880 | * frozen has the highest priority, means running sync_thread will be |
| @@ -4861,8 +4898,17 @@ enum sync_action md_sync_action(struct mddev *mddev) · 17 unmodified lines | ||
| 4861 | 4898 | !test_bit(MD_RECOVERY_NEEDED, &recovery)) |
| 4862 | 4899 | return ACTION_IDLE; |
| 4863 | 4900 | |
| 4864 | − if (test_bit(MD_RECOVERY_RESHAPE, &recovery) || | |
| 4865 | − mddev->reshape_position != MaxSector) | |
| 4901 | + /* | |
| 4902 | + * Check if any sync operation (resync/recover/reshape) is | |
| 4903 | + * currently active. This ensures that only one sync operation | |
| 4904 | + * can run at a time. Returns the type of active operation, or | |
| 4905 | + * ACTION_IDLE if none are active. | |
| 4906 | + */ | |
| 4907 | + active_action = md_get_active_sync_action(mddev); | |
| 4908 | + if (active_action != ACTION_IDLE) | |
| 4909 | + return active_action; | |
| 4910 | + | |
| 4911 | + if (test_bit(MD_RECOVERY_RESHAPE, &recovery)) | |
| 4866 | 4912 | return ACTION_RESHAPE; |
| 4867 | 4913 | |
| 4868 | 4914 | if (test_bit(MD_RECOVERY_RECOVER, &recovery)) |
| @@ -5818,6 +5864,13 @@ static void md_kobj_release(struct kobject *ko) · 949 unmodified lines | ||
| 5818 | 5864 | { |
| 5819 | 5865 | struct mddev *mddev = container_of(ko, struct mddev, kobj); |
| 5820 | 5866 | |
| 5867 | + if (legacy_async_del_gendisk) { | |
| 5868 | + if (mddev->sysfs_state) | |
| 5869 | + sysfs_put(mddev->sysfs_state); | |
| 5870 | + if (mddev->sysfs_level) | |
| 5871 | + sysfs_put(mddev->sysfs_level); | |
| 5872 | + del_gendisk(mddev->gendisk); | |
| 5873 | + } | |
| 5821 | 5874 | put_disk(mddev->gendisk); |
| 5822 | 5875 | } |
| 5823 | 5876 | |
| @@ -6021,6 +6074,9 @@ static int md_alloc_and_put(dev_t dev, char *name) · 197 unmodified lines | ||
| 6021 | 6074 | { |
| 6022 | 6075 | struct mddev *mddev = md_alloc(dev, name); |
| 6023 | 6076 | |
| 6077 | + if (legacy_async_del_gendisk) | |
| 6078 | + pr_warn("md: async del_gendisk mode will be removed in future, please upgrade to mdadm-4.5+\n"); | |
| 6079 | + | |
| 6024 | 6080 | if (IS_ERR(mddev)) |
| 6025 | 6081 | return PTR_ERR(mddev); |
| 6026 | 6082 | mddev_put(mddev); |
| @@ -6431,10 +6487,22 @@ static void md_clean(struct mddev *mddev) · 404 unmodified lines | ||
| 6431 | 6487 | mddev->persistent = 0; |
| 6432 | 6488 | mddev->level = LEVEL_NONE; |
| 6433 | 6489 | mddev->clevel[0] = 0; |
| 6434 | − /* if UNTIL_STOP is set, it's cleared here */ | |
| 6435 | − mddev->hold_active = 0; | |
| 6436 | − /* Don't clear MD_CLOSING, or mddev can be opened again. */ | |
| 6437 | − mddev->flags &= BIT_ULL_MASK(MD_CLOSING); | |
| 6490 | + | |
| 6491 | + /* | |
| 6492 | + * For legacy_async_del_gendisk mode, it can stop the array in the | |
| 6493 | + * middle of assembling it, then it still can access the array. So | |
| 6494 | + * it needs to clear MD_CLOSING. If not legacy_async_del_gendisk, | |
| 6495 | + * it can't open the array again after stopping it. So it doesn't | |
| 6496 | + * clear MD_CLOSING. | |
| 6497 | + */ | |
| 6498 | + if (legacy_async_del_gendisk && mddev->hold_active) { | |
| 6499 | + clear_bit(MD_CLOSING, &mddev->flags); | |
| 6500 | + } else { | |
| 6501 | + /* if UNTIL_STOP is set, it's cleared here */ | |
| 6502 | + mddev->hold_active = 0; | |
| 6503 | + /* Don't clear MD_CLOSING, or mddev can be opened again. */ | |
| 6504 | + mddev->flags &= BIT_ULL_MASK(MD_CLOSING); | |
| 6505 | + } | |
| 6438 | 6506 | mddev->sb_flags = 0; |
| 6439 | 6507 | mddev->ro = MD_RDWR; |
| 6440 | 6508 | mddev->metadata_type[0] = 0; |
| @@ -6658,7 +6726,8 @@ static int do_md_stop(struct mddev *mddev, int mode) · 217 unmodified lines | ||
| 6658 | 6726 | |
| 6659 | 6727 | export_array(mddev); |
| 6660 | 6728 | md_clean(mddev); |
| 6661 | − set_bit(MD_DELETED, &mddev->flags); | |
| 6729 | + if (!legacy_async_del_gendisk) | |
| 6730 | + set_bit(MD_DELETED, &mddev->flags); | |
| 6662 | 6731 | } |
| 6663 | 6732 | md_new_event(); |
| 6664 | 6733 | sysfs_notify_dirent_safe(mddev->sysfs_state); |
| @@ -8968,11 +9037,7 @@ static sector_t md_sync_position(struct mddev *mddev, enum sync_action action) · 2303 unmodified lines | ||
| 8968 | 9037 | start = MaxSector; |
| 8969 | 9038 | rcu_read_lock(); |
| 8970 | 9039 | rdev_for_each_rcu(rdev, mddev) |
| 8971 | − if (rdev->raid_disk >= 0 && | |
| 8972 | − !test_bit(Journal, &rdev->flags) && | |
| 8973 | − !test_bit(Faulty, &rdev->flags) && | |
| 8974 | − !test_bit(In_sync, &rdev->flags) && | |
| 8975 | − rdev->recovery_offset < start) | |
| 9040 | + if (rdev_needs_recovery(rdev, start)) | |
| 8976 | 9041 | start = rdev->recovery_offset; |
| 8977 | 9042 | rcu_read_unlock(); |
| 8978 | 9043 | |
| @@ -9331,12 +9396,8 @@ void md_do_sync(struct md_thread *thread) · 352 unmodified lines | ||
| 9331 | 9396 | test_bit(MD_RECOVERY_RECOVER, &mddev->recovery)) { |
| 9332 | 9397 | rcu_read_lock(); |
| 9333 | 9398 | rdev_for_each_rcu(rdev, mddev) |
| 9334 | − if (rdev->raid_disk >= 0 && | |
| 9335 | − mddev->delta_disks >= 0 && | |
| 9336 | − !test_bit(Journal, &rdev->flags) && | |
| 9337 | − !test_bit(Faulty, &rdev->flags) && | |
| 9338 | − !test_bit(In_sync, &rdev->flags) && | |
| 9339 | − rdev->recovery_offset < mddev->curr_resync) | |
| 9399 | + if (mddev->delta_disks >= 0 && | |
| 9400 | + rdev_needs_recovery(rdev, mddev->curr_resync)) | |
| 9340 | 9401 | rdev->recovery_offset = mddev->curr_resync; |
| 9341 | 9402 | rcu_read_unlock(); |
| 9342 | 9403 | } |
| @@ -10392,6 +10453,7 @@ module_param_call(start_ro, set_ro, get_ro, NULL, S_IRUSR|S_IWUSR); · 1049 unmodified lines | ||
| 10392 | 10453 | module_param(start_dirty_degraded, int, S_IRUGO|S_IWUSR); |
| 10393 | 10454 | module_param_call(new_array, add_named_array, NULL, NULL, S_IWUSR); |
| 10394 | 10455 | module_param(create_on_open, bool, S_IRUSR|S_IWUSR); |
| 10456 | +module_param(legacy_async_del_gendisk, bool, 0600); | |
| 10395 | 10457 | |
| 10396 | 10458 | MODULE_LICENSE("GPL"); |
| 10397 | 10459 | MODULE_DESCRIPTION("MD RAID framework"); |
| @@ -1841,7 +1841,6 @@ static int alvium_s_stream(struct v4l2_subdev *sd, int enable) · 1840 unmodified lines | ||
| 1841 | 1841 | |
| 1842 | 1842 | } else { |
| 1843 | 1843 | alvium_set_stream_mipi(alvium, enable); |
| 1844 | − pm_runtime_mark_last_busy(&client->dev); | |
| 1845 | 1844 | pm_runtime_put_autosuspend(&client->dev); |
| 1846 | 1845 | } |
| 1847 | 1846 | |
| @@ -787,10 +787,8 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl) · 786 unmodified lines | ||
| 787 | 787 | rval = -EINVAL; |
| 788 | 788 | } |
| 789 | 789 | |
| 790 | − if (pm_status > 0) { | |
| 791 | − pm_runtime_mark_last_busy(&client->dev); | |
| 790 | + if (pm_status > 0) | |
| 792 | 791 | pm_runtime_put_autosuspend(&client->dev); |
| 793 | − } | |
| 794 | 792 | |
| 795 | 793 | return rval; |
| 796 | 794 | } |
| @@ -1914,7 +1912,6 @@ static int ccs_set_stream(struct v4l2_subdev *subdev, int enable) · 1117 unmodified lines | ||
| 1914 | 1912 | if (!enable) { |
| 1915 | 1913 | ccs_stop_streaming(sensor); |
| 1916 | 1914 | sensor->streaming = false; |
| 1917 | − pm_runtime_mark_last_busy(&client->dev); | |
| 1918 | 1915 | pm_runtime_put_autosuspend(&client->dev); |
| 1919 | 1916 | |
| 1920 | 1917 | return 0; |
| @@ -1929,7 +1926,6 @@ static int ccs_set_stream(struct v4l2_subdev *subdev, int enable) · 8 unmodified lines | ||
| 1929 | 1926 | rval = ccs_start_streaming(sensor); |
| 1930 | 1927 | if (rval < 0) { |
| 1931 | 1928 | sensor->streaming = false; |
| 1932 | − pm_runtime_mark_last_busy(&client->dev); | |
| 1933 | 1929 | pm_runtime_put_autosuspend(&client->dev); |
| 1934 | 1930 | } |
| 1935 | 1931 | |
| @@ -2677,7 +2673,6 @@ nvm_show(struct device *dev, struct device_attribute *attr, char *buf) · 741 unmodified lines | ||
| 2677 | 2673 | return -ENODEV; |
| 2678 | 2674 | } |
| 2679 | 2675 | |
| 2680 | − pm_runtime_mark_last_busy(&client->dev); | |
| 2681 | 2676 | pm_runtime_put_autosuspend(&client->dev); |
| 2682 | 2677 | |
| 2683 | 2678 | /* |
| @@ -374,7 +374,6 @@ static int dw9768_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) · 373 unmodified lines | ||
| 374 | 374 | |
| 375 | 375 | static int dw9768_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
| 376 | 376 | { |
| 377 | − pm_runtime_mark_last_busy(sd->dev); | |
| 378 | 377 | pm_runtime_put_autosuspend(sd->dev); |
| 379 | 378 | |
| 380 | 379 | return 0; |
| @@ -974,7 +974,6 @@ static int gc0308_s_ctrl(struct v4l2_ctrl *ctrl) · 973 unmodified lines | ||
| 974 | 974 | if (ret) |
| 975 | 975 | dev_err(gc0308->dev, "failed to set control: %d\n", ret); |
| 976 | 976 | |
| 977 | − pm_runtime_mark_last_busy(gc0308->dev); | |
| 978 | 977 | pm_runtime_put_autosuspend(gc0308->dev); |
| 979 | 978 | |
| 980 | 979 | return ret; |
| @@ -1157,14 +1156,12 @@ static int gc0308_start_stream(struct gc0308 *gc0308) · 176 unmodified lines | ||
| 1157 | 1156 | return 0; |
| 1158 | 1157 | |
| 1159 | 1158 | disable_pm: |
| 1160 | − pm_runtime_mark_last_busy(gc0308->dev); | |
| 1161 | 1159 | pm_runtime_put_autosuspend(gc0308->dev); |
| 1162 | 1160 | return ret; |
| 1163 | 1161 | } |
| 1164 | 1162 | |
| 1165 | 1163 | static int gc0308_stop_stream(struct gc0308 *gc0308) |
| 1166 | 1164 | { |
| 1167 | − pm_runtime_mark_last_busy(gc0308->dev); | |
| 1168 | 1165 | pm_runtime_put_autosuspend(gc0308->dev); |
| 1169 | 1166 | return 0; |
| 1170 | 1167 | } |
| @@ -963,7 +963,6 @@ static int gc2145_enable_streams(struct v4l2_subdev *sd, · 962 unmodified lines | ||
| 963 | 963 | return 0; |
| 964 | 964 | |
| 965 | 965 | err_rpm_put: |
| 966 | − pm_runtime_mark_last_busy(&client->dev); | |
| 967 | 966 | pm_runtime_put_autosuspend(&client->dev); |
| 968 | 967 | return ret; |
| 969 | 968 | } |
| @@ -985,7 +984,6 @@ static int gc2145_disable_streams(struct v4l2_subdev *sd, · 15 unmodified lines | ||
| 985 | 984 | if (ret) |
| 986 | 985 | dev_err(&client->dev, "%s failed to write regs\n", __func__); |
| 987 | 986 | |
| 988 | − pm_runtime_mark_last_busy(&client->dev); | |
| 989 | 987 | pm_runtime_put_autosuspend(&client->dev); |
| 990 | 988 | |
| 991 | 989 | return ret; |
| @@ -1193,7 +1191,6 @@ static int gc2145_s_ctrl(struct v4l2_ctrl *ctrl) · 201 unmodified lines | ||
| 1193 | 1191 | break; |
| 1194 | 1192 | } |
| 1195 | 1193 | |
| 1196 | − pm_runtime_mark_last_busy(&client->dev); | |
| 1197 | 1194 | pm_runtime_put_autosuspend(&client->dev); |
| 1198 | 1195 | |
| 1199 | 1196 | return ret; |
| @@ -771,7 +771,6 @@ static int imx219_enable_streams(struct v4l2_subdev *sd, · 770 unmodified lines | ||
| 771 | 771 | return 0; |
| 772 | 772 | |
| 773 | 773 | err_rpm_put: |
| 774 | − pm_runtime_mark_last_busy(&client->dev); | |
| 775 | 774 | pm_runtime_put_autosuspend(&client->dev); |
| 776 | 775 | return ret; |
| 777 | 776 | } |
| @@ -793,7 +792,6 @@ static int imx219_disable_streams(struct v4l2_subdev *sd, · 15 unmodified lines | ||
| 793 | 792 | __v4l2_ctrl_grab(imx219->vflip, false); |
| 794 | 793 | __v4l2_ctrl_grab(imx219->hflip, false); |
| 795 | 794 | |
| 796 | − pm_runtime_mark_last_busy(&client->dev); | |
| 797 | 795 | pm_runtime_put_autosuspend(&client->dev); |
| 798 | 796 | |
| 799 | 797 | return ret; |
| @@ -1143,7 +1143,6 @@ static int imx283_enable_streams(struct v4l2_subdev *sd, · 1142 unmodified lines | ||
| 1143 | 1143 | return 0; |
| 1144 | 1144 | |
| 1145 | 1145 | err_rpm_put: |
| 1146 | − pm_runtime_mark_last_busy(imx283->dev); | |
| 1147 | 1146 | pm_runtime_put_autosuspend(imx283->dev); |
| 1148 | 1147 | |
| 1149 | 1148 | return ret; |
| @@ -1163,7 +1162,6 @@ static int imx283_disable_streams(struct v4l2_subdev *sd, · 13 unmodified lines | ||
| 1163 | 1162 | if (ret) |
| 1164 | 1163 | dev_err(imx283->dev, "Failed to stop stream\n"); |
| 1165 | 1164 | |
| 1166 | − pm_runtime_mark_last_busy(imx283->dev); | |
| 1167 | 1165 | pm_runtime_put_autosuspend(imx283->dev); |
| 1168 | 1166 | |
| 1169 | 1167 | return ret; |
| @@ -1558,7 +1556,6 @@ static int imx283_probe(struct i2c_client *client) · 388 unmodified lines | ||
| 1558 | 1556 | * Decrease the PM usage count. The device will get suspended after the |
| 1559 | 1557 | * autosuspend delay, turning the power off. |
| 1560 | 1558 | */ |
| 1561 | − pm_runtime_mark_last_busy(imx283->dev); | |
| 1562 | 1559 | pm_runtime_put_autosuspend(imx283->dev); |
| 1563 | 1560 | |
| 1564 | 1561 | return 0; |
| @@ -869,7 +869,6 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl) · 868 unmodified lines | ||
| 869 | 869 | break; |
| 870 | 870 | } |
| 871 | 871 | |
| 872 | − pm_runtime_mark_last_busy(imx290->dev); | |
| 873 | 872 | pm_runtime_put_autosuspend(imx290->dev); |
| 874 | 873 | |
| 875 | 874 | return ret; |
| @@ -1099,7 +1098,6 @@ static int imx290_set_stream(struct v4l2_subdev *sd, int enable) · 223 unmodified lines | ||
| 1099 | 1098 | } |
| 1100 | 1099 | } else { |
| 1101 | 1100 | imx290_stop_streaming(imx290); |
| 1102 | − pm_runtime_mark_last_busy(imx290->dev); | |
| 1103 | 1101 | pm_runtime_put_autosuspend(imx290->dev); |
| 1104 | 1102 | } |
| 1105 | 1103 | |
| @@ -1294,7 +1292,6 @@ static int imx290_subdev_init(struct imx290 *imx290) · 188 unmodified lines | ||
| 1294 | 1292 | * will already be prevented even before the delay. |
| 1295 | 1293 | */ |
| 1296 | 1294 | v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops); |
| 1297 | − pm_runtime_mark_last_busy(imx290->dev); | |
| 1298 | 1295 | pm_runtime_put_autosuspend(imx290->dev); |
| 1299 | 1296 | |
| 1300 | 1297 | imx290->sd.internal_ops = &imx290_internal_ops; |
| @@ -604,7 +604,6 @@ static int imx296_s_stream(struct v4l2_subdev *sd, int enable) · 603 unmodified lines | ||
| 604 | 604 | if (!enable) { |
| 605 | 605 | ret = imx296_stream_off(sensor); |
| 606 | 606 | |
| 607 | − pm_runtime_mark_last_busy(sensor->dev); | |
| 608 | 607 | pm_runtime_put_autosuspend(sensor->dev); |
| 609 | 608 | |
| 610 | 609 | goto unlock; |
| @@ -952,7 +952,6 @@ static int imx415_s_stream(struct v4l2_subdev *sd, int enable) · 951 unmodified lines | ||
| 952 | 952 | if (!enable) { |
| 953 | 953 | ret = imx415_stream_off(sensor); |
| 954 | 954 | |
| 955 | − pm_runtime_mark_last_busy(sensor->dev); | |
| 956 | 955 | pm_runtime_put_autosuspend(sensor->dev); |
| 957 | 956 | |
| 958 | 957 | goto unlock; |
| @@ -974,7 +974,6 @@ static int mt9m114_start_streaming(struct mt9m114 *sensor, · 973 unmodified lines | ||
| 974 | 974 | return 0; |
| 975 | 975 | |
| 976 | 976 | error: |
| 977 | − pm_runtime_mark_last_busy(&sensor->client->dev); | |
| 978 | 977 | pm_runtime_put_autosuspend(&sensor->client->dev); |
| 979 | 978 | |
| 980 | 979 | return ret; |
| @@ -988,7 +987,6 @@ static int mt9m114_stop_streaming(struct mt9m114 *sensor) · 7 unmodified lines | ||
| 988 | 987 | |
| 989 | 988 | ret = mt9m114_set_state(sensor, MT9M114_SYS_STATE_ENTER_SUSPEND); |
| 990 | 989 | |
| 991 | − pm_runtime_mark_last_busy(&sensor->client->dev); | |
| 992 | 990 | pm_runtime_put_autosuspend(&sensor->client->dev); |
| 993 | 991 | |
| 994 | 992 | return ret; |
| @@ -1046,7 +1044,6 @@ static int mt9m114_pa_g_ctrl(struct v4l2_ctrl *ctrl) · 51 unmodified lines | ||
| 1046 | 1044 | break; |
| 1047 | 1045 | } |
| 1048 | 1046 | |
| 1049 | − pm_runtime_mark_last_busy(&sensor->client->dev); | |
| 1050 | 1047 | pm_runtime_put_autosuspend(&sensor->client->dev); |
| 1051 | 1048 | |
| 1052 | 1049 | return ret; |
| @@ -1113,7 +1110,6 @@ static int mt9m114_pa_s_ctrl(struct v4l2_ctrl *ctrl) · 60 unmodified lines | ||
| 1113 | 1110 | break; |
| 1114 | 1111 | } |
| 1115 | 1112 | |
| 1116 | − pm_runtime_mark_last_busy(&sensor->client->dev); | |
| 1117 | 1113 | pm_runtime_put_autosuspend(&sensor->client->dev); |
| 1118 | 1114 | |
| 1119 | 1115 | return ret; |
| @@ -1565,7 +1561,6 @@ static int mt9m114_ifp_s_ctrl(struct v4l2_ctrl *ctrl) · 445 unmodified lines | ||
| 1565 | 1561 | break; |
| 1566 | 1562 | } |
| 1567 | 1563 | |
| 1568 | − pm_runtime_mark_last_busy(&sensor->client->dev); | |
| 1569 | 1564 | pm_runtime_put_autosuspend(&sensor->client->dev); |
| 1570 | 1565 | |
| 1571 | 1566 | return ret; |
| @@ -2472,7 +2467,6 @@ static int mt9m114_probe(struct i2c_client *client) · 900 unmodified lines | ||
| 2472 | 2467 | * Decrease the PM usage count. The device will get suspended after the |
| 2473 | 2468 | * autosuspend delay, turning the power off. |
| 2474 | 2469 | */ |
| 2475 | − pm_runtime_mark_last_busy(dev); | |
| 2476 | 2470 | pm_runtime_put_autosuspend(dev); |
| 2477 | 2471 | |
| 2478 | 2472 | return 0; |
| @@ -497,7 +497,6 @@ static int ov4689_s_stream(struct v4l2_subdev *sd, int on) · 496 unmodified lines | ||
| 497 | 497 | } else { |
| 498 | 498 | cci_write(ov4689->regmap, OV4689_REG_CTRL_MODE, |
| 499 | 499 | OV4689_MODE_SW_STANDBY, NULL); |
| 500 | − pm_runtime_mark_last_busy(dev); | |
| 501 | 500 | pm_runtime_put_autosuspend(dev); |
| 502 | 501 | } |
| 503 | 502 | |
| @@ -702,7 +701,6 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) · 198 unmodified lines | ||
| 702 | 701 | break; |
| 703 | 702 | } |
| 704 | 703 | |
| 705 | − pm_runtime_mark_last_busy(dev); | |
| 706 | 704 | pm_runtime_put_autosuspend(dev); |
| 707 | 705 | |
| 708 | 706 | return ret; |
| @@ -999,7 +997,6 @@ static int ov4689_probe(struct i2c_client *client) · 290 unmodified lines | ||
| 999 | 997 | goto err_clean_subdev_pm; |
| 1000 | 998 | } |
| 1001 | 999 | |
| 1002 | − pm_runtime_mark_last_busy(dev); | |
| 1003 | 1000 | pm_runtime_put_autosuspend(dev); |
| 1004 | 1001 | |
| 1005 | 1002 | return 0; |
| @@ -3341,7 +3341,6 @@ static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl) · 3340 unmodified lines | ||
| 3341 | 3341 | break; |
| 3342 | 3342 | } |
| 3343 | 3343 | |
| 3344 | − pm_runtime_mark_last_busy(&sensor->i2c_client->dev); | |
| 3345 | 3344 | pm_runtime_put_autosuspend(&sensor->i2c_client->dev); |
| 3346 | 3345 | |
| 3347 | 3346 | return 0; |
| @@ -3417,7 +3416,6 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl) · 69 unmodified lines | ||
| 3417 | 3416 | break; |
| 3418 | 3417 | } |
| 3419 | 3418 | |
| 3420 | − pm_runtime_mark_last_busy(&sensor->i2c_client->dev); | |
| 3421 | 3419 | pm_runtime_put_autosuspend(&sensor->i2c_client->dev); |
| 3422 | 3420 | |
| 3423 | 3421 | return ret; |
| @@ -3754,7 +3752,6 @@ out: · 330 unmodified lines | ||
| 3754 | 3752 | mutex_unlock(&sensor->lock); |
| 3755 | 3753 | |
| 3756 | 3754 | if (!enable || ret) { |
| 3757 | − pm_runtime_mark_last_busy(&sensor->i2c_client->dev); | |
| 3758 | 3755 | pm_runtime_put_autosuspend(&sensor->i2c_client->dev); |
| 3759 | 3756 | } |
| 3760 | 3757 | |
| @@ -3965,7 +3962,6 @@ static int ov5640_probe(struct i2c_client *client) · 204 unmodified lines | ||
| 3965 | 3962 | |
| 3966 | 3963 | pm_runtime_set_autosuspend_delay(dev, 1000); |
| 3967 | 3964 | pm_runtime_use_autosuspend(dev); |
| 3968 | − pm_runtime_mark_last_busy(dev); | |
| 3969 | 3965 | pm_runtime_put_autosuspend(dev); |
| 3970 | 3966 | |
| 3971 | 3967 | return 0; |
| @@ -808,7 +808,6 @@ static int ov5645_s_ctrl(struct v4l2_ctrl *ctrl) · 807 unmodified lines | ||
| 808 | 808 | break; |
| 809 | 809 | } |
| 810 | 810 | |
| 811 | − pm_runtime_mark_last_busy(ov5645->dev); | |
| 812 | 811 | pm_runtime_put_autosuspend(ov5645->dev); |
| 813 | 812 | |
| 814 | 813 | return ret; |
| @@ -979,7 +978,6 @@ static int ov5645_disable_streams(struct v4l2_subdev *sd, · 164 unmodified lines | ||
| 979 | 978 | OV5645_SYSTEM_CTRL0_STOP); |
| 980 | 979 | |
| 981 | 980 | rpm_put: |
| 982 | − pm_runtime_mark_last_busy(ov5645->dev); | |
| 983 | 981 | pm_runtime_put_autosuspend(ov5645->dev); |
| 984 | 982 | |
| 985 | 983 | return ret; |
| @@ -1196,7 +1194,6 @@ static int ov5645_probe(struct i2c_client *client) · 210 unmodified lines | ||
| 1196 | 1194 | |
| 1197 | 1195 | pm_runtime_set_autosuspend_delay(dev, 1000); |
| 1198 | 1196 | pm_runtime_use_autosuspend(dev); |
| 1199 | − pm_runtime_mark_last_busy(dev); | |
| 1200 | 1197 | pm_runtime_put_autosuspend(dev); |
| 1201 | 1198 | |
| 1202 | 1199 | return 0; |
| @@ -2990,7 +2990,6 @@ static int ov64a40_start_streaming(struct ov64a40 *ov64a40, · 2989 unmodified lines | ||
| 2990 | 2990 | return 0; |
| 2991 | 2991 | |
| 2992 | 2992 | error_power_off: |
| 2993 | − pm_runtime_mark_last_busy(ov64a40->dev); | |
| 2994 | 2993 | pm_runtime_put_autosuspend(ov64a40->dev); |
| 2995 | 2994 | |
| 2996 | 2995 | return ret; |
| @@ -3000,7 +2999,6 @@ static int ov64a40_stop_streaming(struct ov64a40 *ov64a40, · 3 unmodified lines | ||
| 3000 | 2999 | struct v4l2_subdev_state *state) |
| 3001 | 3000 | { |
| 3002 | 3001 | cci_update_bits(ov64a40->cci, OV64A40_REG_SMIA, BIT(0), 0, NULL); |
| 3003 | − pm_runtime_mark_last_busy(ov64a40->dev); | |
| 3004 | 3002 | pm_runtime_put_autosuspend(ov64a40->dev); |
| 3005 | 3003 | |
| 3006 | 3004 | __v4l2_ctrl_grab(ov64a40->link_freq, false); |
| @@ -3329,10 +3327,8 @@ static int ov64a40_set_ctrl(struct v4l2_ctrl *ctrl) · 322 unmodified lines | ||
| 3329 | 3327 | break; |
| 3330 | 3328 | } |
| 3331 | 3329 | |
| 3332 | − if (pm_status > 0) { | |
| 3333 | − pm_runtime_mark_last_busy(ov64a40->dev); | |
| 3330 | + if (pm_status > 0) | |
| 3334 | 3331 | pm_runtime_put_autosuspend(ov64a40->dev); |
| 3335 | − } | |
| 3336 | 3332 | |
| 3337 | 3333 | return ret; |
| 3338 | 3334 | } |
| @@ -3622,7 +3618,6 @@ static int ov64a40_probe(struct i2c_client *client) · 283 unmodified lines | ||
| 3622 | 3618 | goto error_subdev_cleanup; |
| 3623 | 3619 | } |
| 3624 | 3620 | |
| 3625 | − pm_runtime_mark_last_busy(&client->dev); | |
| 3626 | 3621 | pm_runtime_put_autosuspend(&client->dev); |
| 3627 | 3622 | |
| 3628 | 3623 | return 0; |
| @@ -1391,7 +1391,6 @@ static int ov8858_s_stream(struct v4l2_subdev *sd, int on) · 1390 unmodified lines | ||
| 1391 | 1391 | } |
| 1392 | 1392 | } else { |
| 1393 | 1393 | ov8858_stop_stream(ov8858); |
| 1394 | − pm_runtime_mark_last_busy(&client->dev); | |
| 1395 | 1394 | pm_runtime_put_autosuspend(&client->dev); |
| 1396 | 1395 | } |
| 1397 | 1396 | |
| @@ -1945,7 +1944,6 @@ static int ov8858_probe(struct i2c_client *client) · 547 unmodified lines | ||
| 1945 | 1944 | goto err_power_off; |
| 1946 | 1945 | } |
| 1947 | 1946 | |
| 1948 | − pm_runtime_mark_last_busy(dev); | |
| 1949 | 1947 | pm_runtime_put_autosuspend(dev); |
| 1950 | 1948 | |
| 1951 | 1949 | return 0; |
| @@ -465,7 +465,6 @@ static int mipid02_disable_streams(struct v4l2_subdev *sd, · 464 unmodified lines | ||
| 465 | 465 | if (ret) |
| 466 | 466 | goto error; |
| 467 | 467 | |
| 468 | − pm_runtime_mark_last_busy(&client->dev); | |
| 469 | 468 | pm_runtime_put_autosuspend(&client->dev); |
| 470 | 469 | |
| 471 | 470 | error: |
| @@ -542,7 +541,6 @@ error: · 70 unmodified lines | ||
| 542 | 541 | cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, 0, &ret); |
| 543 | 542 | cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret); |
| 544 | 543 | |
| 545 | − pm_runtime_mark_last_busy(&client->dev); | |
| 546 | 544 | pm_runtime_put_autosuspend(&client->dev); |
| 547 | 545 | return ret; |
| 548 | 546 | } |
| @@ -816,7 +816,6 @@ static int tc358746_s_stream(struct v4l2_subdev *sd, int enable) · 815 unmodified lines | ||
| 816 | 816 | return 0; |
| 817 | 817 | |
| 818 | 818 | err_out: |
| 819 | − pm_runtime_mark_last_busy(sd->dev); | |
| 820 | 819 | pm_runtime_put_sync_autosuspend(sd->dev); |
| 821 | 820 | |
| 822 | 821 | return err; |
| @@ -838,7 +837,6 @@ err_out: · 15 unmodified lines | ||
| 838 | 837 | if (err) |
| 839 | 838 | return err; |
| 840 | 839 | |
| 841 | − pm_runtime_mark_last_busy(sd->dev); | |
| 842 | 840 | pm_runtime_put_sync_autosuspend(sd->dev); |
| 843 | 841 | |
| 844 | 842 | return v4l2_subdev_call(src, video, s_stream, 0); |
| @@ -1016,7 +1014,6 @@ tc358746_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) · 171 unmodified lines | ||
| 1016 | 1014 | err = tc358746_read(tc358746, reg->reg, &val); |
| 1017 | 1015 | reg->val = val; |
| 1018 | 1016 | |
| 1019 | − pm_runtime_mark_last_busy(sd->dev); | |
| 1020 | 1017 | pm_runtime_put_sync_autosuspend(sd->dev); |
| 1021 | 1018 | |
| 1022 | 1019 | return err; |
| @@ -1032,7 +1029,6 @@ tc358746_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) · 9 unmodified lines | ||
| 1032 | 1029 | |
| 1033 | 1030 | tc358746_write(tc358746, (u32)reg->reg, (u32)reg->val); |
| 1034 | 1031 | |
| 1035 | − pm_runtime_mark_last_busy(sd->dev); | |
| 1036 | 1032 | pm_runtime_put_sync_autosuspend(sd->dev); |
| 1037 | 1033 | |
| 1038 | 1034 | return 0; |
| @@ -1395,7 +1391,6 @@ static int tc358746_init_hw(struct tc358746 *tc358746) · 356 unmodified lines | ||
| 1395 | 1391 | } |
| 1396 | 1392 | |
| 1397 | 1393 | err = tc358746_read(tc358746, CHIPID_REG, &val); |
| 1398 | − pm_runtime_mark_last_busy(dev); | |
| 1399 | 1394 | pm_runtime_put_sync_autosuspend(dev); |
| 1400 | 1395 | if (err) |
| 1401 | 1396 | return -ENODEV; |
| @@ -808,7 +808,6 @@ static int thp7312_s_stream(struct v4l2_subdev *sd, int enable) · 807 unmodified lines | ||
| 808 | 808 | if (!enable) { |
| 809 | 809 | thp7312_stream_enable(thp7312, false); |
| 810 | 810 | |
| 811 | − pm_runtime_mark_last_busy(thp7312->dev); | |
| 812 | 811 | pm_runtime_put_autosuspend(thp7312->dev); |
| 813 | 812 | |
| 814 | 813 | v4l2_subdev_unlock_state(sd_state); |
| @@ -839,7 +838,6 @@ static int thp7312_s_stream(struct v4l2_subdev *sd, int enable) · 24 unmodified lines | ||
| 839 | 838 | goto finish_unlock; |
| 840 | 839 | |
| 841 | 840 | finish_pm: |
| 842 | − pm_runtime_mark_last_busy(thp7312->dev); | |
| 843 | 841 | pm_runtime_put_autosuspend(thp7312->dev); |
| 844 | 842 | finish_unlock: |
| 845 | 843 | v4l2_subdev_unlock_state(sd_state); |
| @@ -1147,7 +1145,6 @@ static int thp7312_s_ctrl(struct v4l2_ctrl *ctrl) · 301 unmodified lines | ||
| 1147 | 1145 | break; |
| 1148 | 1146 | } |
| 1149 | 1147 | |
| 1150 | − pm_runtime_mark_last_busy(thp7312->dev); | |
| 1151 | 1148 | pm_runtime_put_autosuspend(thp7312->dev); |
| 1152 | 1149 | |
| 1153 | 1150 | return ret; |
| @@ -2183,7 +2180,6 @@ static int thp7312_probe(struct i2c_client *client) · 1029 unmodified lines | ||
| 2183 | 2180 | * Decrease the PM usage count. The device will get suspended after the |
| 2184 | 2181 | * autosuspend delay, turning the power off. |
| 2185 | 2182 | */ |
| 2186 | − pm_runtime_mark_last_busy(dev); | |
| 2187 | 2183 | pm_runtime_put_autosuspend(dev); |
| 2188 | 2184 | |
| 2189 | 2185 | dev_info(dev, "THP7312 firmware version %02u.%02u\n", |
| @@ -1104,7 +1104,6 @@ static int vd55g1_disable_streams(struct v4l2_subdev *sd, · 1103 unmodified lines | ||
| 1104 | 1104 | |
| 1105 | 1105 | vd55g1_grab_ctrls(sensor, false); |
| 1106 | 1106 | |
| 1107 | − pm_runtime_mark_last_busy(sensor->dev); | |
| 1108 | 1107 | pm_runtime_put_autosuspend(sensor->dev); |
| 1109 | 1108 | |
| 1110 | 1109 | return ret; |
| @@ -1338,7 +1337,6 @@ static int vd55g1_g_volatile_ctrl(struct v4l2_ctrl *ctrl) · 227 unmodified lines | ||
| 1338 | 1337 | break; |
| 1339 | 1338 | } |
| 1340 | 1339 | |
| 1341 | − pm_runtime_mark_last_busy(sensor->dev); | |
| 1342 | 1340 | pm_runtime_put_autosuspend(sensor->dev); |
| 1343 | 1341 | |
| 1344 | 1342 | return ret; |
| @@ -1433,7 +1431,6 @@ static int vd55g1_s_ctrl(struct v4l2_ctrl *ctrl) · 88 unmodified lines | ||
| 1433 | 1431 | break; |
| 1434 | 1432 | } |
| 1435 | 1433 | |
| 1436 | − pm_runtime_mark_last_busy(sensor->dev); | |
| 1437 | 1434 | pm_runtime_put_autosuspend(sensor->dev); |
| 1438 | 1435 | |
| 1439 | 1436 | return ret; |
| @@ -1895,7 +1892,6 @@ static int vd55g1_probe(struct i2c_client *client) · 455 unmodified lines | ||
| 1895 | 1892 | pm_runtime_enable(dev); |
| 1896 | 1893 | pm_runtime_set_autosuspend_delay(dev, 4000); |
| 1897 | 1894 | pm_runtime_use_autosuspend(dev); |
| 1898 | − pm_runtime_mark_last_busy(dev); | |
| 1899 | 1895 | pm_runtime_put_autosuspend(dev); |
| 1900 | 1896 | |
| 1901 | 1897 | ret = vd55g1_subdev_init(sensor); |
| @@ -493,7 +493,6 @@ static int vd56g3_g_volatile_ctrl(struct v4l2_ctrl *ctrl) · 492 unmodified lines | ||
| 493 | 493 | break; |
| 494 | 494 | } |
| 495 | 495 | |
| 496 | − pm_runtime_mark_last_busy(sensor->dev); | |
| 497 | 496 | pm_runtime_put_autosuspend(sensor->dev); |
| 498 | 497 | |
| 499 | 498 | return ret; |
| @@ -577,7 +576,6 @@ static int vd56g3_s_ctrl(struct v4l2_ctrl *ctrl) · 77 unmodified lines | ||
| 577 | 576 | break; |
| 578 | 577 | } |
| 579 | 578 | |
| 580 | − pm_runtime_mark_last_busy(sensor->dev); | |
| 581 | 579 | pm_runtime_put_autosuspend(sensor->dev); |
| 582 | 580 | |
| 583 | 581 | return ret; |
| @@ -1021,7 +1019,6 @@ static int vd56g3_disable_streams(struct v4l2_subdev *sd, · 437 unmodified lines | ||
| 1021 | 1019 | __v4l2_ctrl_grab(sensor->vflip_ctrl, false); |
| 1022 | 1020 | __v4l2_ctrl_grab(sensor->patgen_ctrl, false); |
| 1023 | 1021 | |
| 1024 | − pm_runtime_mark_last_busy(sensor->dev); | |
| 1025 | 1022 | pm_runtime_put_autosuspend(sensor->dev); |
| 1026 | 1023 | |
| 1027 | 1024 | return ret; |
| @@ -1527,7 +1524,6 @@ static int vd56g3_probe(struct i2c_client *client) · 499 unmodified lines | ||
| 1527 | 1524 | } |
| 1528 | 1525 | |
| 1529 | 1526 | /* Sensor could now be powered off (after the autosuspend delay) */ |
| 1530 | − pm_runtime_mark_last_busy(dev); | |
| 1531 | 1527 | pm_runtime_put_autosuspend(dev); |
| 1532 | 1528 | |
| 1533 | 1529 | dev_dbg(dev, "Successfully probe %s sensor\n", |
| @@ -288,7 +288,6 @@ static int amg88xx_read(struct device *dev, enum hwmon_sensor_types type, · 287 unmodified lines | ||
| 288 | 288 | return tmp; |
| 289 | 289 | |
| 290 | 290 | tmp = regmap_bulk_read(data->regmap, AMG88XX_REG_TTHL, &buf, 2); |
| 291 | − pm_runtime_mark_last_busy(regmap_get_device(data->regmap)); | |
| 292 | 291 | pm_runtime_put_autosuspend(regmap_get_device(data->regmap)); |
| 293 | 292 | if (tmp) |
| 294 | 293 | return tmp; |
| @@ -527,7 +526,6 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) · 232 unmodified lines | ||
| 527 | 526 | return 0; |
| 528 | 527 | |
| 529 | 528 | error_rpm_put: |
| 530 | − pm_runtime_mark_last_busy(dev); | |
| 531 | 529 | pm_runtime_put_autosuspend(dev); |
| 532 | 530 | error_del_list: |
| 533 | 531 | video_i2c_del_list(vq, VB2_BUF_STATE_QUEUED); |
| @@ -544,7 +542,6 @@ static void stop_streaming(struct vb2_queue *vq) · 10 unmodified lines | ||
| 544 | 542 | |
| 545 | 543 | kthread_stop(data->kthread_vid_cap); |
| 546 | 544 | data->kthread_vid_cap = NULL; |
| 547 | − pm_runtime_mark_last_busy(regmap_get_device(data->regmap)); | |
| 548 | 545 | pm_runtime_put_autosuspend(regmap_get_device(data->regmap)); |
| 549 | 546 | |
| 550 | 547 | video_i2c_del_list(vq, VB2_BUF_STATE_ERROR); |
| @@ -853,7 +850,6 @@ static int video_i2c_probe(struct i2c_client *client) · 302 unmodified lines | ||
| 853 | 850 | if (ret < 0) |
| 854 | 851 | goto error_pm_disable; |
| 855 | 852 | |
| 856 | − pm_runtime_mark_last_busy(&client->dev); | |
| 857 | 853 | pm_runtime_put_autosuspend(&client->dev); |
| 858 | 854 | |
| 859 | 855 | return 0; |
| @@ -451,7 +451,6 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) · 450 unmodified lines | ||
| 451 | 451 | if (q_status.report_queue_count == 0 && |
| 452 | 452 | (q_status.instance_queue_count == 0 || dec_info.sequence_changed)) { |
| 453 | 453 | dev_dbg(inst->dev->dev, "%s: finishing job.\n", __func__); |
| 454 | − pm_runtime_mark_last_busy(inst->dev->dev); | |
| 455 | 454 | pm_runtime_put_autosuspend(inst->dev->dev); |
| 456 | 455 | v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); |
| 457 | 456 | } |
| @@ -1364,7 +1363,6 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count · 906 unmodified lines | ||
| 1364 | 1363 | } |
| 1365 | 1364 | |
| 1366 | 1365 | } |
| 1367 | − pm_runtime_mark_last_busy(inst->dev->dev); | |
| 1368 | 1366 | pm_runtime_put_autosuspend(inst->dev->dev); |
| 1369 | 1367 | return ret; |
| 1370 | 1368 | |
| @@ -1498,7 +1496,6 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) · 127 unmodified lines | ||
| 1498 | 1496 | else |
| 1499 | 1497 | streamoff_capture(q); |
| 1500 | 1498 | |
| 1501 | − pm_runtime_mark_last_busy(inst->dev->dev); | |
| 1502 | 1499 | pm_runtime_put_autosuspend(inst->dev->dev); |
| 1503 | 1500 | } |
| 1504 | 1501 | |
| @@ -1662,7 +1659,6 @@ static void wave5_vpu_dec_device_run(void *priv) · 157 unmodified lines | ||
| 1662 | 1659 | |
| 1663 | 1660 | finish_job_and_return: |
| 1664 | 1661 | dev_dbg(inst->dev->dev, "%s: leave and finish job", __func__); |
| 1665 | − pm_runtime_mark_last_busy(inst->dev->dev); | |
| 1666 | 1662 | pm_runtime_put_autosuspend(inst->dev->dev); |
| 1667 | 1663 | v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); |
| 1668 | 1664 | } |
| @@ -1391,12 +1391,10 @@ static int wave5_vpu_enc_start_streaming(struct vb2_queue *q, unsigned int count · 1390 unmodified lines | ||
| 1391 | 1391 | if (ret) |
| 1392 | 1392 | goto return_buffers; |
| 1393 | 1393 | |
| 1394 | − pm_runtime_mark_last_busy(inst->dev->dev); | |
| 1395 | 1394 | pm_runtime_put_autosuspend(inst->dev->dev); |
| 1396 | 1395 | return 0; |
| 1397 | 1396 | return_buffers: |
| 1398 | 1397 | wave5_return_bufs(q, VB2_BUF_STATE_QUEUED); |
| 1399 | − pm_runtime_mark_last_busy(inst->dev->dev); | |
| 1400 | 1398 | pm_runtime_put_autosuspend(inst->dev->dev); |
| 1401 | 1399 | return ret; |
| 1402 | 1400 | } |
| @@ -1465,7 +1463,6 @@ static void wave5_vpu_enc_stop_streaming(struct vb2_queue *q) · 62 unmodified lines | ||
| 1465 | 1463 | else |
| 1466 | 1464 | streamoff_capture(inst, q); |
| 1467 | 1465 | |
| 1468 | − pm_runtime_mark_last_busy(inst->dev->dev); | |
| 1469 | 1466 | pm_runtime_put_autosuspend(inst->dev->dev); |
| 1470 | 1467 | } |
| 1471 | 1468 | |
| @@ -1520,7 +1517,6 @@ static void wave5_vpu_enc_device_run(void *priv) · 48 unmodified lines | ||
| 1520 | 1517 | break; |
| 1521 | 1518 | } |
| 1522 | 1519 | dev_dbg(inst->dev->dev, "%s: leave with active job", __func__); |
| 1523 | − pm_runtime_mark_last_busy(inst->dev->dev); | |
| 1524 | 1520 | pm_runtime_put_autosuspend(inst->dev->dev); |
| 1525 | 1521 | return; |
| 1526 | 1522 | default: |
| @@ -1529,7 +1525,6 @@ static void wave5_vpu_enc_device_run(void *priv) · 2 unmodified lines | ||
| 1529 | 1525 | break; |
| 1530 | 1526 | } |
| 1531 | 1527 | dev_dbg(inst->dev->dev, "%s: leave and finish job", __func__); |
| 1532 | − pm_runtime_mark_last_busy(inst->dev->dev); | |
| 1533 | 1528 | pm_runtime_put_autosuspend(inst->dev->dev); |
| 1534 | 1529 | v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); |
| 1535 | 1530 | } |
| @@ -585,7 +585,6 @@ static int tegra_vde_decode_begin(struct tegra_vde *vde, · 584 unmodified lines | ||
| 585 | 585 | return 0; |
| 586 | 586 | |
| 587 | 587 | put_runtime_pm: |
| 588 | − pm_runtime_mark_last_busy(dev); | |
| 589 | 588 | pm_runtime_put_autosuspend(dev); |
| 590 | 589 | |
| 591 | 590 | unlock: |
| @@ -612,7 +611,6 @@ static void tegra_vde_decode_abort(struct tegra_vde *vde) · 20 unmodified lines | ||
| 612 | 611 | if (err) |
| 613 | 612 | dev_err(dev, "DEC end: Failed to assert HW reset: %d\n", err); |
| 614 | 613 | |
| 615 | − pm_runtime_mark_last_busy(dev); | |
| 616 | 614 | pm_runtime_put_autosuspend(dev); |
| 617 | 615 | |
| 618 | 616 | mutex_unlock(&vde->lock); |
| @@ -142,7 +142,6 @@ int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size) · 141 unmodified lines | ||
| 142 | 142 | } |
| 143 | 143 | mutex_unlock(&core->lock); |
| 144 | 144 | |
| 145 | − pm_runtime_mark_last_busy(core->dev); | |
| 146 | 145 | pm_runtime_put_autosuspend(core->dev); |
| 147 | 146 | |
| 148 | 147 | return 0; |
| @@ -950,7 +950,6 @@ static void pispbe_node_stop_streaming(struct vb2_queue *q) · 949 unmodified lines | ||
| 950 | 950 | kfree(job); |
| 951 | 951 | } |
| 952 | 952 | |
| 953 | − pm_runtime_mark_last_busy(pispbe->dev); | |
| 954 | 953 | pm_runtime_put_autosuspend(pispbe->dev); |
| 955 | 954 | |
| 956 | 955 | dev_dbg(pispbe->dev, "Nodes streaming now 0x%x\n", |
| @@ -1742,7 +1741,6 @@ static int pispbe_probe(struct platform_device *pdev) · 785 unmodified lines | ||
| 1742 | 1741 | if (ret) |
| 1743 | 1742 | goto disable_devs_err; |
| 1744 | 1743 | |
| 1745 | − pm_runtime_mark_last_busy(pispbe->dev); | |
| 1746 | 1744 | pm_runtime_put_autosuspend(pispbe->dev); |
| 1747 | 1745 | |
| 1748 | 1746 | return 0; |
| @@ -765,7 +765,6 @@ static void rkvdec_job_finish(struct rkvdec_ctx *ctx, · 764 unmodified lines | ||
| 765 | 765 | { |
| 766 | 766 | struct rkvdec_dev *rkvdec = ctx->dev; |
| 767 | 767 | |
| 768 | − pm_runtime_mark_last_busy(rkvdec->dev); | |
| 769 | 768 | pm_runtime_put_autosuspend(rkvdec->dev); |
| 770 | 769 | rkvdec_job_finish_no_pm(ctx, result); |
| 771 | 770 | } |
| @@ -1159,13 +1158,6 @@ static int rkvdec_probe(struct platform_device *pdev) · 387 unmodified lines | ||
| 1159 | 1158 | return ret; |
| 1160 | 1159 | } |
| 1161 | 1160 | |
| 1162 | − if (iommu_get_domain_for_dev(&pdev->dev)) { | |
| 1163 | − rkvdec->empty_domain = iommu_paging_domain_alloc(rkvdec->dev); | |
| 1164 | − | |
| 1165 | − if (!rkvdec->empty_domain) | |
| 1166 | − dev_warn(rkvdec->dev, "cannot alloc new empty domain\n"); | |
| 1167 | − } | |
| 1168 | − | |
| 1169 | 1161 | vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); |
| 1170 | 1162 | |
| 1171 | 1163 | irq = platform_get_irq(pdev, 0); |
| @@ -1188,6 +1180,15 @@ static int rkvdec_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 1188 | 1180 | if (ret) |
| 1189 | 1181 | goto err_disable_runtime_pm; |
| 1190 | 1182 | |
| 1183 | + if (iommu_get_domain_for_dev(&pdev->dev)) { | |
| 1184 | + rkvdec->empty_domain = iommu_paging_domain_alloc(rkvdec->dev); | |
| 1185 | + | |
| 1186 | + if (IS_ERR(rkvdec->empty_domain)) { | |
| 1187 | + rkvdec->empty_domain = NULL; | |
| 1188 | + dev_warn(rkvdec->dev, "cannot alloc new empty domain\n"); | |
| 1189 | + } | |
| 1190 | + } | |
| 1191 | + | |
| 1191 | 1192 | return 0; |
| 1192 | 1193 | |
| 1193 | 1194 | err_disable_runtime_pm: |
| @@ -89,7 +89,6 @@ static void hantro_job_finish(struct hantro_dev *vpu, · 88 unmodified lines | ||
| 89 | 89 | struct hantro_ctx *ctx, |
| 90 | 90 | enum vb2_buffer_state result) |
| 91 | 91 | { |
| 92 | − pm_runtime_mark_last_busy(vpu->dev); | |
| 93 | 92 | pm_runtime_put_autosuspend(vpu->dev); |
| 94 | 93 | |
| 95 | 94 | clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks); |
| @@ -48,10 +48,8 @@ static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) · 47 unmodified lines | ||
| 48 | 48 | if (val >= 0) |
| 49 | 49 | ir_raw_event_store_edge(gpio_dev->rcdev, val == 1); |
| 50 | 50 | |
| 51 | − if (pmdev) { | |
| 52 | − pm_runtime_mark_last_busy(pmdev); | |
| 51 | + if (pmdev) | |
| 53 | 52 | pm_runtime_put_autosuspend(pmdev); |
| 54 | − } | |
| 55 | 53 | |
| 56 | 54 | return IRQ_HANDLED; |
| 57 | 55 | } |
| @@ -555,7 +555,6 @@ EXPORT_SYMBOL(memstick_add_host); · 554 unmodified lines | ||
| 555 | 555 | */ |
| 556 | 556 | void memstick_remove_host(struct memstick_host *host) |
| 557 | 557 | { |
| 558 | − host->removing = 1; | |
| 559 | 558 | flush_workqueue(workqueue); |
| 560 | 559 | mutex_lock(&host->lock); |
| 561 | 560 | if (host->card) |
| @@ -812,6 +812,7 @@ static void rtsx_usb_ms_drv_remove(struct platform_device *pdev) · 811 unmodified lines | ||
| 812 | 812 | int err; |
| 813 | 813 | |
| 814 | 814 | host->eject = true; |
| 815 | + msh->removing = true; | |
| 815 | 816 | cancel_work_sync(&host->handle_req); |
| 816 | 817 | cancel_delayed_work_sync(&host->poll_card); |
| 817 | 818 | |
| @@ -99,6 +99,9 @@ · 98 unmodified lines | ||
| 99 | 99 | #define HIWORD_UPDATE(val, mask, shift) \ |
| 100 | 100 | ((val) << (shift) | (mask) << ((shift) + 16)) |
| 101 | 101 | |
| 102 | +#define CD_STABLE_TIMEOUT_US 1000000 | |
| 103 | +#define CD_STABLE_MAX_SLEEP_US 10 | |
| 104 | + | |
| 102 | 105 | /** |
| 103 | 106 | * struct sdhci_arasan_soc_ctl_field - Field used in sdhci_arasan_soc_ctl_map |
| 104 | 107 | * |
| @@ -206,12 +209,15 @@ struct sdhci_arasan_data { · 101 unmodified lines | ||
| 206 | 209 | * 19MHz instead |
| 207 | 210 | */ |
| 208 | 211 | #define SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN BIT(2) |
| 212 | +/* Enable CD stable check before power-up */ | |
| 213 | +#define SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE BIT(3) | |
| 209 | 214 | }; |
| 210 | 215 | |
| 211 | 216 | struct sdhci_arasan_of_data { |
| 212 | 217 | const struct sdhci_arasan_soc_ctl_map *soc_ctl_map; |
| 213 | 218 | const struct sdhci_pltfm_data *pdata; |
| 214 | 219 | const struct sdhci_arasan_clk_ops *clk_ops; |
| 220 | + u32 quirks; | |
| 215 | 221 | }; |
| 216 | 222 | |
| 217 | 223 | static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = { |
| @@ -514,6 +520,24 @@ static int sdhci_arasan_voltage_switch(struct mmc_host *mmc, · 296 unmodified lines | ||
| 514 | 520 | return -EINVAL; |
| 515 | 521 | } |
| 516 | 522 | |
| 523 | +static void sdhci_arasan_set_power_and_bus_voltage(struct sdhci_host *host, unsigned char mode, | |
| 524 | + unsigned short vdd) | |
| 525 | +{ | |
| 526 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
| 527 | + struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); | |
| 528 | + u32 reg; | |
| 529 | + | |
| 530 | + /* | |
| 531 | + * Ensure that the card detect logic has stabilized before powering up, this is | |
| 532 | + * necessary after a host controller reset. | |
| 533 | + */ | |
| 534 | + if (mode == MMC_POWER_UP && sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE) | |
| 535 | + read_poll_timeout(sdhci_readl, reg, reg & SDHCI_CD_STABLE, CD_STABLE_MAX_SLEEP_US, | |
| 536 | + CD_STABLE_TIMEOUT_US, false, host, SDHCI_PRESENT_STATE); | |
| 537 | + | |
| 538 | + sdhci_set_power_and_bus_voltage(host, mode, vdd); | |
| 539 | +} | |
| 540 | + | |
| 517 | 541 | static const struct sdhci_ops sdhci_arasan_ops = { |
| 518 | 542 | .set_clock = sdhci_arasan_set_clock, |
| 519 | 543 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, |
| @@ -521,7 +545,7 @@ static const struct sdhci_ops sdhci_arasan_ops = { · 1 unmodified line | ||
| 521 | 545 | .set_bus_width = sdhci_set_bus_width, |
| 522 | 546 | .reset = sdhci_arasan_reset, |
| 523 | 547 | .set_uhs_signaling = sdhci_set_uhs_signaling, |
| 524 | − .set_power = sdhci_set_power_and_bus_voltage, | |
| 548 | + .set_power = sdhci_arasan_set_power_and_bus_voltage, | |
| 525 | 549 | .hw_reset = sdhci_arasan_hw_reset, |
| 526 | 550 | }; |
| 527 | 551 | |
| @@ -570,7 +594,7 @@ static const struct sdhci_ops sdhci_arasan_cqe_ops = { · 42 unmodified lines | ||
| 570 | 594 | .set_bus_width = sdhci_set_bus_width, |
| 571 | 595 | .reset = sdhci_arasan_reset, |
| 572 | 596 | .set_uhs_signaling = sdhci_set_uhs_signaling, |
| 573 | − .set_power = sdhci_set_power_and_bus_voltage, | |
| 597 | + .set_power = sdhci_arasan_set_power_and_bus_voltage, | |
| 574 | 598 | .irq = sdhci_arasan_cqhci_irq, |
| 575 | 599 | }; |
| 576 | 600 | |
| @@ -1447,6 +1471,7 @@ static const struct sdhci_arasan_clk_ops zynqmp_clk_ops = { · 870 unmodified lines | ||
| 1447 | 1471 | static struct sdhci_arasan_of_data sdhci_arasan_zynqmp_data = { |
| 1448 | 1472 | .pdata = &sdhci_arasan_zynqmp_pdata, |
| 1449 | 1473 | .clk_ops = &zynqmp_clk_ops, |
| 1474 | + .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE, | |
| 1450 | 1475 | }; |
| 1451 | 1476 | |
| 1452 | 1477 | static const struct sdhci_arasan_clk_ops versal_clk_ops = { |
| @@ -1457,6 +1482,7 @@ static const struct sdhci_arasan_clk_ops versal_clk_ops = { · 4 unmodified lines | ||
| 1457 | 1482 | static struct sdhci_arasan_of_data sdhci_arasan_versal_data = { |
| 1458 | 1483 | .pdata = &sdhci_arasan_zynqmp_pdata, |
| 1459 | 1484 | .clk_ops = &versal_clk_ops, |
| 1485 | + .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE, | |
| 1460 | 1486 | }; |
| 1461 | 1487 | |
| 1462 | 1488 | static const struct sdhci_arasan_clk_ops versal_net_clk_ops = { |
| @@ -1467,6 +1493,7 @@ static const struct sdhci_arasan_clk_ops versal_net_clk_ops = { · 4 unmodified lines | ||
| 1467 | 1493 | static struct sdhci_arasan_of_data sdhci_arasan_versal_net_data = { |
| 1468 | 1494 | .pdata = &sdhci_arasan_versal_net_pdata, |
| 1469 | 1495 | .clk_ops = &versal_net_clk_ops, |
| 1496 | + .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE, | |
| 1470 | 1497 | }; |
| 1471 | 1498 | |
| 1472 | 1499 | static struct sdhci_arasan_of_data intel_keembay_emmc_data = { |
| @@ -1937,6 +1964,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev) · 464 unmodified lines | ||
| 1937 | 1964 | if (of_device_is_compatible(np, "rockchip,rk3399-sdhci-5.1")) |
| 1938 | 1965 | sdhci_arasan_update_clockmultiplier(host, 0x0); |
| 1939 | 1966 | |
| 1967 | + sdhci_arasan->quirks |= data->quirks; | |
| 1968 | + | |
| 1940 | 1969 | if (of_device_is_compatible(np, "intel,keembay-sdhci-5.1-emmc") || |
| 1941 | 1970 | of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sd") || |
| 1942 | 1971 | of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sdio")) { |
| @@ -287,6 +287,20 @@ · 286 unmodified lines | ||
| 287 | 287 | #define GLI_MAX_TUNING_LOOP 40 |
| 288 | 288 | |
| 289 | 289 | /* Genesys Logic chipset */ |
| 290 | +static void sdhci_gli_mask_replay_timer_timeout(struct pci_dev *pdev) | |
| 291 | +{ | |
| 292 | + int aer; | |
| 293 | + u32 value; | |
| 294 | + | |
| 295 | + /* mask the replay timer timeout of AER */ | |
| 296 | + aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | |
| 297 | + if (aer) { | |
| 298 | + pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value); | |
| 299 | + value |= PCI_ERR_COR_REP_TIMER; | |
| 300 | + pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value); | |
| 301 | + } | |
| 302 | +} | |
| 303 | + | |
| 290 | 304 | static inline void gl9750_wt_on(struct sdhci_host *host) |
| 291 | 305 | { |
| 292 | 306 | u32 wt_value; |
| @@ -607,7 +621,6 @@ static void gl9750_hw_setting(struct sdhci_host *host) · 314 unmodified lines | ||
| 607 | 621 | { |
| 608 | 622 | struct sdhci_pci_slot *slot = sdhci_priv(host); |
| 609 | 623 | struct pci_dev *pdev; |
| 610 | − int aer; | |
| 611 | 624 | u32 value; |
| 612 | 625 | |
| 613 | 626 | pdev = slot->chip->pdev; |
| @@ -626,12 +639,7 @@ static void gl9750_hw_setting(struct sdhci_host *host) · 12 unmodified lines | ||
| 626 | 639 | pci_set_power_state(pdev, PCI_D0); |
| 627 | 640 | |
| 628 | 641 | /* mask the replay timer timeout of AER */ |
| 629 | − aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | |
| 630 | − if (aer) { | |
| 631 | − pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value); | |
| 632 | − value |= PCI_ERR_COR_REP_TIMER; | |
| 633 | − pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value); | |
| 634 | − } | |
| 642 | + sdhci_gli_mask_replay_timer_timeout(pdev); | |
| 635 | 643 | |
| 636 | 644 | gl9750_wt_off(host); |
| 637 | 645 | } |
| @@ -806,7 +814,6 @@ static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock) · 168 unmodified lines | ||
| 806 | 814 | static void gl9755_hw_setting(struct sdhci_pci_slot *slot) |
| 807 | 815 | { |
| 808 | 816 | struct pci_dev *pdev = slot->chip->pdev; |
| 809 | − int aer; | |
| 810 | 817 | u32 value; |
| 811 | 818 | |
| 812 | 819 | gl9755_wt_on(pdev); |
| @@ -841,12 +848,7 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot) · 28 unmodified lines | ||
| 841 | 848 | pci_set_power_state(pdev, PCI_D0); |
| 842 | 849 | |
| 843 | 850 | /* mask the replay timer timeout of AER */ |
| 844 | − aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | |
| 845 | − if (aer) { | |
| 846 | − pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value); | |
| 847 | − value |= PCI_ERR_COR_REP_TIMER; | |
| 848 | − pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value); | |
| 849 | − } | |
| 851 | + sdhci_gli_mask_replay_timer_timeout(pdev); | |
| 850 | 852 | |
| 851 | 853 | gl9755_wt_off(pdev); |
| 852 | 854 | } |
| @@ -1751,7 +1753,7 @@ cleanup: · 898 unmodified lines | ||
| 1751 | 1753 | return ret; |
| 1752 | 1754 | } |
| 1753 | 1755 | |
| 1754 | −static void gli_set_gl9763e(struct sdhci_pci_slot *slot) | |
| 1756 | +static void gl9763e_hw_setting(struct sdhci_pci_slot *slot) | |
| 1755 | 1757 | { |
| 1756 | 1758 | struct pci_dev *pdev = slot->chip->pdev; |
| 1757 | 1759 | u32 value; |
| @@ -1780,6 +1782,9 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot) · 22 unmodified lines | ||
| 1780 | 1782 | value |= FIELD_PREP(GLI_9763E_HS400_RXDLY, GLI_9763E_HS400_RXDLY_5); |
| 1781 | 1783 | pci_write_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, value); |
| 1782 | 1784 | |
| 1785 | + /* mask the replay timer timeout of AER */ | |
| 1786 | + sdhci_gli_mask_replay_timer_timeout(pdev); | |
| 1787 | + | |
| 1783 | 1788 | pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); |
| 1784 | 1789 | value &= ~GLI_9763E_VHS_REV; |
| 1785 | 1790 | value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); |
| @@ -1923,7 +1928,7 @@ static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) · 137 unmodified lines | ||
| 1923 | 1928 | gli_pcie_enable_msi(slot); |
| 1924 | 1929 | host->mmc_host_ops.hs400_enhanced_strobe = |
| 1925 | 1930 | gl9763e_hs400_enhanced_strobe; |
| 1926 | − gli_set_gl9763e(slot); | |
| 1931 | + gl9763e_hw_setting(slot); | |
| 1927 | 1932 | sdhci_enable_v4_mode(host); |
| 1928 | 1933 | |
| 1929 | 1934 | return 0; |
| @@ -156,6 +156,7 @@ struct sdhci_am654_data { · 155 unmodified lines | ||
| 156 | 156 | |
| 157 | 157 | #define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) |
| 158 | 158 | #define SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA BIT(1) |
| 159 | +#define SDHCI_AM654_QUIRK_DISABLE_HS400 BIT(2) | |
| 159 | 160 | }; |
| 160 | 161 | |
| 161 | 162 | struct window { |
| @@ -765,6 +766,7 @@ static int sdhci_am654_init(struct sdhci_host *host) · 603 unmodified lines | ||
| 765 | 766 | { |
| 766 | 767 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 767 | 768 | struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); |
| 769 | + struct device *dev = mmc_dev(host->mmc); | |
| 768 | 770 | u32 ctl_cfg_2 = 0; |
| 769 | 771 | u32 mask; |
| 770 | 772 | u32 val; |
| @@ -820,6 +822,12 @@ static int sdhci_am654_init(struct sdhci_host *host) · 49 unmodified lines | ||
| 820 | 822 | if (ret) |
| 821 | 823 | goto err_cleanup_host; |
| 822 | 824 | |
| 825 | + if (sdhci_am654->quirks & SDHCI_AM654_QUIRK_DISABLE_HS400 && | |
| 826 | + host->mmc->caps2 & (MMC_CAP2_HS400 | MMC_CAP2_HS400_ES)) { | |
| 827 | + dev_info(dev, "HS400 mode not supported on this silicon revision, disabling it\n"); | |
| 828 | + host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); | |
| 829 | + } | |
| 830 | + | |
| 823 | 831 | ret = __sdhci_add_host(host); |
| 824 | 832 | if (ret) |
| 825 | 833 | goto err_cleanup_host; |
| @@ -883,6 +891,12 @@ static int sdhci_am654_get_of_property(struct platform_device *pdev, · 57 unmodified lines | ||
| 883 | 891 | return 0; |
| 884 | 892 | } |
| 885 | 893 | |
| 894 | +static const struct soc_device_attribute sdhci_am654_descope_hs400[] = { | |
| 895 | + { .family = "AM62PX", .revision = "SR1.0" }, | |
| 896 | + { .family = "AM62PX", .revision = "SR1.1" }, | |
| 897 | + { /* sentinel */ } | |
| 898 | +}; | |
| 899 | + | |
| 886 | 900 | static const struct of_device_id sdhci_am654_of_match[] = { |
| 887 | 901 | { |
| 888 | 902 | .compatible = "ti,am654-sdhci-5.1", |
| @@ -970,6 +984,10 @@ static int sdhci_am654_probe(struct platform_device *pdev) · 81 unmodified lines | ||
| 970 | 984 | if (ret) |
| 971 | 985 | return dev_err_probe(dev, ret, "parsing dt failed\n"); |
| 972 | 986 | |
| 987 | + soc = soc_device_match(sdhci_am654_descope_hs400); | |
| 988 | + if (soc) | |
| 989 | + sdhci_am654->quirks |= SDHCI_AM654_QUIRK_DISABLE_HS400; | |
| 990 | + | |
| 973 | 991 | host->mmc_host_ops.start_signal_voltage_switch = sdhci_am654_start_signal_voltage_switch; |
| 974 | 992 | host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning; |
| 975 | 993 | |
| @@ -538,8 +538,8 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch) · 537 unmodified lines | ||
| 538 | 538 | dev = bus_find_device_by_name(&mostbus, NULL, mdev); |
| 539 | 539 | if (!dev) |
| 540 | 540 | return NULL; |
| 541 | − put_device(dev); | |
| 542 | 541 | iface = dev_get_drvdata(dev); |
| 542 | + put_device(dev); | |
| 543 | 543 | list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { |
| 544 | 544 | if (!strcmp(dev_name(&c->dev), mdev_ch)) |
| 545 | 545 | return c; |
| @@ -8022,7 +8022,8 @@ static int __bnxt_reserve_rings(struct bnxt *bp) · 8021 unmodified lines | ||
| 8022 | 8022 | } |
| 8023 | 8023 | rx_rings = min_t(int, rx_rings, hwr.grp); |
| 8024 | 8024 | hwr.cp = min_t(int, hwr.cp, bp->cp_nr_rings); |
| 8025 | − if (hwr.stat > bnxt_get_ulp_stat_ctxs(bp)) | |
| 8025 | + if (bnxt_ulp_registered(bp->edev) && | |
| 8026 | + hwr.stat > bnxt_get_ulp_stat_ctxs(bp)) | |
| 8026 | 8027 | hwr.stat -= bnxt_get_ulp_stat_ctxs(bp); |
| 8027 | 8028 | hwr.cp = min_t(int, hwr.cp, hwr.stat); |
| 8028 | 8029 | rc = bnxt_trim_rings(bp, &rx_rings, &hwr.tx, hwr.cp, sh); |
| @@ -8030,6 +8031,11 @@ static int __bnxt_reserve_rings(struct bnxt *bp) · 1 unmodified line | ||
| 8030 | 8031 | hwr.rx = rx_rings << 1; |
| 8031 | 8032 | tx_cp = bnxt_num_tx_to_cp(bp, hwr.tx); |
| 8032 | 8033 | hwr.cp = sh ? max_t(int, tx_cp, rx_rings) : tx_cp + rx_rings; |
| 8034 | + if (hwr.tx != bp->tx_nr_rings) { | |
| 8035 | + netdev_warn(bp->dev, | |
| 8036 | + "Able to reserve only %d out of %d requested TX rings\n", | |
| 8037 | + hwr.tx, bp->tx_nr_rings); | |
| 8038 | + } | |
| 8033 | 8039 | bp->tx_nr_rings = hwr.tx; |
| 8034 | 8040 | |
| 8035 | 8041 | /* If we cannot reserve all the RX rings, reset the RSS map only |
| @@ -12857,6 +12863,17 @@ static int bnxt_set_xps_mapping(struct bnxt *bp) · 4821 unmodified lines | ||
| 12857 | 12863 | return rc; |
| 12858 | 12864 | } |
| 12859 | 12865 | |
| 12866 | +static int bnxt_tx_nr_rings(struct bnxt *bp) | |
| 12867 | +{ | |
| 12868 | + return bp->num_tc ? bp->tx_nr_rings_per_tc * bp->num_tc : | |
| 12869 | + bp->tx_nr_rings_per_tc; | |
| 12870 | +} | |
| 12871 | + | |
| 12872 | +static int bnxt_tx_nr_rings_per_tc(struct bnxt *bp) | |
| 12873 | +{ | |
| 12874 | + return bp->num_tc ? bp->tx_nr_rings / bp->num_tc : bp->tx_nr_rings; | |
| 12875 | +} | |
| 12876 | + | |
| 12860 | 12877 | static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) |
| 12861 | 12878 | { |
| 12862 | 12879 | int rc = 0; |
| @@ -12874,6 +12891,13 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) · 11 unmodified lines | ||
| 12874 | 12891 | if (rc) |
| 12875 | 12892 | return rc; |
| 12876 | 12893 | |
| 12894 | + /* Make adjustments if reserved TX rings are less than requested */ | |
| 12895 | + bp->tx_nr_rings -= bp->tx_nr_rings_xdp; | |
| 12896 | + bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); | |
| 12897 | + if (bp->tx_nr_rings_xdp) { | |
| 12898 | + bp->tx_nr_rings_xdp = bp->tx_nr_rings_per_tc; | |
| 12899 | + bp->tx_nr_rings += bp->tx_nr_rings_xdp; | |
| 12900 | + } | |
| 12877 | 12901 | rc = bnxt_alloc_mem(bp, irq_re_init); |
| 12878 | 12902 | if (rc) { |
| 12879 | 12903 | netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc); |
| @@ -16329,7 +16353,7 @@ static void bnxt_trim_dflt_sh_rings(struct bnxt *bp) · 3449 unmodified lines | ||
| 16329 | 16353 | bp->cp_nr_rings = min_t(int, bp->tx_nr_rings_per_tc, bp->rx_nr_rings); |
| 16330 | 16354 | bp->rx_nr_rings = bp->cp_nr_rings; |
| 16331 | 16355 | bp->tx_nr_rings_per_tc = bp->cp_nr_rings; |
| 16332 | − bp->tx_nr_rings = bp->tx_nr_rings_per_tc; | |
| 16356 | + bp->tx_nr_rings = bnxt_tx_nr_rings(bp); | |
| 16333 | 16357 | } |
| 16334 | 16358 | |
| 16335 | 16359 | static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) |
| @@ -16361,7 +16385,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) · 25 unmodified lines | ||
| 16361 | 16385 | bnxt_trim_dflt_sh_rings(bp); |
| 16362 | 16386 | else |
| 16363 | 16387 | bp->cp_nr_rings = bp->tx_nr_rings_per_tc + bp->rx_nr_rings; |
| 16364 | − bp->tx_nr_rings = bp->tx_nr_rings_per_tc; | |
| 16388 | + bp->tx_nr_rings = bnxt_tx_nr_rings(bp); | |
| 16365 | 16389 | |
| 16366 | 16390 | avail_msix = bnxt_get_max_func_irqs(bp) - bp->cp_nr_rings; |
| 16367 | 16391 | if (avail_msix >= BNXT_MIN_ROCE_CP_RINGS) { |
| @@ -16374,7 +16398,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) · 6 unmodified lines | ||
| 16374 | 16398 | rc = __bnxt_reserve_rings(bp); |
| 16375 | 16399 | if (rc && rc != -ENODEV) |
| 16376 | 16400 | netdev_warn(bp->dev, "Unable to reserve tx rings\n"); |
| 16377 | − bp->tx_nr_rings_per_tc = bp->tx_nr_rings; | |
| 16401 | + bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); | |
| 16378 | 16402 | if (sh) |
| 16379 | 16403 | bnxt_trim_dflt_sh_rings(bp); |
| 16380 | 16404 | |
| @@ -16383,7 +16407,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) · 2 unmodified lines | ||
| 16383 | 16407 | rc = __bnxt_reserve_rings(bp); |
| 16384 | 16408 | if (rc && rc != -ENODEV) |
| 16385 | 16409 | netdev_warn(bp->dev, "2nd rings reservation failed.\n"); |
| 16386 | − bp->tx_nr_rings_per_tc = bp->tx_nr_rings; | |
| 16410 | + bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); | |
| 16387 | 16411 | } |
| 16388 | 16412 | if (BNXT_CHIP_TYPE_NITRO_A0(bp)) { |
| 16389 | 16413 | bp->rx_nr_rings++; |
| @@ -16417,7 +16441,7 @@ static int bnxt_init_dflt_ring_mode(struct bnxt *bp) · 27 unmodified lines | ||
| 16417 | 16441 | if (rc) |
| 16418 | 16442 | goto init_dflt_ring_err; |
| 16419 | 16443 | |
| 16420 | − bp->tx_nr_rings_per_tc = bp->tx_nr_rings; | |
| 16444 | + bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); | |
| 16421 | 16445 | |
| 16422 | 16446 | bnxt_set_dflt_rfs(bp); |
| 16423 | 16447 | |
| @@ -3091,7 +3091,7 @@ static void gem_update_stats(struct macb *bp) · 3090 unmodified lines | ||
| 3091 | 3091 | /* Add GEM_OCTTXH, GEM_OCTRXH */ |
| 3092 | 3092 | val = bp->macb_reg_readl(bp, offset + 4); |
| 3093 | 3093 | bp->ethtool_stats[i] += ((u64)val) << 32; |
| 3094 | − *(p++) += ((u64)val) << 32; | |
| 3094 | + *p += ((u64)val) << 32; | |
| 3095 | 3095 | } |
| 3096 | 3096 | } |
| 3097 | 3097 | |
| @@ -5636,19 +5636,16 @@ static void macb_remove(struct platform_device *pdev) · 2538 unmodified lines | ||
| 5636 | 5636 | |
| 5637 | 5637 | if (dev) { |
| 5638 | 5638 | bp = netdev_priv(dev); |
| 5639 | + unregister_netdev(dev); | |
| 5639 | 5640 | phy_exit(bp->sgmii_phy); |
| 5640 | 5641 | mdiobus_unregister(bp->mii_bus); |
| 5641 | 5642 | mdiobus_free(bp->mii_bus); |
| 5642 | 5643 | |
| 5643 | − unregister_netdev(dev); | |
| 5644 | + device_set_wakeup_enable(&bp->pdev->dev, 0); | |
| 5644 | 5645 | cancel_work_sync(&bp->hresp_err_bh_work); |
| 5645 | 5646 | pm_runtime_disable(&pdev->dev); |
| 5646 | 5647 | pm_runtime_dont_use_autosuspend(&pdev->dev); |
| 5647 | − if (!pm_runtime_suspended(&pdev->dev)) { | |
| 5648 | − macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, | |
| 5649 | − bp->rx_clk, bp->tsu_clk); | |
| 5650 | − pm_runtime_set_suspended(&pdev->dev); | |
| 5651 | − } | |
| 5648 | + pm_runtime_set_suspended(&pdev->dev); | |
| 5652 | 5649 | phylink_destroy(bp->phylink); |
| 5653 | 5650 | free_netdev(dev); |
| 5654 | 5651 | } |
| @@ -1099,7 +1099,7 @@ get_stats (struct net_device *dev) · 1098 unmodified lines | ||
| 1099 | 1099 | dev->stats.rx_bytes += dr32(OctetRcvOk); |
| 1100 | 1100 | dev->stats.tx_bytes += dr32(OctetXmtOk); |
| 1101 | 1101 | |
| 1102 | − dev->stats.multicast = dr32(McstFramesRcvdOk); | |
| 1102 | + dev->stats.multicast += dr32(McstFramesRcvdOk); | |
| 1103 | 1103 | dev->stats.collisions += dr32(SingleColFrames) |
| 1104 | 1104 | + dr32(MultiColFrames); |
| 1105 | 1105 | |
| @@ -511,6 +511,7 @@ enum ice_pf_flags { · 510 unmodified lines | ||
| 511 | 511 | ICE_FLAG_LINK_LENIENT_MODE_ENA, |
| 512 | 512 | ICE_FLAG_PLUG_AUX_DEV, |
| 513 | 513 | ICE_FLAG_UNPLUG_AUX_DEV, |
| 514 | + ICE_FLAG_AUX_DEV_CREATED, | |
| 514 | 515 | ICE_FLAG_MTU_CHANGED, |
| 515 | 516 | ICE_FLAG_GNSS, /* GNSS successfully initialized */ |
| 516 | 517 | ICE_FLAG_DPLL, /* SyncE/PTP dplls initialized */ |
| @@ -13,16 +13,45 @@ · 12 unmodified lines | ||
| 13 | 13 | static DEFINE_XARRAY(ice_adapters); |
| 14 | 14 | static DEFINE_MUTEX(ice_adapters_mutex); |
| 15 | 15 | |
| 16 | −static unsigned long ice_adapter_index(u64 dsn) | |
| 16 | +#define ICE_ADAPTER_FIXED_INDEX BIT_ULL(63) | |
| 17 | + | |
| 18 | +#define ICE_ADAPTER_INDEX_E825C \ | |
| 19 | + (ICE_DEV_ID_E825C_BACKPLANE | ICE_ADAPTER_FIXED_INDEX) | |
| 20 | + | |
| 21 | +static u64 ice_adapter_index(struct pci_dev *pdev) | |
| 17 | 22 | { |
| 23 | + switch (pdev->device) { | |
| 24 | + case ICE_DEV_ID_E825C_BACKPLANE: | |
| 25 | + case ICE_DEV_ID_E825C_QSFP: | |
| 26 | + case ICE_DEV_ID_E825C_SFP: | |
| 27 | + case ICE_DEV_ID_E825C_SGMII: | |
| 28 | + /* E825C devices have multiple NACs which are connected to the | |
| 29 | + * same clock source, and which must share the same | |
| 30 | + * ice_adapter structure. We can't use the serial number since | |
| 31 | + * each NAC has its own NVM generated with its own unique | |
| 32 | + * Device Serial Number. Instead, rely on the embedded nature | |
| 33 | + * of the E825C devices, and use a fixed index. This relies on | |
| 34 | + * the fact that all E825C physical functions in a given | |
| 35 | + * system are part of the same overall device. | |
| 36 | + */ | |
| 37 | + return ICE_ADAPTER_INDEX_E825C; | |
| 38 | + default: | |
| 39 | + return pci_get_dsn(pdev) & ~ICE_ADAPTER_FIXED_INDEX; | |
| 40 | + } | |
| 41 | +} | |
| 42 | + | |
| 43 | +static unsigned long ice_adapter_xa_index(struct pci_dev *pdev) | |
| 44 | +{ | |
| 45 | + u64 index = ice_adapter_index(pdev); | |
| 46 | + | |
| 18 | 47 | #if BITS_PER_LONG == 64 |
| 19 | − return dsn; | |
| 48 | + return index; | |
| 20 | 49 | #else |
| 21 | − return (u32)dsn ^ (u32)(dsn >> 32); | |
| 50 | + return (u32)index ^ (u32)(index >> 32); | |
| 22 | 51 | #endif |
| 23 | 52 | } |
| 24 | 53 | |
| 25 | −static struct ice_adapter *ice_adapter_new(u64 dsn) | |
| 54 | +static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev) | |
| 26 | 55 | { |
| 27 | 56 | struct ice_adapter *adapter; |
| 28 | 57 | |
| @@ -30,7 +59,7 @@ static struct ice_adapter *ice_adapter_new(u64 dsn) · 1 unmodified line | ||
| 30 | 59 | if (!adapter) |
| 31 | 60 | return NULL; |
| 32 | 61 | |
| 33 | − adapter->device_serial_number = dsn; | |
| 62 | + adapter->index = ice_adapter_index(pdev); | |
| 34 | 63 | spin_lock_init(&adapter->ptp_gltsyn_time_lock); |
| 35 | 64 | spin_lock_init(&adapter->txq_ctx_lock); |
| 36 | 65 | refcount_set(&adapter->refcount, 1); |
| @@ -64,24 +93,23 @@ static void ice_adapter_free(struct ice_adapter *adapter) · 27 unmodified lines | ||
| 64 | 93 | */ |
| 65 | 94 | struct ice_adapter *ice_adapter_get(struct pci_dev *pdev) |
| 66 | 95 | { |
| 67 | − u64 dsn = pci_get_dsn(pdev); | |
| 68 | 96 | struct ice_adapter *adapter; |
| 69 | 97 | unsigned long index; |
| 70 | 98 | int err; |
| 71 | 99 | |
| 72 | − index = ice_adapter_index(dsn); | |
| 100 | + index = ice_adapter_xa_index(pdev); | |
| 73 | 101 | scoped_guard(mutex, &ice_adapters_mutex) { |
| 74 | 102 | err = xa_insert(&ice_adapters, index, NULL, GFP_KERNEL); |
| 75 | 103 | if (err == -EBUSY) { |
| 76 | 104 | adapter = xa_load(&ice_adapters, index); |
| 77 | 105 | refcount_inc(&adapter->refcount); |
| 78 | − WARN_ON_ONCE(adapter->device_serial_number != dsn); | |
| 106 | + WARN_ON_ONCE(adapter->index != ice_adapter_index(pdev)); | |
| 79 | 107 | return adapter; |
| 80 | 108 | } |
| 81 | 109 | if (err) |
| 82 | 110 | return ERR_PTR(err); |
| 83 | 111 | |
| 84 | − adapter = ice_adapter_new(dsn); | |
| 112 | + adapter = ice_adapter_new(pdev); | |
| 85 | 113 | if (!adapter) |
| 86 | 114 | return ERR_PTR(-ENOMEM); |
| 87 | 115 | xa_store(&ice_adapters, index, adapter, GFP_KERNEL); |
| @@ -100,11 +128,10 @@ struct ice_adapter *ice_adapter_get(struct pci_dev *pdev) · 12 unmodified lines | ||
| 100 | 128 | */ |
| 101 | 129 | void ice_adapter_put(struct pci_dev *pdev) |
| 102 | 130 | { |
| 103 | − u64 dsn = pci_get_dsn(pdev); | |
| 104 | 131 | struct ice_adapter *adapter; |
| 105 | 132 | unsigned long index; |
| 106 | 133 | |
| 107 | − index = ice_adapter_index(dsn); | |
| 134 | + index = ice_adapter_xa_index(pdev); | |
| 108 | 135 | scoped_guard(mutex, &ice_adapters_mutex) { |
| 109 | 136 | adapter = xa_load(&ice_adapters, index); |
| 110 | 137 | if (WARN_ON(!adapter)) |
| @@ -33,7 +33,7 @@ struct ice_port_list { · 32 unmodified lines | ||
| 33 | 33 | * @txq_ctx_lock: Spinlock protecting access to the GLCOMM_QTX_CNTX_CTL register |
| 34 | 34 | * @ctrl_pf: Control PF of the adapter |
| 35 | 35 | * @ports: Ports list |
| 36 | − * @device_serial_number: DSN cached for collision detection on 32bit systems | |
| 36 | + * @index: 64-bit index cached for collision detection on 32bit systems | |
| 37 | 37 | */ |
| 38 | 38 | struct ice_adapter { |
| 39 | 39 | refcount_t refcount; |
| @@ -44,7 +44,7 @@ struct ice_adapter { · 4 unmodified lines | ||
| 44 | 44 | |
| 45 | 45 | struct ice_pf *ctrl_pf; |
| 46 | 46 | struct ice_port_list ports; |
| 47 | − u64 device_serial_number; | |
| 47 | + u64 index; | |
| 48 | 48 | }; |
| 49 | 49 | |
| 50 | 50 | struct ice_adapter *ice_adapter_get(struct pci_dev *pdev); |
| @@ -2377,7 +2377,13 @@ ice_get_set_tx_topo(struct ice_hw *hw, u8 *buf, u16 buf_size, · 2376 unmodified lines | ||
| 2377 | 2377 | * The function will apply the new Tx topology from the package buffer |
| 2378 | 2378 | * if available. |
| 2379 | 2379 | * |
| 2380 | − * Return: zero when update was successful, negative values otherwise. | |
| 2380 | + * Return: | |
| 2381 | + * * 0 - Successfully applied topology configuration. | |
| 2382 | + * * -EBUSY - Failed to acquire global configuration lock. | |
| 2383 | + * * -EEXIST - Topology configuration has already been applied. | |
| 2384 | + * * -EIO - Unable to apply topology configuration. | |
| 2385 | + * * -ENODEV - Failed to re-initialize device after applying configuration. | |
| 2386 | + * * Other negative error codes indicate unexpected failures. | |
| 2381 | 2387 | */ |
| 2382 | 2388 | int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) |
| 2383 | 2389 | { |
| @@ -2410,7 +2416,7 @@ int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) · 26 unmodified lines | ||
| 2410 | 2416 | |
| 2411 | 2417 | if (status) { |
| 2412 | 2418 | ice_debug(hw, ICE_DBG_INIT, "Get current topology is failed\n"); |
| 2413 | − return status; | |
| 2419 | + return -EIO; | |
| 2414 | 2420 | } |
| 2415 | 2421 | |
| 2416 | 2422 | /* Is default topology already applied ? */ |
| @@ -2497,31 +2503,45 @@ update_topo: · 80 unmodified lines | ||
| 2497 | 2503 | ICE_GLOBAL_CFG_LOCK_TIMEOUT); |
| 2498 | 2504 | if (status) { |
| 2499 | 2505 | ice_debug(hw, ICE_DBG_INIT, "Failed to acquire global lock\n"); |
| 2500 | − return status; | |
| 2506 | + return -EBUSY; | |
| 2501 | 2507 | } |
| 2502 | 2508 | |
| 2503 | 2509 | /* Check if reset was triggered already. */ |
| 2504 | 2510 | reg = rd32(hw, GLGEN_RSTAT); |
| 2505 | 2511 | if (reg & GLGEN_RSTAT_DEVSTATE_M) { |
| 2506 | − /* Reset is in progress, re-init the HW again */ | |
| 2507 | 2512 | ice_debug(hw, ICE_DBG_INIT, "Reset is in progress. Layer topology might be applied already\n"); |
| 2508 | 2513 | ice_check_reset(hw); |
| 2509 | − return 0; | |
| 2514 | + /* Reset is in progress, re-init the HW again */ | |
| 2515 | + goto reinit_hw; | |
| 2510 | 2516 | } |
| 2511 | 2517 | |
| 2512 | 2518 | /* Set new topology */ |
| 2513 | 2519 | status = ice_get_set_tx_topo(hw, new_topo, size, NULL, NULL, true); |
| 2514 | 2520 | if (status) { |
| 2515 | − ice_debug(hw, ICE_DBG_INIT, "Failed setting Tx topology\n"); | |
| 2516 | − return status; | |
| 2521 | + ice_debug(hw, ICE_DBG_INIT, "Failed to set Tx topology, status %pe\n", | |
| 2522 | + ERR_PTR(status)); | |
| 2523 | + /* only report -EIO here as the caller checks the error value | |
| 2524 | + * and reports an informational error message informing that | |
| 2525 | + * the driver failed to program Tx topology. | |
| 2526 | + */ | |
| 2527 | + status = -EIO; | |
| 2517 | 2528 | } |
| 2518 | 2529 | |
| 2519 | − /* New topology is updated, delay 1 second before issuing the CORER */ | |
| 2530 | + /* Even if Tx topology config failed, we need to CORE reset here to | |
| 2531 | + * clear the global configuration lock. Delay 1 second to allow | |
| 2532 | + * hardware to settle then issue a CORER | |
| 2533 | + */ | |
| 2520 | 2534 | msleep(1000); |
| 2521 | 2535 | ice_reset(hw, ICE_RESET_CORER); |
| 2522 | − /* CORER will clear the global lock, so no explicit call | |
| 2523 | − * required for release. | |
| 2524 | − */ | |
| 2536 | + ice_check_reset(hw); | |
| 2537 | + | |
| 2538 | +reinit_hw: | |
| 2539 | + /* Since we triggered a CORER, re-initialize hardware */ | |
| 2540 | + ice_deinit_hw(hw); | |
| 2541 | + if (ice_init_hw(hw)) { | |
| 2542 | + ice_debug(hw, ICE_DBG_INIT, "Failed to re-init hardware after setting Tx topology\n"); | |
| 2543 | + return -ENODEV; | |
| 2544 | + } | |
| 2525 | 2545 | |
| 2526 | − return 0; | |
| 2546 | + return status; | |
| 2527 | 2547 | } |
| @@ -336,6 +336,7 @@ int ice_plug_aux_dev(struct ice_pf *pf) · 335 unmodified lines | ||
| 336 | 336 | mutex_lock(&pf->adev_mutex); |
| 337 | 337 | cdev->adev = adev; |
| 338 | 338 | mutex_unlock(&pf->adev_mutex); |
| 339 | + set_bit(ICE_FLAG_AUX_DEV_CREATED, pf->flags); | |
| 339 | 340 | |
| 340 | 341 | return 0; |
| 341 | 342 | } |
| @@ -347,15 +348,16 @@ void ice_unplug_aux_dev(struct ice_pf *pf) · 5 unmodified lines | ||
| 347 | 348 | { |
| 348 | 349 | struct auxiliary_device *adev; |
| 349 | 350 | |
| 351 | + if (!test_and_clear_bit(ICE_FLAG_AUX_DEV_CREATED, pf->flags)) | |
| 352 | + return; | |
| 353 | + | |
| 350 | 354 | mutex_lock(&pf->adev_mutex); |
| 351 | 355 | adev = pf->cdev_info->adev; |
| 352 | 356 | pf->cdev_info->adev = NULL; |
| 353 | 357 | mutex_unlock(&pf->adev_mutex); |
| 354 | 358 | |
| 355 | − if (adev) { | |
| 356 | − auxiliary_device_delete(adev); | |
| 357 | − auxiliary_device_uninit(adev); | |
| 358 | − } | |
| 359 | + auxiliary_device_delete(adev); | |
| 360 | + auxiliary_device_uninit(adev); | |
| 359 | 361 | } |
| 360 | 362 | |
| 361 | 363 | /** |
| @@ -4536,17 +4536,23 @@ ice_init_tx_topology(struct ice_hw *hw, const struct firmware *firmware) · 4535 unmodified lines | ||
| 4536 | 4536 | dev_info(dev, "Tx scheduling layers switching feature disabled\n"); |
| 4537 | 4537 | else |
| 4538 | 4538 | dev_info(dev, "Tx scheduling layers switching feature enabled\n"); |
| 4539 | − /* if there was a change in topology ice_cfg_tx_topo triggered | |
| 4540 | − * a CORER and we need to re-init hw | |
| 4539 | + return 0; | |
| 4540 | + } else if (err == -ENODEV) { | |
| 4541 | + /* If we failed to re-initialize the device, we can no longer | |
| 4542 | + * continue loading. | |
| 4541 | 4543 | */ |
| 4542 | − ice_deinit_hw(hw); | |
| 4543 | − err = ice_init_hw(hw); | |
| 4544 | − | |
| 4544 | + dev_warn(dev, "Failed to initialize hardware after applying Tx scheduling configuration.\n"); | |
| 4545 | 4545 | return err; |
| 4546 | 4546 | } else if (err == -EIO) { |
| 4547 | 4547 | dev_info(dev, "DDP package does not support Tx scheduling layers switching feature - please update to the latest DDP package and try again\n"); |
| 4548 | + return 0; | |
| 4549 | + } else if (err == -EEXIST) { | |
| 4550 | + return 0; | |
| 4548 | 4551 | } |
| 4549 | 4552 | |
| 4553 | + /* Do not treat this as a fatal error. */ | |
| 4554 | + dev_info(dev, "Failed to apply Tx scheduling configuration, err %pe\n", | |
| 4555 | + ERR_PTR(err)); | |
| 4550 | 4556 | return 0; |
| 4551 | 4557 | } |
| 4552 | 4558 | |
| @@ -1352,7 +1352,7 @@ construct_skb: · 1351 unmodified lines | ||
| 1352 | 1352 | skb = ice_construct_skb(rx_ring, xdp); |
| 1353 | 1353 | /* exit if we failed to retrieve a buffer */ |
| 1354 | 1354 | if (!skb) { |
| 1355 | − rx_ring->ring_stats->rx_stats.alloc_page_failed++; | |
| 1355 | + rx_ring->ring_stats->rx_stats.alloc_buf_failed++; | |
| 1356 | 1356 | xdp_verdict = ICE_XDP_CONSUMED; |
| 1357 | 1357 | } |
| 1358 | 1358 | ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); |
| @@ -179,6 +179,58 @@ static int idpf_tx_singleq_csum(struct sk_buff *skb, · 178 unmodified lines | ||
| 179 | 179 | return 1; |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | +/** | |
| 183 | + * idpf_tx_singleq_dma_map_error - handle TX DMA map errors | |
| 184 | + * @txq: queue to send buffer on | |
| 185 | + * @skb: send buffer | |
| 186 | + * @first: original first buffer info buffer for packet | |
| 187 | + * @idx: starting point on ring to unwind | |
| 188 | + */ | |
| 189 | +static void idpf_tx_singleq_dma_map_error(struct idpf_tx_queue *txq, | |
| 190 | + struct sk_buff *skb, | |
| 191 | + struct idpf_tx_buf *first, u16 idx) | |
| 192 | +{ | |
| 193 | + struct libeth_sq_napi_stats ss = { }; | |
| 194 | + struct libeth_cq_pp cp = { | |
| 195 | + .dev = txq->dev, | |
| 196 | + .ss = &ss, | |
| 197 | + }; | |
| 198 | + | |
| 199 | + u64_stats_update_begin(&txq->stats_sync); | |
| 200 | + u64_stats_inc(&txq->q_stats.dma_map_errs); | |
| 201 | + u64_stats_update_end(&txq->stats_sync); | |
| 202 | + | |
| 203 | + /* clear dma mappings for failed tx_buf map */ | |
| 204 | + for (;;) { | |
| 205 | + struct idpf_tx_buf *tx_buf; | |
| 206 | + | |
| 207 | + tx_buf = &txq->tx_buf[idx]; | |
| 208 | + libeth_tx_complete(tx_buf, &cp); | |
| 209 | + if (tx_buf == first) | |
| 210 | + break; | |
| 211 | + if (idx == 0) | |
| 212 | + idx = txq->desc_count; | |
| 213 | + idx--; | |
| 214 | + } | |
| 215 | + | |
| 216 | + if (skb_is_gso(skb)) { | |
| 217 | + union idpf_tx_flex_desc *tx_desc; | |
| 218 | + | |
| 219 | + /* If we failed a DMA mapping for a TSO packet, we will have | |
| 220 | + * used one additional descriptor for a context | |
| 221 | + * descriptor. Reset that here. | |
| 222 | + */ | |
| 223 | + tx_desc = &txq->flex_tx[idx]; | |
| 224 | + memset(tx_desc, 0, sizeof(*tx_desc)); | |
| 225 | + if (idx == 0) | |
| 226 | + idx = txq->desc_count; | |
| 227 | + idx--; | |
| 228 | + } | |
| 229 | + | |
| 230 | + /* Update tail in case netdev_xmit_more was previously true */ | |
| 231 | + idpf_tx_buf_hw_update(txq, idx, false); | |
| 232 | +} | |
| 233 | + | |
| 182 | 234 | /** |
| 183 | 235 | * idpf_tx_singleq_map - Build the Tx base descriptor |
| 184 | 236 | * @tx_q: queue to send buffer on |
| @@ -219,8 +271,9 @@ static void idpf_tx_singleq_map(struct idpf_tx_queue *tx_q, · 34 unmodified lines | ||
| 219 | 271 | for (frag = &skb_shinfo(skb)->frags[0];; frag++) { |
| 220 | 272 | unsigned int max_data = IDPF_TX_MAX_DESC_DATA_ALIGNED; |
| 221 | 273 | |
| 222 | − if (dma_mapping_error(tx_q->dev, dma)) | |
| 223 | − return idpf_tx_dma_map_error(tx_q, skb, first, i); | |
| 274 | + if (unlikely(dma_mapping_error(tx_q->dev, dma))) | |
| 275 | + return idpf_tx_singleq_dma_map_error(tx_q, skb, | |
| 276 | + first, i); | |
| 224 | 277 | |
| 225 | 278 | /* record length, and DMA address */ |
| 226 | 279 | dma_unmap_len_set(tx_buf, len, size); |
| @@ -362,11 +415,11 @@ netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, · 135 unmodified lines | ||
| 362 | 415 | { |
| 363 | 416 | struct idpf_tx_offload_params offload = { }; |
| 364 | 417 | struct idpf_tx_buf *first; |
| 418 | + u32 count, buf_count = 1; | |
| 365 | 419 | int csum, tso, needed; |
| 366 | − unsigned int count; | |
| 367 | 420 | __be16 protocol; |
| 368 | 421 | |
| 369 | − count = idpf_tx_desc_count_required(tx_q, skb); | |
| 422 | + count = idpf_tx_res_count_required(tx_q, skb, &buf_count); | |
| 370 | 423 | if (unlikely(!count)) |
| 371 | 424 | return idpf_tx_drop_skb(tx_q, skb); |
| 372 | 425 | |
| @@ -8,12 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include "idpf_ptp.h" |
| 9 | 9 | #include "idpf_virtchnl.h" |
| 10 | 10 | |
| 11 | −struct idpf_tx_stash { | |
| 12 | − struct hlist_node hlist; | |
| 13 | − struct libeth_sqe buf; | |
| 14 | −}; | |
| 15 | − | |
| 16 | −#define idpf_tx_buf_compl_tag(buf) (*(u32 *)&(buf)->priv) | |
| 11 | +#define idpf_tx_buf_next(buf) (*(u32 *)&(buf)->priv) | |
| 17 | 12 | LIBETH_SQE_CHECK_PRIV(u32); |
| 18 | 13 | |
| 19 | 14 | /** |
| @@ -39,36 +34,6 @@ static bool idpf_chk_linearize(const struct sk_buff *skb, · 19 unmodified lines | ||
| 39 | 34 | return true; |
| 40 | 35 | } |
| 41 | 36 | |
| 42 | −/** | |
| 43 | − * idpf_buf_lifo_push - push a buffer pointer onto stack | |
| 44 | − * @stack: pointer to stack struct | |
| 45 | − * @buf: pointer to buf to push | |
| 46 | − * | |
| 47 | − * Returns 0 on success, negative on failure | |
| 48 | − **/ | |
| 49 | −static int idpf_buf_lifo_push(struct idpf_buf_lifo *stack, | |
| 50 | − struct idpf_tx_stash *buf) | |
| 51 | −{ | |
| 52 | − if (unlikely(stack->top == stack->size)) | |
| 53 | − return -ENOSPC; | |
| 54 | − | |
| 55 | − stack->bufs[stack->top++] = buf; | |
| 56 | − | |
| 57 | − return 0; | |
| 58 | −} | |
| 59 | − | |
| 60 | −/** | |
| 61 | − * idpf_buf_lifo_pop - pop a buffer pointer from stack | |
| 62 | − * @stack: pointer to stack struct | |
| 63 | − **/ | |
| 64 | −static struct idpf_tx_stash *idpf_buf_lifo_pop(struct idpf_buf_lifo *stack) | |
| 65 | −{ | |
| 66 | − if (unlikely(!stack->top)) | |
| 67 | − return NULL; | |
| 68 | − | |
| 69 | − return stack->bufs[--stack->top]; | |
| 70 | −} | |
| 71 | − | |
| 72 | 37 | /** |
| 73 | 38 | * idpf_tx_timeout - Respond to a Tx Hang |
| 74 | 39 | * @netdev: network interface device structure |
| @@ -97,52 +62,22 @@ void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue) · 22 unmodified lines | ||
| 97 | 62 | static void idpf_tx_buf_rel_all(struct idpf_tx_queue *txq) |
| 98 | 63 | { |
| 99 | 64 | struct libeth_sq_napi_stats ss = { }; |
| 100 | − struct idpf_buf_lifo *buf_stack; | |
| 101 | − struct idpf_tx_stash *stash; | |
| 102 | 65 | struct libeth_cq_pp cp = { |
| 103 | 66 | .dev = txq->dev, |
| 104 | 67 | .ss = &ss, |
| 105 | 68 | }; |
| 106 | − struct hlist_node *tmp; | |
| 107 | − u32 i, tag; | |
| 69 | + u32 i; | |
| 108 | 70 | |
| 109 | 71 | /* Buffers already cleared, nothing to do */ |
| 110 | 72 | if (!txq->tx_buf) |
| 111 | 73 | return; |
| 112 | 74 | |
| 113 | 75 | /* Free all the Tx buffer sk_buffs */ |
| 114 | − for (i = 0; i < txq->desc_count; i++) | |
| 76 | + for (i = 0; i < txq->buf_pool_size; i++) | |
| 115 | 77 | libeth_tx_complete(&txq->tx_buf[i], &cp); |
| 116 | 78 | |
| 117 | 79 | kfree(txq->tx_buf); |
| 118 | 80 | txq->tx_buf = NULL; |
| 119 | − | |
| 120 | − if (!idpf_queue_has(FLOW_SCH_EN, txq)) | |
| 121 | − return; | |
| 122 | − | |
| 123 | − buf_stack = &txq->stash->buf_stack; | |
| 124 | − if (!buf_stack->bufs) | |
| 125 | − return; | |
| 126 | − | |
| 127 | − /* | |
| 128 | − * If a Tx timeout occurred, there are potentially still bufs in the | |
| 129 | − * hash table, free them here. | |
| 130 | − */ | |
| 131 | − hash_for_each_safe(txq->stash->sched_buf_hash, tag, tmp, stash, | |
| 132 | − hlist) { | |
| 133 | − if (!stash) | |
| 134 | − continue; | |
| 135 | − | |
| 136 | − libeth_tx_complete(&stash->buf, &cp); | |
| 137 | − hash_del(&stash->hlist); | |
| 138 | − idpf_buf_lifo_push(buf_stack, stash); | |
| 139 | − } | |
| 140 | − | |
| 141 | − for (i = 0; i < buf_stack->size; i++) | |
| 142 | − kfree(buf_stack->bufs[i]); | |
| 143 | − | |
| 144 | − kfree(buf_stack->bufs); | |
| 145 | − buf_stack->bufs = NULL; | |
| 146 | 81 | } |
| 147 | 82 | |
| 148 | 83 | /** |
| @@ -159,6 +94,9 @@ static void idpf_tx_desc_rel(struct idpf_tx_queue *txq) · 10 unmodified lines | ||
| 159 | 94 | if (!txq->desc_ring) |
| 160 | 95 | return; |
| 161 | 96 | |
| 97 | + if (txq->refillq) | |
| 98 | + kfree(txq->refillq->ring); | |
| 99 | + | |
| 162 | 100 | dmam_free_coherent(txq->dev, txq->size, txq->desc_ring, txq->dma); |
| 163 | 101 | txq->desc_ring = NULL; |
| 164 | 102 | txq->next_to_use = 0; |
| @@ -215,41 +153,18 @@ static void idpf_tx_desc_rel_all(struct idpf_vport *vport) · 50 unmodified lines | ||
| 215 | 153 | */ |
| 216 | 154 | static int idpf_tx_buf_alloc_all(struct idpf_tx_queue *tx_q) |
| 217 | 155 | { |
| 218 | − struct idpf_buf_lifo *buf_stack; | |
| 219 | − int buf_size; | |
| 220 | − int i; | |
| 221 | − | |
| 222 | 156 | /* Allocate book keeping buffers only. Buffers to be supplied to HW |
| 223 | 157 | * are allocated by kernel network stack and received as part of skb |
| 224 | 158 | */ |
| 225 | − buf_size = sizeof(struct idpf_tx_buf) * tx_q->desc_count; | |
| 226 | − tx_q->tx_buf = kzalloc(buf_size, GFP_KERNEL); | |
| 159 | + if (idpf_queue_has(FLOW_SCH_EN, tx_q)) | |
| 160 | + tx_q->buf_pool_size = U16_MAX; | |
| 161 | + else | |
| 162 | + tx_q->buf_pool_size = tx_q->desc_count; | |
| 163 | + tx_q->tx_buf = kcalloc(tx_q->buf_pool_size, sizeof(*tx_q->tx_buf), | |
| 164 | + GFP_KERNEL); | |
| 227 | 165 | if (!tx_q->tx_buf) |
| 228 | 166 | return -ENOMEM; |
| 229 | 167 | |
| 230 | − if (!idpf_queue_has(FLOW_SCH_EN, tx_q)) | |
| 231 | − return 0; | |
| 232 | − | |
| 233 | − buf_stack = &tx_q->stash->buf_stack; | |
| 234 | − | |
| 235 | − /* Initialize tx buf stack for out-of-order completions if | |
| 236 | − * flow scheduling offload is enabled | |
| 237 | − */ | |
| 238 | − buf_stack->bufs = kcalloc(tx_q->desc_count, sizeof(*buf_stack->bufs), | |
| 239 | − GFP_KERNEL); | |
| 240 | − if (!buf_stack->bufs) | |
| 241 | − return -ENOMEM; | |
| 242 | − | |
| 243 | − buf_stack->size = tx_q->desc_count; | |
| 244 | − buf_stack->top = tx_q->desc_count; | |
| 245 | − | |
| 246 | − for (i = 0; i < tx_q->desc_count; i++) { | |
| 247 | − buf_stack->bufs[i] = kzalloc(sizeof(*buf_stack->bufs[i]), | |
| 248 | − GFP_KERNEL); | |
| 249 | − if (!buf_stack->bufs[i]) | |
| 250 | − return -ENOMEM; | |
| 251 | − } | |
| 252 | − | |
| 253 | 168 | return 0; |
| 254 | 169 | } |
| 255 | 170 | |
| @@ -264,6 +179,7 @@ static int idpf_tx_desc_alloc(const struct idpf_vport *vport, · 8 unmodified lines | ||
| 264 | 179 | struct idpf_tx_queue *tx_q) |
| 265 | 180 | { |
| 266 | 181 | struct device *dev = tx_q->dev; |
| 182 | + struct idpf_sw_queue *refillq; | |
| 267 | 183 | int err; |
| 268 | 184 | |
| 269 | 185 | err = idpf_tx_buf_alloc_all(tx_q); |
| @@ -287,6 +203,31 @@ static int idpf_tx_desc_alloc(const struct idpf_vport *vport, · 17 unmodified lines | ||
| 287 | 203 | tx_q->next_to_clean = 0; |
| 288 | 204 | idpf_queue_set(GEN_CHK, tx_q); |
| 289 | 205 | |
| 206 | + if (!idpf_queue_has(FLOW_SCH_EN, tx_q)) | |
| 207 | + return 0; | |
| 208 | + | |
| 209 | + refillq = tx_q->refillq; | |
| 210 | + refillq->desc_count = tx_q->buf_pool_size; | |
| 211 | + refillq->ring = kcalloc(refillq->desc_count, sizeof(u32), | |
| 212 | + GFP_KERNEL); | |
| 213 | + if (!refillq->ring) { | |
| 214 | + err = -ENOMEM; | |
| 215 | + goto err_alloc; | |
| 216 | + } | |
| 217 | + | |
| 218 | + for (unsigned int i = 0; i < refillq->desc_count; i++) | |
| 219 | + refillq->ring[i] = | |
| 220 | + FIELD_PREP(IDPF_RFL_BI_BUFID_M, i) | | |
| 221 | + FIELD_PREP(IDPF_RFL_BI_GEN_M, | |
| 222 | + idpf_queue_has(GEN_CHK, refillq)); | |
| 223 | + | |
| 224 | + /* Go ahead and flip the GEN bit since this counts as filling | |
| 225 | + * up the ring, i.e. we already ring wrapped. | |
| 226 | + */ | |
| 227 | + idpf_queue_change(GEN_CHK, refillq); | |
| 228 | + | |
| 229 | + tx_q->last_re = tx_q->desc_count - IDPF_TX_SPLITQ_RE_MIN_GAP; | |
| 230 | + | |
| 290 | 231 | return 0; |
| 291 | 232 | |
| 292 | 233 | err_alloc: |
| @@ -337,8 +278,6 @@ static int idpf_tx_desc_alloc_all(struct idpf_vport *vport) · 44 unmodified lines | ||
| 337 | 278 | for (i = 0; i < vport->num_txq_grp; i++) { |
| 338 | 279 | for (j = 0; j < vport->txq_grps[i].num_txq; j++) { |
| 339 | 280 | struct idpf_tx_queue *txq = vport->txq_grps[i].txqs[j]; |
| 340 | − u8 gen_bits = 0; | |
| 341 | − u16 bufidx_mask; | |
| 342 | 281 | |
| 343 | 282 | err = idpf_tx_desc_alloc(vport, txq); |
| 344 | 283 | if (err) { |
| @@ -347,34 +286,6 @@ static int idpf_tx_desc_alloc_all(struct idpf_vport *vport) · 2 unmodified lines | ||
| 347 | 286 | i); |
| 348 | 287 | goto err_out; |
| 349 | 288 | } |
| 350 | − | |
| 351 | − if (!idpf_is_queue_model_split(vport->txq_model)) | |
| 352 | − continue; | |
| 353 | − | |
| 354 | − txq->compl_tag_cur_gen = 0; | |
| 355 | − | |
| 356 | − /* Determine the number of bits in the bufid | |
| 357 | − * mask and add one to get the start of the | |
| 358 | − * generation bits | |
| 359 | − */ | |
| 360 | − bufidx_mask = txq->desc_count - 1; | |
| 361 | − while (bufidx_mask >> 1) { | |
| 362 | − txq->compl_tag_gen_s++; | |
| 363 | − bufidx_mask = bufidx_mask >> 1; | |
| 364 | − } | |
| 365 | − txq->compl_tag_gen_s++; | |
| 366 | − | |
| 367 | − gen_bits = IDPF_TX_SPLITQ_COMPL_TAG_WIDTH - | |
| 368 | − txq->compl_tag_gen_s; | |
| 369 | − txq->compl_tag_gen_max = GETMAXVAL(gen_bits); | |
| 370 | − | |
| 371 | − /* Set bufid mask based on location of first | |
| 372 | − * gen bit; it cannot simply be the descriptor | |
| 373 | − * ring size-1 since we can have size values | |
| 374 | − * where not all of those bits are set. | |
| 375 | − */ | |
| 376 | − txq->compl_tag_bufid_m = | |
| 377 | − GETMAXVAL(txq->compl_tag_gen_s); | |
| 378 | 289 | } |
| 379 | 290 | |
| 380 | 291 | if (!idpf_is_queue_model_split(vport->txq_model)) |
| @@ -623,18 +534,18 @@ static int idpf_rx_hdr_buf_alloc_all(struct idpf_buf_queue *bufq) · 242 unmodified lines | ||
| 623 | 534 | } |
| 624 | 535 | |
| 625 | 536 | /** |
| 626 | − * idpf_rx_post_buf_refill - Post buffer id to refill queue | |
| 537 | + * idpf_post_buf_refill - Post buffer id to refill queue | |
| 627 | 538 | * @refillq: refill queue to post to |
| 628 | 539 | * @buf_id: buffer id to post |
| 629 | 540 | */ |
| 630 | −static void idpf_rx_post_buf_refill(struct idpf_sw_queue *refillq, u16 buf_id) | |
| 541 | +static void idpf_post_buf_refill(struct idpf_sw_queue *refillq, u16 buf_id) | |
| 631 | 542 | { |
| 632 | 543 | u32 nta = refillq->next_to_use; |
| 633 | 544 | |
| 634 | 545 | /* store the buffer ID and the SW maintained GEN bit to the refillq */ |
| 635 | 546 | refillq->ring[nta] = |
| 636 | − FIELD_PREP(IDPF_RX_BI_BUFID_M, buf_id) | | |
| 637 | − FIELD_PREP(IDPF_RX_BI_GEN_M, | |
| 547 | + FIELD_PREP(IDPF_RFL_BI_BUFID_M, buf_id) | | |
| 548 | + FIELD_PREP(IDPF_RFL_BI_GEN_M, | |
| 638 | 549 | idpf_queue_has(GEN_CHK, refillq)); |
| 639 | 550 | |
| 640 | 551 | if (unlikely(++nta == refillq->desc_count)) { |
| @@ -1015,6 +926,11 @@ static void idpf_txq_group_rel(struct idpf_vport *vport) · 374 unmodified lines | ||
| 1015 | 926 | struct idpf_txq_group *txq_grp = &vport->txq_grps[i]; |
| 1016 | 927 | |
| 1017 | 928 | for (j = 0; j < txq_grp->num_txq; j++) { |
| 929 | + if (flow_sch_en) { | |
| 930 | + kfree(txq_grp->txqs[j]->refillq); | |
| 931 | + txq_grp->txqs[j]->refillq = NULL; | |
| 932 | + } | |
| 933 | + | |
| 1018 | 934 | kfree(txq_grp->txqs[j]); |
| 1019 | 935 | txq_grp->txqs[j] = NULL; |
| 1020 | 936 | } |
| @@ -1024,9 +940,6 @@ static void idpf_txq_group_rel(struct idpf_vport *vport) · 3 unmodified lines | ||
| 1024 | 940 | |
| 1025 | 941 | kfree(txq_grp->complq); |
| 1026 | 942 | txq_grp->complq = NULL; |
| 1027 | − | |
| 1028 | − if (flow_sch_en) | |
| 1029 | − kfree(txq_grp->stashes); | |
| 1030 | 943 | } |
| 1031 | 944 | kfree(vport->txq_grps); |
| 1032 | 945 | vport->txq_grps = NULL; |
| @@ -1387,7 +1300,6 @@ static int idpf_txq_group_alloc(struct idpf_vport *vport, u16 num_txq) · 354 unmodified lines | ||
| 1387 | 1300 | for (i = 0; i < vport->num_txq_grp; i++) { |
| 1388 | 1301 | struct idpf_txq_group *tx_qgrp = &vport->txq_grps[i]; |
| 1389 | 1302 | struct idpf_adapter *adapter = vport->adapter; |
| 1390 | − struct idpf_txq_stash *stashes; | |
| 1391 | 1303 | int j; |
| 1392 | 1304 | |
| 1393 | 1305 | tx_qgrp->vport = vport; |
| @@ -1400,15 +1312,6 @@ static int idpf_txq_group_alloc(struct idpf_vport *vport, u16 num_txq) · 6 unmodified lines | ||
| 1400 | 1312 | goto err_alloc; |
| 1401 | 1313 | } |
| 1402 | 1314 | |
| 1403 | − if (split && flow_sch_en) { | |
| 1404 | − stashes = kcalloc(num_txq, sizeof(*stashes), | |
| 1405 | − GFP_KERNEL); | |
| 1406 | − if (!stashes) | |
| 1407 | − goto err_alloc; | |
| 1408 | − | |
| 1409 | − tx_qgrp->stashes = stashes; | |
| 1410 | − } | |
| 1411 | − | |
| 1412 | 1315 | for (j = 0; j < tx_qgrp->num_txq; j++) { |
| 1413 | 1316 | struct idpf_tx_queue *q = tx_qgrp->txqs[j]; |
| 1414 | 1317 | |
| @@ -1428,12 +1331,14 @@ static int idpf_txq_group_alloc(struct idpf_vport *vport, u16 num_txq) · 13 unmodified lines | ||
| 1428 | 1331 | if (!flow_sch_en) |
| 1429 | 1332 | continue; |
| 1430 | 1333 | |
| 1431 | − if (split) { | |
| 1432 | − q->stash = &stashes[j]; | |
| 1433 | − hash_init(q->stash->sched_buf_hash); | |
| 1434 | − } | |
| 1435 | − | |
| 1436 | 1334 | idpf_queue_set(FLOW_SCH_EN, q); |
| 1335 | + | |
| 1336 | + q->refillq = kzalloc(sizeof(*q->refillq), GFP_KERNEL); | |
| 1337 | + if (!q->refillq) | |
| 1338 | + goto err_alloc; | |
| 1339 | + | |
| 1340 | + idpf_queue_set(GEN_CHK, q->refillq); | |
| 1341 | + idpf_queue_set(RFL_GEN_CHK, q->refillq); | |
| 1437 | 1342 | } |
| 1438 | 1343 | |
| 1439 | 1344 | if (!split) |
| @@ -1717,87 +1622,6 @@ static void idpf_tx_read_tstamp(struct idpf_tx_queue *txq, struct sk_buff *skb) · 277 unmodified lines | ||
| 1717 | 1622 | spin_unlock_bh(&tx_tstamp_caps->status_lock); |
| 1718 | 1623 | } |
| 1719 | 1624 | |
| 1720 | −/** | |
| 1721 | − * idpf_tx_clean_stashed_bufs - clean bufs that were stored for | |
| 1722 | − * out of order completions | |
| 1723 | − * @txq: queue to clean | |
| 1724 | − * @compl_tag: completion tag of packet to clean (from completion descriptor) | |
| 1725 | − * @cleaned: pointer to stats struct to track cleaned packets/bytes | |
| 1726 | − * @budget: Used to determine if we are in netpoll | |
| 1727 | − */ | |
| 1728 | −static void idpf_tx_clean_stashed_bufs(struct idpf_tx_queue *txq, | |
| 1729 | − u16 compl_tag, | |
| 1730 | − struct libeth_sq_napi_stats *cleaned, | |
| 1731 | − int budget) | |
| 1732 | −{ | |
| 1733 | − struct idpf_tx_stash *stash; | |
| 1734 | − struct hlist_node *tmp_buf; | |
| 1735 | − struct libeth_cq_pp cp = { | |
| 1736 | − .dev = txq->dev, | |
| 1737 | − .ss = cleaned, | |
| 1738 | − .napi = budget, | |
| 1739 | − }; | |
| 1740 | − | |
| 1741 | − /* Buffer completion */ | |
| 1742 | − hash_for_each_possible_safe(txq->stash->sched_buf_hash, stash, tmp_buf, | |
| 1743 | − hlist, compl_tag) { | |
| 1744 | − if (unlikely(idpf_tx_buf_compl_tag(&stash->buf) != compl_tag)) | |
| 1745 | − continue; | |
| 1746 | − | |
| 1747 | − hash_del(&stash->hlist); | |
| 1748 | − | |
| 1749 | − if (stash->buf.type == LIBETH_SQE_SKB && | |
| 1750 | − (skb_shinfo(stash->buf.skb)->tx_flags & SKBTX_IN_PROGRESS)) | |
| 1751 | − idpf_tx_read_tstamp(txq, stash->buf.skb); | |
| 1752 | − | |
| 1753 | − libeth_tx_complete(&stash->buf, &cp); | |
| 1754 | − | |
| 1755 | − /* Push shadow buf back onto stack */ | |
| 1756 | − idpf_buf_lifo_push(&txq->stash->buf_stack, stash); | |
| 1757 | − } | |
| 1758 | −} | |
| 1759 | − | |
| 1760 | −/** | |
| 1761 | − * idpf_stash_flow_sch_buffers - store buffer parameters info to be freed at a | |
| 1762 | − * later time (only relevant for flow scheduling mode) | |
| 1763 | − * @txq: Tx queue to clean | |
| 1764 | − * @tx_buf: buffer to store | |
| 1765 | − */ | |
| 1766 | −static int idpf_stash_flow_sch_buffers(struct idpf_tx_queue *txq, | |
| 1767 | − struct idpf_tx_buf *tx_buf) | |
| 1768 | −{ | |
| 1769 | − struct idpf_tx_stash *stash; | |
| 1770 | − | |
| 1771 | − if (unlikely(tx_buf->type <= LIBETH_SQE_CTX)) | |
| 1772 | − return 0; | |
| 1773 | − | |
| 1774 | − stash = idpf_buf_lifo_pop(&txq->stash->buf_stack); | |
| 1775 | − if (unlikely(!stash)) { | |
| 1776 | − net_err_ratelimited("%s: No out-of-order TX buffers left!\n", | |
| 1777 | − netdev_name(txq->netdev)); | |
| 1778 | − | |
| 1779 | − return -ENOMEM; | |
| 1780 | − } | |
| 1781 | − | |
| 1782 | − /* Store buffer params in shadow buffer */ | |
| 1783 | − stash->buf.skb = tx_buf->skb; | |
| 1784 | − stash->buf.bytes = tx_buf->bytes; | |
| 1785 | − stash->buf.packets = tx_buf->packets; | |
| 1786 | − stash->buf.type = tx_buf->type; | |
| 1787 | − stash->buf.nr_frags = tx_buf->nr_frags; | |
| 1788 | − dma_unmap_addr_set(&stash->buf, dma, dma_unmap_addr(tx_buf, dma)); | |
| 1789 | − dma_unmap_len_set(&stash->buf, len, dma_unmap_len(tx_buf, len)); | |
| 1790 | − idpf_tx_buf_compl_tag(&stash->buf) = idpf_tx_buf_compl_tag(tx_buf); | |
| 1791 | − | |
| 1792 | − /* Add buffer to buf_hash table to be freed later */ | |
| 1793 | − hash_add(txq->stash->sched_buf_hash, &stash->hlist, | |
| 1794 | − idpf_tx_buf_compl_tag(&stash->buf)); | |
| 1795 | − | |
| 1796 | − tx_buf->type = LIBETH_SQE_EMPTY; | |
| 1797 | − | |
| 1798 | − return 0; | |
| 1799 | −} | |
| 1800 | − | |
| 1801 | 1625 | #define idpf_tx_splitq_clean_bump_ntc(txq, ntc, desc, buf) \ |
| 1802 | 1626 | do { \ |
| 1803 | 1627 | if (unlikely(++(ntc) == (txq)->desc_count)) { \ |
| @@ -1825,14 +1649,8 @@ do { \ · 21 unmodified lines | ||
| 1825 | 1649 | * Separate packet completion events will be reported on the completion queue, |
| 1826 | 1650 | * and the buffers will be cleaned separately. The stats are not updated from |
| 1827 | 1651 | * this function when using flow-based scheduling. |
| 1828 | − * | |
| 1829 | − * Furthermore, in flow scheduling mode, check to make sure there are enough | |
| 1830 | − * reserve buffers to stash the packet. If there are not, return early, which | |
| 1831 | − * will leave next_to_clean pointing to the packet that failed to be stashed. | |
| 1832 | − * | |
| 1833 | − * Return: false in the scenario above, true otherwise. | |
| 1834 | 1652 | */ |
| 1835 | −static bool idpf_tx_splitq_clean(struct idpf_tx_queue *tx_q, u16 end, | |
| 1653 | +static void idpf_tx_splitq_clean(struct idpf_tx_queue *tx_q, u16 end, | |
| 1836 | 1654 | int napi_budget, |
| 1837 | 1655 | struct libeth_sq_napi_stats *cleaned, |
| 1838 | 1656 | bool descs_only) |
| @@ -1846,7 +1664,12 @@ static bool idpf_tx_splitq_clean(struct idpf_tx_queue *tx_q, u16 end, · 7 unmodified lines | ||
| 1846 | 1664 | .napi = napi_budget, |
| 1847 | 1665 | }; |
| 1848 | 1666 | struct idpf_tx_buf *tx_buf; |
| 1849 | − bool clean_complete = true; | |
| 1667 | + | |
| 1668 | + if (descs_only) { | |
| 1669 | + /* Bump ring index to mark as cleaned. */ | |
| 1670 | + tx_q->next_to_clean = end; | |
| 1671 | + return; | |
| 1672 | + } | |
| 1850 | 1673 | |
| 1851 | 1674 | tx_desc = &tx_q->flex_tx[ntc]; |
| 1852 | 1675 | next_pending_desc = &tx_q->flex_tx[end]; |
| @@ -1866,136 +1689,61 @@ static bool idpf_tx_splitq_clean(struct idpf_tx_queue *tx_q, u16 end, · 13 unmodified lines | ||
| 1866 | 1689 | break; |
| 1867 | 1690 | |
| 1868 | 1691 | eop_idx = tx_buf->rs_idx; |
| 1692 | + libeth_tx_complete(tx_buf, &cp); | |
| 1869 | 1693 | |
| 1870 | − if (descs_only) { | |
| 1871 | − if (IDPF_TX_BUF_RSV_UNUSED(tx_q) < tx_buf->nr_frags) { | |
| 1872 | − clean_complete = false; | |
| 1873 | − goto tx_splitq_clean_out; | |
| 1874 | − } | |
| 1875 | − | |
| 1876 | − idpf_stash_flow_sch_buffers(tx_q, tx_buf); | |
| 1694 | + /* unmap remaining buffers */ | |
| 1695 | + while (ntc != eop_idx) { | |
| 1696 | + idpf_tx_splitq_clean_bump_ntc(tx_q, ntc, | |
| 1697 | + tx_desc, tx_buf); | |
| 1877 | 1698 | |
| 1878 | − while (ntc != eop_idx) { | |
| 1879 | − idpf_tx_splitq_clean_bump_ntc(tx_q, ntc, | |
| 1880 | − tx_desc, tx_buf); | |
| 1881 | − idpf_stash_flow_sch_buffers(tx_q, tx_buf); | |
| 1882 | − } | |
| 1883 | − } else { | |
| 1699 | + /* unmap any remaining paged data */ | |
| 1884 | 1700 | libeth_tx_complete(tx_buf, &cp); |
| 1885 | − | |
| 1886 | − /* unmap remaining buffers */ | |
| 1887 | − while (ntc != eop_idx) { | |
| 1888 | − idpf_tx_splitq_clean_bump_ntc(tx_q, ntc, | |
| 1889 | − tx_desc, tx_buf); | |
| 1890 | − | |
| 1891 | − /* unmap any remaining paged data */ | |
| 1892 | − libeth_tx_complete(tx_buf, &cp); | |
| 1893 | − } | |
| 1894 | 1701 | } |
| 1895 | 1702 | |
| 1896 | 1703 | fetch_next_txq_desc: |
| 1897 | 1704 | idpf_tx_splitq_clean_bump_ntc(tx_q, ntc, tx_desc, tx_buf); |
| 1898 | 1705 | } |
| 1899 | 1706 | |
| 1900 | −tx_splitq_clean_out: | |
| 1901 | 1707 | tx_q->next_to_clean = ntc; |
| 1902 | − | |
| 1903 | − return clean_complete; | |
| 1904 | 1708 | } |
| 1905 | 1709 | |
| 1906 | −#define idpf_tx_clean_buf_ring_bump_ntc(txq, ntc, buf) \ | |
| 1907 | −do { \ | |
| 1908 | − (buf)++; \ | |
| 1909 | − (ntc)++; \ | |
| 1910 | − if (unlikely((ntc) == (txq)->desc_count)) { \ | |
| 1911 | − buf = (txq)->tx_buf; \ | |
| 1912 | − ntc = 0; \ | |
| 1913 | − } \ | |
| 1914 | −} while (0) | |
| 1915 | − | |
| 1916 | 1710 | /** |
| 1917 | − * idpf_tx_clean_buf_ring - clean flow scheduling TX queue buffers | |
| 1711 | + * idpf_tx_clean_bufs - clean flow scheduling TX queue buffers | |
| 1918 | 1712 | * @txq: queue to clean |
| 1919 | − * @compl_tag: completion tag of packet to clean (from completion descriptor) | |
| 1713 | + * @buf_id: packet's starting buffer ID, from completion descriptor | |
| 1920 | 1714 | * @cleaned: pointer to stats struct to track cleaned packets/bytes |
| 1921 | 1715 | * @budget: Used to determine if we are in netpoll |
| 1922 | 1716 | * |
| 1923 | − * Cleans all buffers associated with the input completion tag either from the | |
| 1924 | − * TX buffer ring or from the hash table if the buffers were previously | |
| 1925 | − * stashed. Returns the byte/segment count for the cleaned packet associated | |
| 1926 | − * this completion tag. | |
| 1717 | + * Clean all buffers associated with the packet starting at buf_id. Returns the | |
| 1718 | + * byte/segment count for the cleaned packet. | |
| 1927 | 1719 | */ |
| 1928 | −static bool idpf_tx_clean_buf_ring(struct idpf_tx_queue *txq, u16 compl_tag, | |
| 1929 | − struct libeth_sq_napi_stats *cleaned, | |
| 1930 | − int budget) | |
| 1720 | +static void idpf_tx_clean_bufs(struct idpf_tx_queue *txq, u32 buf_id, | |
| 1721 | + struct libeth_sq_napi_stats *cleaned, | |
| 1722 | + int budget) | |
| 1931 | 1723 | { |
| 1932 | − u16 idx = compl_tag & txq->compl_tag_bufid_m; | |
| 1933 | 1724 | struct idpf_tx_buf *tx_buf = NULL; |
| 1934 | 1725 | struct libeth_cq_pp cp = { |
| 1935 | 1726 | .dev = txq->dev, |
| 1936 | 1727 | .ss = cleaned, |
| 1937 | 1728 | .napi = budget, |
| 1938 | 1729 | }; |
| 1939 | − u16 ntc, orig_idx = idx; | |
| 1940 | − | |
| 1941 | − tx_buf = &txq->tx_buf[idx]; | |
| 1942 | − | |
| 1943 | − if (unlikely(tx_buf->type <= LIBETH_SQE_CTX || | |
| 1944 | − idpf_tx_buf_compl_tag(tx_buf) != compl_tag)) | |
| 1945 | − return false; | |
| 1946 | 1730 | |
| 1731 | + tx_buf = &txq->tx_buf[buf_id]; | |
| 1947 | 1732 | if (tx_buf->type == LIBETH_SQE_SKB) { |
| 1948 | 1733 | if (skb_shinfo(tx_buf->skb)->tx_flags & SKBTX_IN_PROGRESS) |
| 1949 | 1734 | idpf_tx_read_tstamp(txq, tx_buf->skb); |
| 1950 | 1735 | |
| 1951 | 1736 | libeth_tx_complete(tx_buf, &cp); |
| 1737 | + idpf_post_buf_refill(txq->refillq, buf_id); | |
| 1952 | 1738 | } |
| 1953 | 1739 | |
| 1954 | − idpf_tx_clean_buf_ring_bump_ntc(txq, idx, tx_buf); | |
| 1740 | + while (idpf_tx_buf_next(tx_buf) != IDPF_TXBUF_NULL) { | |
| 1741 | + buf_id = idpf_tx_buf_next(tx_buf); | |
| 1955 | 1742 | |
| 1956 | − while (idpf_tx_buf_compl_tag(tx_buf) == compl_tag) { | |
| 1743 | + tx_buf = &txq->tx_buf[buf_id]; | |
| 1957 | 1744 | libeth_tx_complete(tx_buf, &cp); |
| 1958 | − idpf_tx_clean_buf_ring_bump_ntc(txq, idx, tx_buf); | |
| 1745 | + idpf_post_buf_refill(txq->refillq, buf_id); | |
| 1959 | 1746 | } |
| 1960 | − | |
| 1961 | − /* | |
| 1962 | − * It's possible the packet we just cleaned was an out of order | |
| 1963 | − * completion, which means we can stash the buffers starting from | |
| 1964 | − * the original next_to_clean and reuse the descriptors. We need | |
| 1965 | − * to compare the descriptor ring next_to_clean packet's "first" buffer | |
| 1966 | − * to the "first" buffer of the packet we just cleaned to determine if | |
| 1967 | − * this is the case. Howevever, next_to_clean can point to either a | |
| 1968 | − * reserved buffer that corresponds to a context descriptor used for the | |
| 1969 | − * next_to_clean packet (TSO packet) or the "first" buffer (single | |
| 1970 | − * packet). The orig_idx from the packet we just cleaned will always | |
| 1971 | − * point to the "first" buffer. If next_to_clean points to a reserved | |
| 1972 | − * buffer, let's bump ntc once and start the comparison from there. | |
| 1973 | − */ | |
| 1974 | − ntc = txq->next_to_clean; | |
| 1975 | − tx_buf = &txq->tx_buf[ntc]; | |
| 1976 | − | |
| 1977 | − if (tx_buf->type == LIBETH_SQE_CTX) | |
| 1978 | − idpf_tx_clean_buf_ring_bump_ntc(txq, ntc, tx_buf); | |
| 1979 | − | |
| 1980 | − /* | |
| 1981 | − * If ntc still points to a different "first" buffer, clean the | |
| 1982 | − * descriptor ring and stash all of the buffers for later cleaning. If | |
| 1983 | − * we cannot stash all of the buffers, next_to_clean will point to the | |
| 1984 | − * "first" buffer of the packet that could not be stashed and cleaning | |
| 1985 | − * will start there next time. | |
| 1986 | − */ | |
| 1987 | − if (unlikely(tx_buf != &txq->tx_buf[orig_idx] && | |
| 1988 | − !idpf_tx_splitq_clean(txq, orig_idx, budget, cleaned, | |
| 1989 | − true))) | |
| 1990 | − return true; | |
| 1991 | − | |
| 1992 | − /* | |
| 1993 | − * Otherwise, update next_to_clean to reflect the cleaning that was | |
| 1994 | − * done above. | |
| 1995 | − */ | |
| 1996 | − txq->next_to_clean = idx; | |
| 1997 | − | |
| 1998 | − return true; | |
| 1999 | 1747 | } |
| 2000 | 1748 | |
| 2001 | 1749 | /** |
| @@ -2014,22 +1762,17 @@ static void idpf_tx_handle_rs_completion(struct idpf_tx_queue *txq, · 12 unmodified lines | ||
| 2014 | 1762 | struct libeth_sq_napi_stats *cleaned, |
| 2015 | 1763 | int budget) |
| 2016 | 1764 | { |
| 2017 | − u16 compl_tag; | |
| 1765 | + /* RS completion contains queue head for queue based scheduling or | |
| 1766 | + * completion tag for flow based scheduling. | |
| 1767 | + */ | |
| 1768 | + u16 rs_compl_val = le16_to_cpu(desc->q_head_compl_tag.q_head); | |
| 2018 | 1769 | |
| 2019 | 1770 | if (!idpf_queue_has(FLOW_SCH_EN, txq)) { |
| 2020 | − u16 head = le16_to_cpu(desc->q_head_compl_tag.q_head); | |
| 2021 | − | |
| 2022 | − idpf_tx_splitq_clean(txq, head, budget, cleaned, false); | |
| 1771 | + idpf_tx_splitq_clean(txq, rs_compl_val, budget, cleaned, false); | |
| 2023 | 1772 | return; |
| 2024 | 1773 | } |
| 2025 | 1774 | |
| 2026 | − compl_tag = le16_to_cpu(desc->q_head_compl_tag.compl_tag); | |
| 2027 | − | |
| 2028 | − /* If we didn't clean anything on the ring, this packet must be | |
| 2029 | − * in the hash table. Go clean it there. | |
| 2030 | − */ | |
| 2031 | − if (!idpf_tx_clean_buf_ring(txq, compl_tag, cleaned, budget)) | |
| 2032 | − idpf_tx_clean_stashed_bufs(txq, compl_tag, cleaned, budget); | |
| 1775 | + idpf_tx_clean_bufs(txq, rs_compl_val, cleaned, budget); | |
| 2033 | 1776 | } |
| 2034 | 1777 | |
| 2035 | 1778 | /** |
| @@ -2146,8 +1889,7 @@ fetch_next_desc: · 110 unmodified lines | ||
| 2146 | 1889 | /* Update BQL */ |
| 2147 | 1890 | nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx); |
| 2148 | 1891 | |
| 2149 | − dont_wake = !complq_ok || IDPF_TX_BUF_RSV_LOW(tx_q) || | |
| 2150 | − np->state != __IDPF_VPORT_UP || | |
| 1892 | + dont_wake = !complq_ok || np->state != __IDPF_VPORT_UP || | |
| 2151 | 1893 | !netif_carrier_ok(tx_q->netdev); |
| 2152 | 1894 | /* Check if the TXQ needs to and can be restarted */ |
| 2153 | 1895 | __netif_txq_completed_wake(nq, tx_q->cleaned_pkts, tx_q->cleaned_bytes, |
| @@ -2204,15 +1946,21 @@ void idpf_tx_splitq_build_flow_desc(union idpf_tx_flex_desc *desc, · 50 unmodified lines | ||
| 2204 | 1946 | desc->flow.qw1.compl_tag = cpu_to_le16(params->compl_tag); |
| 2205 | 1947 | } |
| 2206 | 1948 | |
| 2207 | −/* Global conditions to tell whether the txq (and related resources) | |
| 2208 | − * has room to allow the use of "size" descriptors. | |
| 1949 | +/** | |
| 1950 | + * idpf_tx_splitq_has_room - check if enough Tx splitq resources are available | |
| 1951 | + * @tx_q: the queue to be checked | |
| 1952 | + * @descs_needed: number of descriptors required for this packet | |
| 1953 | + * @bufs_needed: number of Tx buffers required for this packet | |
| 1954 | + * | |
| 1955 | + * Return: 0 if no room available, 1 otherwise | |
| 2209 | 1956 | */ |
| 2210 | −static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size) | |
| 1957 | +static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 descs_needed, | |
| 1958 | + u32 bufs_needed) | |
| 2211 | 1959 | { |
| 2212 | − if (IDPF_DESC_UNUSED(tx_q) < size || | |
| 1960 | + if (IDPF_DESC_UNUSED(tx_q) < descs_needed || | |
| 2213 | 1961 | IDPF_TX_COMPLQ_PENDING(tx_q->txq_grp) > |
| 2214 | 1962 | IDPF_TX_COMPLQ_OVERFLOW_THRESH(tx_q->txq_grp->complq) || |
| 2215 | − IDPF_TX_BUF_RSV_LOW(tx_q)) | |
| 1963 | + idpf_tx_splitq_get_free_bufs(tx_q->refillq) < bufs_needed) | |
| 2216 | 1964 | return 0; |
| 2217 | 1965 | return 1; |
| 2218 | 1966 | } |
| @@ -2221,14 +1969,21 @@ static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size) · 2 unmodified lines | ||
| 2221 | 1969 | * idpf_tx_maybe_stop_splitq - 1st level check for Tx splitq stop conditions |
| 2222 | 1970 | * @tx_q: the queue to be checked |
| 2223 | 1971 | * @descs_needed: number of descriptors required for this packet |
| 1972 | + * @bufs_needed: number of buffers needed for this packet | |
| 2224 | 1973 | * |
| 2225 | − * Returns 0 if stop is not needed | |
| 1974 | + * Return: 0 if stop is not needed | |
| 2226 | 1975 | */ |
| 2227 | 1976 | static int idpf_tx_maybe_stop_splitq(struct idpf_tx_queue *tx_q, |
| 2228 | − unsigned int descs_needed) | |
| 1977 | + u32 descs_needed, | |
| 1978 | + u32 bufs_needed) | |
| 2229 | 1979 | { |
| 1980 | + /* Since we have multiple resources to check for splitq, our | |
| 1981 | + * start,stop_thrs becomes a boolean check instead of a count | |
| 1982 | + * threshold. | |
| 1983 | + */ | |
| 2230 | 1984 | if (netif_subqueue_maybe_stop(tx_q->netdev, tx_q->idx, |
| 2231 | − idpf_txq_has_room(tx_q, descs_needed), | |
| 1985 | + idpf_txq_has_room(tx_q, descs_needed, | |
| 1986 | + bufs_needed), | |
| 2232 | 1987 | 1, 1)) |
| 2233 | 1988 | return 0; |
| 2234 | 1989 | |
| @@ -2270,14 +2025,16 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val, · 35 unmodified lines | ||
| 2270 | 2025 | } |
| 2271 | 2026 | |
| 2272 | 2027 | /** |
| 2273 | − * idpf_tx_desc_count_required - calculate number of Tx descriptors needed | |
| 2028 | + * idpf_tx_res_count_required - get number of Tx resources needed for this pkt | |
| 2274 | 2029 | * @txq: queue to send buffer on |
| 2275 | 2030 | * @skb: send buffer |
| 2031 | + * @bufs_needed: (output) number of buffers needed for this skb. | |
| 2276 | 2032 | * |
| 2277 | − * Returns number of data descriptors needed for this skb. | |
| 2033 | + * Return: number of data descriptors and buffers needed for this skb. | |
| 2278 | 2034 | */ |
| 2279 | −unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, | |
| 2280 | − struct sk_buff *skb) | |
| 2035 | +unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq, | |
| 2036 | + struct sk_buff *skb, | |
| 2037 | + u32 *bufs_needed) | |
| 2281 | 2038 | { |
| 2282 | 2039 | const struct skb_shared_info *shinfo; |
| 2283 | 2040 | unsigned int count = 0, i; |
| @@ -2288,6 +2045,7 @@ unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, · 4 unmodified lines | ||
| 2288 | 2045 | return count; |
| 2289 | 2046 | |
| 2290 | 2047 | shinfo = skb_shinfo(skb); |
| 2048 | + *bufs_needed += shinfo->nr_frags; | |
| 2291 | 2049 | for (i = 0; i < shinfo->nr_frags; i++) { |
| 2292 | 2050 | unsigned int size; |
| 2293 | 2051 | |
| @@ -2317,71 +2075,89 @@ unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, · 23 unmodified lines | ||
| 2317 | 2075 | } |
| 2318 | 2076 | |
| 2319 | 2077 | /** |
| 2320 | − * idpf_tx_dma_map_error - handle TX DMA map errors | |
| 2321 | − * @txq: queue to send buffer on | |
| 2322 | − * @skb: send buffer | |
| 2323 | − * @first: original first buffer info buffer for packet | |
| 2324 | − * @idx: starting point on ring to unwind | |
| 2078 | + * idpf_tx_splitq_bump_ntu - adjust NTU and generation | |
| 2079 | + * @txq: the tx ring to wrap | |
| 2080 | + * @ntu: ring index to bump | |
| 2325 | 2081 | */ |
| 2326 | −void idpf_tx_dma_map_error(struct idpf_tx_queue *txq, struct sk_buff *skb, | |
| 2327 | − struct idpf_tx_buf *first, u16 idx) | |
| 2082 | +static unsigned int idpf_tx_splitq_bump_ntu(struct idpf_tx_queue *txq, u16 ntu) | |
| 2328 | 2083 | { |
| 2329 | − struct libeth_sq_napi_stats ss = { }; | |
| 2330 | − struct libeth_cq_pp cp = { | |
| 2331 | − .dev = txq->dev, | |
| 2332 | − .ss = &ss, | |
| 2333 | − }; | |
| 2084 | + ntu++; | |
| 2334 | 2085 | |
| 2335 | − u64_stats_update_begin(&txq->stats_sync); | |
| 2336 | − u64_stats_inc(&txq->q_stats.dma_map_errs); | |
| 2337 | − u64_stats_update_end(&txq->stats_sync); | |
| 2086 | + if (ntu == txq->desc_count) | |
| 2087 | + ntu = 0; | |
| 2338 | 2088 | |
| 2339 | − /* clear dma mappings for failed tx_buf map */ | |
| 2340 | − for (;;) { | |
| 2341 | − struct idpf_tx_buf *tx_buf; | |
| 2089 | + return ntu; | |
| 2090 | +} | |
| 2342 | 2091 | |
| 2343 | − tx_buf = &txq->tx_buf[idx]; | |
| 2344 | − libeth_tx_complete(tx_buf, &cp); | |
| 2345 | − if (tx_buf == first) | |
| 2346 | − break; | |
| 2347 | − if (idx == 0) | |
| 2348 | − idx = txq->desc_count; | |
| 2349 | − idx--; | |
| 2350 | − } | |
| 2092 | +/** | |
| 2093 | + * idpf_tx_get_free_buf_id - get a free buffer ID from the refill queue | |
| 2094 | + * @refillq: refill queue to get buffer ID from | |
| 2095 | + * @buf_id: return buffer ID | |
| 2096 | + * | |
| 2097 | + * Return: true if a buffer ID was found, false if not | |
| 2098 | + */ | |
| 2099 | +static bool idpf_tx_get_free_buf_id(struct idpf_sw_queue *refillq, | |
| 2100 | + u32 *buf_id) | |
| 2101 | +{ | |
| 2102 | + u32 ntc = refillq->next_to_clean; | |
| 2103 | + u32 refill_desc; | |
| 2351 | 2104 | |
| 2352 | − if (skb_is_gso(skb)) { | |
| 2353 | − union idpf_tx_flex_desc *tx_desc; | |
| 2105 | + refill_desc = refillq->ring[ntc]; | |
| 2354 | 2106 | |
| 2355 | − /* If we failed a DMA mapping for a TSO packet, we will have | |
| 2356 | − * used one additional descriptor for a context | |
| 2357 | − * descriptor. Reset that here. | |
| 2358 | − */ | |
| 2359 | − tx_desc = &txq->flex_tx[idx]; | |
| 2360 | − memset(tx_desc, 0, sizeof(*tx_desc)); | |
| 2361 | − if (idx == 0) | |
| 2362 | − idx = txq->desc_count; | |
| 2363 | − idx--; | |
| 2107 | + if (unlikely(idpf_queue_has(RFL_GEN_CHK, refillq) != | |
| 2108 | + !!(refill_desc & IDPF_RFL_BI_GEN_M))) | |
| 2109 | + return false; | |
| 2110 | + | |
| 2111 | + *buf_id = FIELD_GET(IDPF_RFL_BI_BUFID_M, refill_desc); | |
| 2112 | + | |
| 2113 | + if (unlikely(++ntc == refillq->desc_count)) { | |
| 2114 | + idpf_queue_change(RFL_GEN_CHK, refillq); | |
| 2115 | + ntc = 0; | |
| 2364 | 2116 | } |
| 2365 | 2117 | |
| 2366 | − /* Update tail in case netdev_xmit_more was previously true */ | |
| 2367 | − idpf_tx_buf_hw_update(txq, idx, false); | |
| 2118 | + refillq->next_to_clean = ntc; | |
| 2119 | + | |
| 2120 | + return true; | |
| 2368 | 2121 | } |
| 2369 | 2122 | |
| 2370 | 2123 | /** |
| 2371 | − * idpf_tx_splitq_bump_ntu - adjust NTU and generation | |
| 2372 | − * @txq: the tx ring to wrap | |
| 2373 | − * @ntu: ring index to bump | |
| 2124 | + * idpf_tx_splitq_pkt_err_unmap - Unmap buffers and bump tail in case of error | |
| 2125 | + * @txq: Tx queue to unwind | |
| 2126 | + * @params: pointer to splitq params struct | |
| 2127 | + * @first: starting buffer for packet to unmap | |
| 2374 | 2128 | */ |
| 2375 | −static unsigned int idpf_tx_splitq_bump_ntu(struct idpf_tx_queue *txq, u16 ntu) | |
| 2129 | +static void idpf_tx_splitq_pkt_err_unmap(struct idpf_tx_queue *txq, | |
| 2130 | + struct idpf_tx_splitq_params *params, | |
| 2131 | + struct idpf_tx_buf *first) | |
| 2376 | 2132 | { |
| 2377 | − ntu++; | |
| 2133 | + struct idpf_sw_queue *refillq = txq->refillq; | |
| 2134 | + struct libeth_sq_napi_stats ss = { }; | |
| 2135 | + struct idpf_tx_buf *tx_buf = first; | |
| 2136 | + struct libeth_cq_pp cp = { | |
| 2137 | + .dev = txq->dev, | |
| 2138 | + .ss = &ss, | |
| 2139 | + }; | |
| 2378 | 2140 | |
| 2379 | − if (ntu == txq->desc_count) { | |
| 2380 | − ntu = 0; | |
| 2381 | − txq->compl_tag_cur_gen = IDPF_TX_ADJ_COMPL_TAG_GEN(txq); | |
| 2141 | + u64_stats_update_begin(&txq->stats_sync); | |
| 2142 | + u64_stats_inc(&txq->q_stats.dma_map_errs); | |
| 2143 | + u64_stats_update_end(&txq->stats_sync); | |
| 2144 | + | |
| 2145 | + libeth_tx_complete(tx_buf, &cp); | |
| 2146 | + while (idpf_tx_buf_next(tx_buf) != IDPF_TXBUF_NULL) { | |
| 2147 | + tx_buf = &txq->tx_buf[idpf_tx_buf_next(tx_buf)]; | |
| 2148 | + libeth_tx_complete(tx_buf, &cp); | |
| 2382 | 2149 | } |
| 2383 | 2150 | |
| 2384 | − return ntu; | |
| 2151 | + /* Update tail in case netdev_xmit_more was previously true. */ | |
| 2152 | + idpf_tx_buf_hw_update(txq, params->prev_ntu, false); | |
| 2153 | + | |
| 2154 | + if (!refillq) | |
| 2155 | + return; | |
| 2156 | + | |
| 2157 | + /* Restore refillq state to avoid leaking tags. */ | |
| 2158 | + if (params->prev_refill_gen != idpf_queue_has(RFL_GEN_CHK, refillq)) | |
| 2159 | + idpf_queue_change(RFL_GEN_CHK, refillq); | |
| 2160 | + refillq->next_to_clean = params->prev_refill_ntc; | |
| 2385 | 2161 | } |
| 2386 | 2162 | |
| 2387 | 2163 | /** |
| @@ -2405,6 +2181,7 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, · 17 unmodified lines | ||
| 2405 | 2181 | struct netdev_queue *nq; |
| 2406 | 2182 | struct sk_buff *skb; |
| 2407 | 2183 | skb_frag_t *frag; |
| 2184 | + u32 next_buf_id; | |
| 2408 | 2185 | u16 td_cmd = 0; |
| 2409 | 2186 | dma_addr_t dma; |
| 2410 | 2187 | |
| @@ -2422,17 +2199,16 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, · 11 unmodified lines | ||
| 2422 | 2199 | tx_buf = first; |
| 2423 | 2200 | first->nr_frags = 0; |
| 2424 | 2201 | |
| 2425 | − params->compl_tag = | |
| 2426 | − (tx_q->compl_tag_cur_gen << tx_q->compl_tag_gen_s) | i; | |
| 2427 | − | |
| 2428 | 2202 | for (frag = &skb_shinfo(skb)->frags[0];; frag++) { |
| 2429 | 2203 | unsigned int max_data = IDPF_TX_MAX_DESC_DATA_ALIGNED; |
| 2430 | 2204 | |
| 2431 | − if (dma_mapping_error(tx_q->dev, dma)) | |
| 2432 | − return idpf_tx_dma_map_error(tx_q, skb, first, i); | |
| 2205 | + if (unlikely(dma_mapping_error(tx_q->dev, dma))) { | |
| 2206 | + idpf_tx_buf_next(tx_buf) = IDPF_TXBUF_NULL; | |
| 2207 | + return idpf_tx_splitq_pkt_err_unmap(tx_q, params, | |
| 2208 | + first); | |
| 2209 | + } | |
| 2433 | 2210 | |
| 2434 | 2211 | first->nr_frags++; |
| 2435 | − idpf_tx_buf_compl_tag(tx_buf) = params->compl_tag; | |
| 2436 | 2212 | tx_buf->type = LIBETH_SQE_FRAG; |
| 2437 | 2213 | |
| 2438 | 2214 | /* record length, and DMA address */ |
| @@ -2488,29 +2264,12 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, · 49 unmodified lines | ||
| 2488 | 2264 | max_data); |
| 2489 | 2265 | |
| 2490 | 2266 | if (unlikely(++i == tx_q->desc_count)) { |
| 2491 | − tx_buf = tx_q->tx_buf; | |
| 2492 | 2267 | tx_desc = &tx_q->flex_tx[0]; |
| 2493 | 2268 | i = 0; |
| 2494 | − tx_q->compl_tag_cur_gen = | |
| 2495 | − IDPF_TX_ADJ_COMPL_TAG_GEN(tx_q); | |
| 2496 | 2269 | } else { |
| 2497 | − tx_buf++; | |
| 2498 | 2270 | tx_desc++; |
| 2499 | 2271 | } |
| 2500 | 2272 | |
| 2501 | − /* Since this packet has a buffer that is going to span | |
| 2502 | − * multiple descriptors, it's going to leave holes in | |
| 2503 | − * to the TX buffer ring. To ensure these holes do not | |
| 2504 | − * cause issues in the cleaning routines, we will clear | |
| 2505 | − * them of any stale data and assign them the same | |
| 2506 | − * completion tag as the current packet. Then when the | |
| 2507 | − * packet is being cleaned, the cleaning routines will | |
| 2508 | − * simply pass over these holes and finish cleaning the | |
| 2509 | − * rest of the packet. | |
| 2510 | − */ | |
| 2511 | − tx_buf->type = LIBETH_SQE_EMPTY; | |
| 2512 | − idpf_tx_buf_compl_tag(tx_buf) = params->compl_tag; | |
| 2513 | − | |
| 2514 | 2273 | /* Adjust the DMA offset and the remaining size of the |
| 2515 | 2274 | * fragment. On the first iteration of this loop, |
| 2516 | 2275 | * max_data will be >= 12K and <= 16K-1. On any |
| @@ -2535,15 +2294,25 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, · 18 unmodified lines | ||
| 2535 | 2294 | idpf_tx_splitq_build_desc(tx_desc, params, td_cmd, size); |
| 2536 | 2295 | |
| 2537 | 2296 | if (unlikely(++i == tx_q->desc_count)) { |
| 2538 | − tx_buf = tx_q->tx_buf; | |
| 2539 | 2297 | tx_desc = &tx_q->flex_tx[0]; |
| 2540 | 2298 | i = 0; |
| 2541 | − tx_q->compl_tag_cur_gen = IDPF_TX_ADJ_COMPL_TAG_GEN(tx_q); | |
| 2542 | 2299 | } else { |
| 2543 | − tx_buf++; | |
| 2544 | 2300 | tx_desc++; |
| 2545 | 2301 | } |
| 2546 | 2302 | |
| 2303 | + if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { | |
| 2304 | + if (unlikely(!idpf_tx_get_free_buf_id(tx_q->refillq, | |
| 2305 | + &next_buf_id))) { | |
| 2306 | + idpf_tx_buf_next(tx_buf) = IDPF_TXBUF_NULL; | |
| 2307 | + return idpf_tx_splitq_pkt_err_unmap(tx_q, params, | |
| 2308 | + first); | |
| 2309 | + } | |
| 2310 | + } else { | |
| 2311 | + next_buf_id = i; | |
| 2312 | + } | |
| 2313 | + idpf_tx_buf_next(tx_buf) = next_buf_id; | |
| 2314 | + tx_buf = &tx_q->tx_buf[next_buf_id]; | |
| 2315 | + | |
| 2547 | 2316 | size = skb_frag_size(frag); |
| 2548 | 2317 | data_len -= size; |
| 2549 | 2318 | |
| @@ -2558,6 +2327,7 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q, · 8 unmodified lines | ||
| 2558 | 2327 | |
| 2559 | 2328 | /* write last descriptor with RS and EOP bits */ |
| 2560 | 2329 | first->rs_idx = i; |
| 2330 | + idpf_tx_buf_next(tx_buf) = IDPF_TXBUF_NULL; | |
| 2561 | 2331 | td_cmd |= params->eop_cmd; |
| 2562 | 2332 | idpf_tx_splitq_build_desc(tx_desc, params, td_cmd, size); |
| 2563 | 2333 | i = idpf_tx_splitq_bump_ntu(tx_q, i); |
| @@ -2661,8 +2431,6 @@ idpf_tx_splitq_get_ctx_desc(struct idpf_tx_queue *txq) · 97 unmodified lines | ||
| 2661 | 2431 | union idpf_flex_tx_ctx_desc *desc; |
| 2662 | 2432 | int i = txq->next_to_use; |
| 2663 | 2433 | |
| 2664 | − txq->tx_buf[i].type = LIBETH_SQE_CTX; | |
| 2665 | − | |
| 2666 | 2434 | /* grab the next descriptor */ |
| 2667 | 2435 | desc = &txq->flex_ctx[i]; |
| 2668 | 2436 | txq->next_to_use = idpf_tx_splitq_bump_ntu(txq, i); |
| @@ -2755,6 +2523,21 @@ static void idpf_tx_set_tstamp_desc(union idpf_flex_tx_ctx_desc *ctx_desc, · 86 unmodified lines | ||
| 2755 | 2523 | { } |
| 2756 | 2524 | #endif /* CONFIG_PTP_1588_CLOCK */ |
| 2757 | 2525 | |
| 2526 | +/** | |
| 2527 | + * idpf_tx_splitq_need_re - check whether RE bit needs to be set | |
| 2528 | + * @tx_q: pointer to Tx queue | |
| 2529 | + * | |
| 2530 | + * Return: true if RE bit needs to be set, false otherwise | |
| 2531 | + */ | |
| 2532 | +static bool idpf_tx_splitq_need_re(struct idpf_tx_queue *tx_q) | |
| 2533 | +{ | |
| 2534 | + int gap = tx_q->next_to_use - tx_q->last_re; | |
| 2535 | + | |
| 2536 | + gap += (gap < 0) ? tx_q->desc_count : 0; | |
| 2537 | + | |
| 2538 | + return gap >= IDPF_TX_SPLITQ_RE_MIN_GAP; | |
| 2539 | +} | |
| 2540 | + | |
| 2758 | 2541 | /** |
| 2759 | 2542 | * idpf_tx_splitq_frame - Sends buffer on Tx ring using flex descriptors |
| 2760 | 2543 | * @skb: send buffer |
| @@ -2765,13 +2548,16 @@ static void idpf_tx_set_tstamp_desc(union idpf_flex_tx_ctx_desc *ctx_desc, · 4 unmodified lines | ||
| 2765 | 2548 | static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, |
| 2766 | 2549 | struct idpf_tx_queue *tx_q) |
| 2767 | 2550 | { |
| 2768 | − struct idpf_tx_splitq_params tx_params = { }; | |
| 2551 | + struct idpf_tx_splitq_params tx_params = { | |
| 2552 | + .prev_ntu = tx_q->next_to_use, | |
| 2553 | + }; | |
| 2769 | 2554 | union idpf_flex_tx_ctx_desc *ctx_desc; |
| 2770 | 2555 | struct idpf_tx_buf *first; |
| 2771 | − unsigned int count; | |
| 2556 | + u32 count, buf_count = 1; | |
| 2772 | 2557 | int tso, idx; |
| 2558 | + u32 buf_id; | |
| 2773 | 2559 | |
| 2774 | − count = idpf_tx_desc_count_required(tx_q, skb); | |
| 2560 | + count = idpf_tx_res_count_required(tx_q, skb, &buf_count); | |
| 2775 | 2561 | if (unlikely(!count)) |
| 2776 | 2562 | return idpf_tx_drop_skb(tx_q, skb); |
| 2777 | 2563 | |
| @@ -2781,7 +2567,7 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, · 3 unmodified lines | ||
| 2781 | 2567 | |
| 2782 | 2568 | /* Check for splitq specific TX resources */ |
| 2783 | 2569 | count += (IDPF_TX_DESCS_PER_CACHE_LINE + tso); |
| 2784 | − if (idpf_tx_maybe_stop_splitq(tx_q, count)) { | |
| 2570 | + if (idpf_tx_maybe_stop_splitq(tx_q, count, buf_count)) { | |
| 2785 | 2571 | idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false); |
| 2786 | 2572 | |
| 2787 | 2573 | return NETDEV_TX_BUSY; |
| @@ -2813,36 +2599,47 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, · 25 unmodified lines | ||
| 2813 | 2599 | idpf_tx_set_tstamp_desc(ctx_desc, idx); |
| 2814 | 2600 | } |
| 2815 | 2601 | |
| 2816 | − /* record the location of the first descriptor for this packet */ | |
| 2817 | − first = &tx_q->tx_buf[tx_q->next_to_use]; | |
| 2818 | − first->skb = skb; | |
| 2602 | + if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { | |
| 2603 | + struct idpf_sw_queue *refillq = tx_q->refillq; | |
| 2819 | 2604 | |
| 2820 | − if (tso) { | |
| 2821 | − first->packets = tx_params.offload.tso_segs; | |
| 2822 | − first->bytes = skb->len + | |
| 2823 | − ((first->packets - 1) * tx_params.offload.tso_hdr_len); | |
| 2824 | − } else { | |
| 2825 | − first->packets = 1; | |
| 2826 | − first->bytes = max_t(unsigned int, skb->len, ETH_ZLEN); | |
| 2827 | − } | |
| 2605 | + /* Save refillq state in case of a packet rollback. Otherwise, | |
| 2606 | + * the tags will be leaked since they will be popped from the | |
| 2607 | + * refillq but never reposted during cleaning. | |
| 2608 | + */ | |
| 2609 | + tx_params.prev_refill_gen = | |
| 2610 | + idpf_queue_has(RFL_GEN_CHK, refillq); | |
| 2611 | + tx_params.prev_refill_ntc = refillq->next_to_clean; | |
| 2612 | + | |
| 2613 | + if (unlikely(!idpf_tx_get_free_buf_id(tx_q->refillq, | |
| 2614 | + &buf_id))) { | |
| 2615 | + if (tx_params.prev_refill_gen != | |
| 2616 | + idpf_queue_has(RFL_GEN_CHK, refillq)) | |
| 2617 | + idpf_queue_change(RFL_GEN_CHK, refillq); | |
| 2618 | + refillq->next_to_clean = tx_params.prev_refill_ntc; | |
| 2619 | + | |
| 2620 | + tx_q->next_to_use = tx_params.prev_ntu; | |
| 2621 | + return idpf_tx_drop_skb(tx_q, skb); | |
| 2622 | + } | |
| 2623 | + tx_params.compl_tag = buf_id; | |
| 2828 | 2624 | |
| 2829 | − if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { | |
| 2830 | 2625 | tx_params.dtype = IDPF_TX_DESC_DTYPE_FLEX_FLOW_SCHE; |
| 2831 | 2626 | tx_params.eop_cmd = IDPF_TXD_FLEX_FLOW_CMD_EOP; |
| 2832 | − /* Set the RE bit to catch any packets that may have not been | |
| 2833 | − * stashed during RS completion cleaning. MIN_GAP is set to | |
| 2834 | − * MIN_RING size to ensure it will be set at least once each | |
| 2835 | − * time around the ring. | |
| 2627 | + /* Set the RE bit to periodically "clean" the descriptor ring. | |
| 2628 | + * MIN_GAP is set to MIN_RING size to ensure it will be set at | |
| 2629 | + * least once each time around the ring. | |
| 2836 | 2630 | */ |
| 2837 | − if (!(tx_q->next_to_use % IDPF_TX_SPLITQ_RE_MIN_GAP)) { | |
| 2631 | + if (idpf_tx_splitq_need_re(tx_q)) { | |
| 2838 | 2632 | tx_params.eop_cmd |= IDPF_TXD_FLEX_FLOW_CMD_RE; |
| 2839 | 2633 | tx_q->txq_grp->num_completions_pending++; |
| 2634 | + tx_q->last_re = tx_q->next_to_use; | |
| 2840 | 2635 | } |
| 2841 | 2636 | |
| 2842 | 2637 | if (skb->ip_summed == CHECKSUM_PARTIAL) |
| 2843 | 2638 | tx_params.offload.td_cmd |= IDPF_TXD_FLEX_FLOW_CMD_CS_EN; |
| 2844 | 2639 | |
| 2845 | 2640 | } else { |
| 2641 | + buf_id = tx_q->next_to_use; | |
| 2642 | + | |
| 2846 | 2643 | tx_params.dtype = IDPF_TX_DESC_DTYPE_FLEX_L2TAG1_L2TAG2; |
| 2847 | 2644 | tx_params.eop_cmd = IDPF_TXD_LAST_DESC_CMD; |
| 2848 | 2645 | |
| @@ -2850,6 +2647,18 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, · 1 unmodified line | ||
| 2850 | 2647 | tx_params.offload.td_cmd |= IDPF_TX_FLEX_DESC_CMD_CS_EN; |
| 2851 | 2648 | } |
| 2852 | 2649 | |
| 2650 | + first = &tx_q->tx_buf[buf_id]; | |
| 2651 | + first->skb = skb; | |
| 2652 | + | |
| 2653 | + if (tso) { | |
| 2654 | + first->packets = tx_params.offload.tso_segs; | |
| 2655 | + first->bytes = skb->len + | |
| 2656 | + ((first->packets - 1) * tx_params.offload.tso_hdr_len); | |
| 2657 | + } else { | |
| 2658 | + first->packets = 1; | |
| 2659 | + first->bytes = max_t(unsigned int, skb->len, ETH_ZLEN); | |
| 2660 | + } | |
| 2661 | + | |
| 2853 | 2662 | idpf_tx_splitq_map(tx_q, &tx_params, first); |
| 2854 | 2663 | |
| 2855 | 2664 | return NETDEV_TX_OK; |
| @@ -3387,7 +3196,7 @@ payload: · 531 unmodified lines | ||
| 3387 | 3196 | skip_data: |
| 3388 | 3197 | rx_buf->netmem = 0; |
| 3389 | 3198 | |
| 3390 | − idpf_rx_post_buf_refill(refillq, buf_id); | |
| 3199 | + idpf_post_buf_refill(refillq, buf_id); | |
| 3391 | 3200 | IDPF_RX_BUMP_NTC(rxq, ntc); |
| 3392 | 3201 | |
| 3393 | 3202 | /* skip if it is non EOP desc */ |
| @@ -3495,10 +3304,10 @@ static void idpf_rx_clean_refillq(struct idpf_buf_queue *bufq, · 101 unmodified lines | ||
| 3495 | 3304 | bool failure; |
| 3496 | 3305 | |
| 3497 | 3306 | if (idpf_queue_has(RFL_GEN_CHK, refillq) != |
| 3498 | − !!(refill_desc & IDPF_RX_BI_GEN_M)) | |
| 3307 | + !!(refill_desc & IDPF_RFL_BI_GEN_M)) | |
| 3499 | 3308 | break; |
| 3500 | 3309 | |
| 3501 | − buf_id = FIELD_GET(IDPF_RX_BI_BUFID_M, refill_desc); | |
| 3310 | + buf_id = FIELD_GET(IDPF_RFL_BI_BUFID_M, refill_desc); | |
| 3502 | 3311 | failure = idpf_rx_update_bufq_desc(bufq, buf_id, buf_desc); |
| 3503 | 3312 | if (failure) |
| 3504 | 3313 | break; |
| @@ -108,8 +108,8 @@ do { \ · 107 unmodified lines | ||
| 108 | 108 | */ |
| 109 | 109 | #define IDPF_TX_SPLITQ_RE_MIN_GAP 64 |
| 110 | 110 | |
| 111 | −#define IDPF_RX_BI_GEN_M BIT(16) | |
| 112 | −#define IDPF_RX_BI_BUFID_M GENMASK(15, 0) | |
| 111 | +#define IDPF_RFL_BI_GEN_M BIT(16) | |
| 112 | +#define IDPF_RFL_BI_BUFID_M GENMASK(15, 0) | |
| 113 | 113 | |
| 114 | 114 | #define IDPF_RXD_EOF_SPLITQ VIRTCHNL2_RX_FLEX_DESC_ADV_STATUS0_EOF_M |
| 115 | 115 | #define IDPF_RXD_EOF_SINGLEQ VIRTCHNL2_RX_BASE_DESC_STATUS_EOF_M |
| @@ -118,10 +118,6 @@ do { \ · 2 unmodified lines | ||
| 118 | 118 | ((((txq)->next_to_clean > (txq)->next_to_use) ? 0 : (txq)->desc_count) + \ |
| 119 | 119 | (txq)->next_to_clean - (txq)->next_to_use - 1) |
| 120 | 120 | |
| 121 | −#define IDPF_TX_BUF_RSV_UNUSED(txq) ((txq)->stash->buf_stack.top) | |
| 122 | −#define IDPF_TX_BUF_RSV_LOW(txq) (IDPF_TX_BUF_RSV_UNUSED(txq) < \ | |
| 123 | − (txq)->desc_count >> 2) | |
| 124 | − | |
| 125 | 121 | #define IDPF_TX_COMPLQ_OVERFLOW_THRESH(txcq) ((txcq)->desc_count >> 1) |
| 126 | 122 | /* Determine the absolute number of completions pending, i.e. the number of |
| 127 | 123 | * completions that are expected to arrive on the TX completion queue. |
| @@ -131,11 +127,7 @@ do { \ · 3 unmodified lines | ||
| 131 | 127 | 0 : U32_MAX) + \ |
| 132 | 128 | (txq)->num_completions_pending - (txq)->complq->num_completions) |
| 133 | 129 | |
| 134 | −#define IDPF_TX_SPLITQ_COMPL_TAG_WIDTH 16 | |
| 135 | −/* Adjust the generation for the completion tag and wrap if necessary */ | |
| 136 | −#define IDPF_TX_ADJ_COMPL_TAG_GEN(txq) \ | |
| 137 | − ((++(txq)->compl_tag_cur_gen) >= (txq)->compl_tag_gen_max ? \ | |
| 138 | − 0 : (txq)->compl_tag_cur_gen) | |
| 130 | +#define IDPF_TXBUF_NULL U32_MAX | |
| 139 | 131 | |
| 140 | 132 | #define IDPF_TXD_LAST_DESC_CMD (IDPF_TX_DESC_CMD_EOP | IDPF_TX_DESC_CMD_RS) |
| 141 | 133 | |
| @@ -152,18 +144,6 @@ union idpf_tx_flex_desc { · 10 unmodified lines | ||
| 152 | 144 | |
| 153 | 145 | #define idpf_tx_buf libeth_sqe |
| 154 | 146 | |
| 155 | −/** | |
| 156 | − * struct idpf_buf_lifo - LIFO for managing OOO completions | |
| 157 | − * @top: Used to know how many buffers are left | |
| 158 | − * @size: Total size of LIFO | |
| 159 | − * @bufs: Backing array | |
| 160 | − */ | |
| 161 | −struct idpf_buf_lifo { | |
| 162 | − u16 top; | |
| 163 | − u16 size; | |
| 164 | − struct idpf_tx_stash **bufs; | |
| 165 | −}; | |
| 166 | − | |
| 167 | 147 | /** |
| 168 | 148 | * struct idpf_tx_offload_params - Offload parameters for a given packet |
| 169 | 149 | * @tx_flags: Feature flags enabled for this packet |
| @@ -196,6 +176,9 @@ struct idpf_tx_offload_params { · 26 unmodified lines | ||
| 196 | 176 | * @compl_tag: Associated tag for completion |
| 197 | 177 | * @td_tag: Descriptor tunneling tag |
| 198 | 178 | * @offload: Offload parameters |
| 179 | + * @prev_ntu: stored TxQ next_to_use in case of rollback | |
| 180 | + * @prev_refill_ntc: stored refillq next_to_clean in case of packet rollback | |
| 181 | + * @prev_refill_gen: stored refillq generation bit in case of packet rollback | |
| 199 | 182 | */ |
| 200 | 183 | struct idpf_tx_splitq_params { |
| 201 | 184 | enum idpf_tx_desc_dtype_value dtype; |
| @@ -206,6 +189,10 @@ struct idpf_tx_splitq_params { · 4 unmodified lines | ||
| 206 | 189 | }; |
| 207 | 190 | |
| 208 | 191 | struct idpf_tx_offload_params offload; |
| 192 | + | |
| 193 | + u16 prev_ntu; | |
| 194 | + u16 prev_refill_ntc; | |
| 195 | + bool prev_refill_gen; | |
| 209 | 196 | }; |
| 210 | 197 | |
| 211 | 198 | enum idpf_tx_ctx_desc_eipt_offload { |
| @@ -467,17 +454,6 @@ struct idpf_tx_queue_stats { · 255 unmodified lines | ||
| 467 | 454 | #define IDPF_ITR_IDX_SPACING(spacing, dflt) (spacing ? spacing : dflt) |
| 468 | 455 | #define IDPF_DIM_DEFAULT_PROFILE_IX 1 |
| 469 | 456 | |
| 470 | −/** | |
| 471 | − * struct idpf_txq_stash - Tx buffer stash for Flow-based scheduling mode | |
| 472 | − * @buf_stack: Stack of empty buffers to store buffer info for out of order | |
| 473 | − * buffer completions. See struct idpf_buf_lifo | |
| 474 | − * @sched_buf_hash: Hash table to store buffers | |
| 475 | − */ | |
| 476 | −struct idpf_txq_stash { | |
| 477 | − struct idpf_buf_lifo buf_stack; | |
| 478 | − DECLARE_HASHTABLE(sched_buf_hash, 12); | |
| 479 | −} ____cacheline_aligned; | |
| 480 | − | |
| 481 | 457 | /** |
| 482 | 458 | * struct idpf_rx_queue - software structure representing a receive queue |
| 483 | 459 | * @rx: universal receive descriptor array |
| @@ -610,6 +586,8 @@ libeth_cacheline_set_assert(struct idpf_rx_queue, 64, · 126 unmodified lines | ||
| 610 | 586 | * @netdev: &net_device corresponding to this queue |
| 611 | 587 | * @next_to_use: Next descriptor to use |
| 612 | 588 | * @next_to_clean: Next descriptor to clean |
| 589 | + * @last_re: last descriptor index that RE bit was set | |
| 590 | + * @tx_max_bufs: Max buffers that can be transmitted with scatter-gather | |
| 613 | 591 | * @cleaned_bytes: Splitq only, TXQ only: When a TX completion is received on |
| 614 | 592 | * the TX completion queue, it can be for any TXQ associated |
| 615 | 593 | * with that completion queue. This means we can clean up to |
| @@ -620,11 +598,7 @@ libeth_cacheline_set_assert(struct idpf_rx_queue, 64, · 4 unmodified lines | ||
| 620 | 598 | * only once at the end of the cleaning routine. |
| 621 | 599 | * @clean_budget: singleq only, queue cleaning budget |
| 622 | 600 | * @cleaned_pkts: Number of packets cleaned for the above said case |
| 623 | − * @tx_max_bufs: Max buffers that can be transmitted with scatter-gather | |
| 624 | − * @stash: Tx buffer stash for Flow-based scheduling mode | |
| 625 | − * @compl_tag_bufid_m: Completion tag buffer id mask | |
| 626 | − * @compl_tag_cur_gen: Used to keep track of current completion tag generation | |
| 627 | − * @compl_tag_gen_max: To determine when compl_tag_cur_gen should be reset | |
| 601 | + * @refillq: Pointer to refill queue | |
| 628 | 602 | * @cached_tstamp_caps: Tx timestamp capabilities negotiated with the CP |
| 629 | 603 | * @tstamp_task: Work that handles Tx timestamp read |
| 630 | 604 | * @stats_sync: See struct u64_stats_sync |
| @@ -633,6 +607,7 @@ libeth_cacheline_set_assert(struct idpf_rx_queue, 64, · 2 unmodified lines | ||
| 633 | 607 | * @size: Length of descriptor ring in bytes |
| 634 | 608 | * @dma: Physical address of ring |
| 635 | 609 | * @q_vector: Backreference to associated vector |
| 610 | + * @buf_pool_size: Total number of idpf_tx_buf | |
| 636 | 611 | */ |
| 637 | 612 | struct idpf_tx_queue { |
| 638 | 613 | __cacheline_group_begin_aligned(read_mostly); |
| @@ -654,7 +629,6 @@ struct idpf_tx_queue { · 15 unmodified lines | ||
| 654 | 629 | u16 desc_count; |
| 655 | 630 | |
| 656 | 631 | u16 tx_min_pkt_len; |
| 657 | − u16 compl_tag_gen_s; | |
| 658 | 632 | |
| 659 | 633 | struct net_device *netdev; |
| 660 | 634 | __cacheline_group_end_aligned(read_mostly); |
| @@ -662,6 +636,8 @@ struct idpf_tx_queue { · 1 unmodified line | ||
| 662 | 636 | __cacheline_group_begin_aligned(read_write); |
| 663 | 637 | u16 next_to_use; |
| 664 | 638 | u16 next_to_clean; |
| 639 | + u16 last_re; | |
| 640 | + u16 tx_max_bufs; | |
| 665 | 641 | |
| 666 | 642 | union { |
| 667 | 643 | u32 cleaned_bytes; |
| @@ -669,12 +645,7 @@ struct idpf_tx_queue { · 1 unmodified line | ||
| 669 | 645 | }; |
| 670 | 646 | u16 cleaned_pkts; |
| 671 | 647 | |
| 672 | − u16 tx_max_bufs; | |
| 673 | − struct idpf_txq_stash *stash; | |
| 674 | − | |
| 675 | − u16 compl_tag_bufid_m; | |
| 676 | − u16 compl_tag_cur_gen; | |
| 677 | − u16 compl_tag_gen_max; | |
| 648 | + struct idpf_sw_queue *refillq; | |
| 678 | 649 | |
| 679 | 650 | struct idpf_ptp_vport_tx_tstamp_caps *cached_tstamp_caps; |
| 680 | 651 | struct work_struct *tstamp_task; |
| @@ -689,11 +660,12 @@ struct idpf_tx_queue { · 8 unmodified lines | ||
| 689 | 660 | dma_addr_t dma; |
| 690 | 661 | |
| 691 | 662 | struct idpf_q_vector *q_vector; |
| 663 | + u32 buf_pool_size; | |
| 692 | 664 | __cacheline_group_end_aligned(cold); |
| 693 | 665 | }; |
| 694 | 666 | libeth_cacheline_set_assert(struct idpf_tx_queue, 64, |
| 695 | − 112 + sizeof(struct u64_stats_sync), | |
| 696 | − 24); | |
| 667 | + 104 + sizeof(struct u64_stats_sync), | |
| 668 | + 32); | |
| 697 | 669 | |
| 698 | 670 | /** |
| 699 | 671 | * struct idpf_buf_queue - software structure representing a buffer queue |
| @@ -903,7 +875,6 @@ struct idpf_rxq_group { · 203 unmodified lines | ||
| 903 | 875 | * @vport: Vport back pointer |
| 904 | 876 | * @num_txq: Number of TX queues associated |
| 905 | 877 | * @txqs: Array of TX queue pointers |
| 906 | − * @stashes: array of OOO stashes for the queues | |
| 907 | 878 | * @complq: Associated completion queue pointer, split queue only |
| 908 | 879 | * @num_completions_pending: Total number of completions pending for the |
| 909 | 880 | * completion queue, acculumated for all TX queues |
| @@ -918,7 +889,6 @@ struct idpf_txq_group { · 8 unmodified lines | ||
| 918 | 889 | |
| 919 | 890 | u16 num_txq; |
| 920 | 891 | struct idpf_tx_queue *txqs[IDPF_LARGE_MAX_Q]; |
| 921 | − struct idpf_txq_stash *stashes; | |
| 922 | 892 | |
| 923 | 893 | struct idpf_compl_queue *complq; |
| 924 | 894 | |
| @@ -1011,6 +981,17 @@ static inline void idpf_vport_intr_set_wb_on_itr(struct idpf_q_vector *q_vector) · 86 unmodified lines | ||
| 1011 | 981 | reg->dyn_ctl); |
| 1012 | 982 | } |
| 1013 | 983 | |
| 984 | +/** | |
| 985 | + * idpf_tx_splitq_get_free_bufs - get number of free buf_ids in refillq | |
| 986 | + * @refillq: pointer to refillq containing buf_ids | |
| 987 | + */ | |
| 988 | +static inline u32 idpf_tx_splitq_get_free_bufs(struct idpf_sw_queue *refillq) | |
| 989 | +{ | |
| 990 | + return (refillq->next_to_use > refillq->next_to_clean ? | |
| 991 | + 0 : refillq->desc_count) + | |
| 992 | + refillq->next_to_use - refillq->next_to_clean - 1; | |
| 993 | +} | |
| 994 | + | |
| 1014 | 995 | int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget); |
| 1015 | 996 | void idpf_vport_init_num_qs(struct idpf_vport *vport, |
| 1016 | 997 | struct virtchnl2_create_vport *vport_msg); |
| @@ -1038,10 +1019,8 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val, · 21 unmodified lines | ||
| 1038 | 1019 | bool xmit_more); |
| 1039 | 1020 | unsigned int idpf_size_to_txd_count(unsigned int size); |
| 1040 | 1021 | netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb); |
| 1041 | −void idpf_tx_dma_map_error(struct idpf_tx_queue *txq, struct sk_buff *skb, | |
| 1042 | − struct idpf_tx_buf *first, u16 ring_idx); | |
| 1043 | −unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, | |
| 1044 | − struct sk_buff *skb); | |
| 1022 | +unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq, | |
| 1023 | + struct sk_buff *skb, u32 *buf_count); | |
| 1045 | 1024 | void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue); |
| 1046 | 1025 | netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, |
| 1047 | 1026 | struct idpf_tx_queue *tx_q); |
| @@ -3125,7 +3125,7 @@ static int ixgbe_get_orom_ver_info(struct ixgbe_hw *hw, · 3124 unmodified lines | ||
| 3125 | 3125 | if (err) |
| 3126 | 3126 | return err; |
| 3127 | 3127 | |
| 3128 | − combo_ver = le32_to_cpu(civd.combo_ver); | |
| 3128 | + combo_ver = get_unaligned_le32(&civd.combo_ver); | |
| 3129 | 3129 | |
| 3130 | 3130 | orom->major = (u8)FIELD_GET(IXGBE_OROM_VER_MASK, combo_ver); |
| 3131 | 3131 | orom->patch = (u8)FIELD_GET(IXGBE_OROM_VER_PATCH_MASK, combo_ver); |
| @@ -932,7 +932,7 @@ struct ixgbe_orom_civd_info { · 931 unmodified lines | ||
| 932 | 932 | __le32 combo_ver; /* Combo Image Version number */ |
| 933 | 933 | u8 combo_name_len; /* Length of the unicode combo image version string, max of 32 */ |
| 934 | 934 | __le16 combo_name[32]; /* Unicode string representing the Combo Image version */ |
| 935 | −}; | |
| 935 | +} __packed; | |
| 936 | 936 | |
| 937 | 937 | /* Function specific capabilities */ |
| 938 | 938 | struct ixgbe_hw_func_caps { |
| @@ -1978,6 +1978,13 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 1977 unmodified lines | ||
| 1978 | 1978 | goto err_release_regions; |
| 1979 | 1979 | } |
| 1980 | 1980 | |
| 1981 | + if (!is_cn20k(pdev) && | |
| 1982 | + !is_cgx_mapped_to_nix(pdev->subsystem_device, cgx->cgx_id)) { | |
| 1983 | + dev_notice(dev, "CGX %d not mapped to NIX, skipping probe\n", | |
| 1984 | + cgx->cgx_id); | |
| 1985 | + goto err_release_regions; | |
| 1986 | + } | |
| 1987 | + | |
| 1981 | 1988 | cgx->lmac_count = cgx->mac_ops->get_nr_lmacs(cgx); |
| 1982 | 1989 | if (!cgx->lmac_count) { |
| 1983 | 1990 | dev_notice(dev, "CGX %d LMAC count is zero, skipping probe\n", cgx->cgx_id); |
| @@ -783,6 +783,20 @@ static inline bool is_cn10kb(struct rvu *rvu) · 782 unmodified lines | ||
| 783 | 783 | return false; |
| 784 | 784 | } |
| 785 | 785 | |
| 786 | +static inline bool is_cgx_mapped_to_nix(unsigned short id, u8 cgx_id) | |
| 787 | +{ | |
| 788 | + /* On CNF10KA and CNF10KB silicons only two CGX blocks are connected | |
| 789 | + * to NIX. | |
| 790 | + */ | |
| 791 | + if (id == PCI_SUBSYS_DEVID_CNF10K_A || id == PCI_SUBSYS_DEVID_CNF10K_B) | |
| 792 | + return cgx_id <= 1; | |
| 793 | + | |
| 794 | + return !(cgx_id && !(id == PCI_SUBSYS_DEVID_96XX || | |
| 795 | + id == PCI_SUBSYS_DEVID_98XX || | |
| 796 | + id == PCI_SUBSYS_DEVID_CN10K_A || | |
| 797 | + id == PCI_SUBSYS_DEVID_CN10K_B)); | |
| 798 | +} | |
| 799 | + | |
| 786 | 800 | static inline bool is_rvu_npc_hash_extract_en(struct rvu *rvu) |
| 787 | 801 | { |
| 788 | 802 | u64 npc_const3; |
| @@ -124,7 +124,9 @@ void otx2_get_dev_stats(struct otx2_nic *pfvf) · 123 unmodified lines | ||
| 124 | 124 | dev_stats->rx_ucast_frames; |
| 125 | 125 | |
| 126 | 126 | dev_stats->tx_bytes = OTX2_GET_TX_STATS(TX_OCTS); |
| 127 | − dev_stats->tx_drops = OTX2_GET_TX_STATS(TX_DROP); | |
| 127 | + dev_stats->tx_drops = OTX2_GET_TX_STATS(TX_DROP) + | |
| 128 | + (unsigned long)atomic_long_read(&dev_stats->tx_discards); | |
| 129 | + | |
| 128 | 130 | dev_stats->tx_bcast_frames = OTX2_GET_TX_STATS(TX_BCAST); |
| 129 | 131 | dev_stats->tx_mcast_frames = OTX2_GET_TX_STATS(TX_MCAST); |
| 130 | 132 | dev_stats->tx_ucast_frames = OTX2_GET_TX_STATS(TX_UCAST); |
| @@ -153,6 +153,7 @@ struct otx2_dev_stats { · 152 unmodified lines | ||
| 153 | 153 | u64 tx_bcast_frames; |
| 154 | 154 | u64 tx_mcast_frames; |
| 155 | 155 | u64 tx_drops; |
| 156 | + atomic_long_t tx_discards; | |
| 156 | 157 | }; |
| 157 | 158 | |
| 158 | 159 | /* Driver counted stats */ |
| @@ -2220,6 +2220,7 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev) · 2219 unmodified lines | ||
| 2220 | 2220 | { |
| 2221 | 2221 | struct otx2_nic *pf = netdev_priv(netdev); |
| 2222 | 2222 | int qidx = skb_get_queue_mapping(skb); |
| 2223 | + struct otx2_dev_stats *dev_stats; | |
| 2223 | 2224 | struct otx2_snd_queue *sq; |
| 2224 | 2225 | struct netdev_queue *txq; |
| 2225 | 2226 | int sq_idx; |
| @@ -2232,6 +2233,8 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev) · 6 unmodified lines | ||
| 2232 | 2233 | /* Check for minimum and maximum packet length */ |
| 2233 | 2234 | if (skb->len <= ETH_HLEN || |
| 2234 | 2235 | (!skb_shinfo(skb)->gso_size && skb->len > pf->tx_max_pktlen)) { |
| 2236 | + dev_stats = &pf->hw.dev_stats; | |
| 2237 | + atomic_long_inc(&dev_stats->tx_discards); | |
| 2235 | 2238 | dev_kfree_skb(skb); |
| 2236 | 2239 | return NETDEV_TX_OK; |
| 2237 | 2240 | } |
| @@ -417,9 +417,19 @@ static netdev_tx_t otx2vf_xmit(struct sk_buff *skb, struct net_device *netdev) · 416 unmodified lines | ||
| 417 | 417 | { |
| 418 | 418 | struct otx2_nic *vf = netdev_priv(netdev); |
| 419 | 419 | int qidx = skb_get_queue_mapping(skb); |
| 420 | + struct otx2_dev_stats *dev_stats; | |
| 420 | 421 | struct otx2_snd_queue *sq; |
| 421 | 422 | struct netdev_queue *txq; |
| 422 | 423 | |
| 424 | + /* Check for minimum and maximum packet length */ | |
| 425 | + if (skb->len <= ETH_HLEN || | |
| 426 | + (!skb_shinfo(skb)->gso_size && skb->len > vf->tx_max_pktlen)) { | |
| 427 | + dev_stats = &vf->hw.dev_stats; | |
| 428 | + atomic_long_inc(&dev_stats->tx_discards); | |
| 429 | + dev_kfree_skb(skb); | |
| 430 | + return NETDEV_TX_OK; | |
| 431 | + } | |
| 432 | + | |
| 423 | 433 | sq = &vf->qset.sq[qidx]; |
| 424 | 434 | txq = netdev_get_tx_queue(netdev, qidx); |
| 425 | 435 | |
| @@ -371,7 +371,8 @@ static void rvu_rep_get_stats(struct work_struct *work) · 370 unmodified lines | ||
| 371 | 371 | stats->rx_mcast_frames = rsp->rx.mcast; |
| 372 | 372 | stats->tx_bytes = rsp->tx.octs; |
| 373 | 373 | stats->tx_frames = rsp->tx.ucast + rsp->tx.bcast + rsp->tx.mcast; |
| 374 | − stats->tx_drops = rsp->tx.drop; | |
| 374 | + stats->tx_drops = rsp->tx.drop + | |
| 375 | + (unsigned long)atomic_long_read(&stats->tx_discards); | |
| 375 | 376 | exit: |
| 376 | 377 | mutex_unlock(&priv->mbox.lock); |
| 377 | 378 | } |
| @@ -418,6 +419,16 @@ static netdev_tx_t rvu_rep_xmit(struct sk_buff *skb, struct net_device *dev) · 40 unmodified lines | ||
| 418 | 419 | struct otx2_nic *pf = rep->mdev; |
| 419 | 420 | struct otx2_snd_queue *sq; |
| 420 | 421 | struct netdev_queue *txq; |
| 422 | + struct rep_stats *stats; | |
| 423 | + | |
| 424 | + /* Check for minimum and maximum packet length */ | |
| 425 | + if (skb->len <= ETH_HLEN || | |
| 426 | + (!skb_shinfo(skb)->gso_size && skb->len > pf->tx_max_pktlen)) { | |
| 427 | + stats = &rep->stats; | |
| 428 | + atomic_long_inc(&stats->tx_discards); | |
| 429 | + dev_kfree_skb(skb); | |
| 430 | + return NETDEV_TX_OK; | |
| 431 | + } | |
| 421 | 432 | |
| 422 | 433 | sq = &pf->qset.sq[rep->rep_id]; |
| 423 | 434 | txq = netdev_get_tx_queue(dev, 0); |
| @@ -27,6 +27,7 @@ struct rep_stats { · 26 unmodified lines | ||
| 27 | 27 | u64 tx_bytes; |
| 28 | 28 | u64 tx_frames; |
| 29 | 29 | u64 tx_drops; |
| 30 | + atomic_long_t tx_discards; | |
| 30 | 31 | }; |
| 31 | 32 | |
| 32 | 33 | struct rep_dev { |
| @@ -160,7 +160,7 @@ static int mlx5_devlink_reload_fw_activate(struct devlink *devlink, struct netli · 159 unmodified lines | ||
| 160 | 160 | if (err) |
| 161 | 161 | return err; |
| 162 | 162 | |
| 163 | − mlx5_unload_one_devl_locked(dev, true); | |
| 163 | + mlx5_sync_reset_unload_flow(dev, true); | |
| 164 | 164 | err = mlx5_health_wait_pci_up(dev); |
| 165 | 165 | if (err) |
| 166 | 166 | NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); |
| @@ -575,7 +575,6 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, · 574 unmodified lines | ||
| 575 | 575 | if (err) |
| 576 | 576 | return err; |
| 577 | 577 | } |
| 578 | − priv->dcbx.xoff = xoff; | |
| 579 | 578 | |
| 580 | 579 | /* Apply the settings */ |
| 581 | 580 | if (update_buffer) { |
| @@ -584,6 +583,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, · 2 unmodified lines | ||
| 584 | 583 | return err; |
| 585 | 584 | } |
| 586 | 585 | |
| 586 | + priv->dcbx.xoff = xoff; | |
| 587 | + | |
| 587 | 588 | if (update_prio2buffer) |
| 588 | 589 | err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); |
| 589 | 590 | |
| @@ -66,11 +66,23 @@ struct mlx5e_port_buffer { · 65 unmodified lines | ||
| 66 | 66 | struct mlx5e_bufferx_reg buffer[MLX5E_MAX_NETWORK_BUFFER]; |
| 67 | 67 | }; |
| 68 | 68 | |
| 69 | +#ifdef CONFIG_MLX5_CORE_EN_DCB | |
| 69 | 70 | int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, |
| 70 | 71 | u32 change, unsigned int mtu, |
| 71 | 72 | struct ieee_pfc *pfc, |
| 72 | 73 | u32 *buffer_size, |
| 73 | 74 | u8 *prio2buffer); |
| 75 | +#else | |
| 76 | +static inline int | |
| 77 | +mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, | |
| 78 | + u32 change, unsigned int mtu, | |
| 79 | + void *pfc, | |
| 80 | + u32 *buffer_size, | |
| 81 | + u8 *prio2buffer) | |
| 82 | +{ | |
| 83 | + return 0; | |
| 84 | +} | |
| 85 | +#endif | |
| 74 | 86 | |
| 75 | 87 | int mlx5e_port_query_buffer(struct mlx5e_priv *priv, |
| 76 | 88 | struct mlx5e_port_buffer *port_buffer); |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | #include "en.h" |
| 50 | 50 | #include "en/dim.h" |
| 51 | 51 | #include "en/txrx.h" |
| 52 | +#include "en/port_buffer.h" | |
| 52 | 53 | #include "en_tc.h" |
| 53 | 54 | #include "en_rep.h" |
| 54 | 55 | #include "en_accel/ipsec.h" |
| @@ -138,6 +139,8 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv) · 83 unmodified lines | ||
| 138 | 139 | if (up) { |
| 139 | 140 | netdev_info(priv->netdev, "Link up\n"); |
| 140 | 141 | netif_carrier_on(priv->netdev); |
| 142 | + mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu, | |
| 143 | + NULL, NULL, NULL); | |
| 141 | 144 | } else { |
| 142 | 145 | netdev_info(priv->netdev, "Link down\n"); |
| 143 | 146 | netif_carrier_off(priv->netdev); |
| @@ -3040,9 +3043,11 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) · 2896 unmodified lines | ||
| 3040 | 3043 | struct mlx5e_params *params = &priv->channels.params; |
| 3041 | 3044 | struct net_device *netdev = priv->netdev; |
| 3042 | 3045 | struct mlx5_core_dev *mdev = priv->mdev; |
| 3043 | − u16 mtu; | |
| 3046 | + u16 mtu, prev_mtu; | |
| 3044 | 3047 | int err; |
| 3045 | 3048 | |
| 3049 | + mlx5e_query_mtu(mdev, params, &prev_mtu); | |
| 3050 | + | |
| 3046 | 3051 | err = mlx5e_set_mtu(mdev, params, params->sw_mtu); |
| 3047 | 3052 | if (err) |
| 3048 | 3053 | return err; |
| @@ -3052,6 +3057,18 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_priv *priv) · 3 unmodified lines | ||
| 3052 | 3057 | netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n", |
| 3053 | 3058 | __func__, mtu, params->sw_mtu); |
| 3054 | 3059 | |
| 3060 | + if (mtu != prev_mtu && MLX5_BUFFER_SUPPORTED(mdev)) { | |
| 3061 | + err = mlx5e_port_manual_buffer_config(priv, 0, mtu, | |
| 3062 | + NULL, NULL, NULL); | |
| 3063 | + if (err) { | |
| 3064 | + netdev_warn(netdev, "%s: Failed to set Xon/Xoff values with MTU %d (err %d), setting back to previous MTU %d\n", | |
| 3065 | + __func__, mtu, err, prev_mtu); | |
| 3066 | + | |
| 3067 | + mlx5e_set_mtu(mdev, params, prev_mtu); | |
| 3068 | + return err; | |
| 3069 | + } | |
| 3070 | + } | |
| 3071 | + | |
| 3055 | 3072 | params->sw_mtu = mtu; |
| 3056 | 3073 | return 0; |
| 3057 | 3074 | } |
| @@ -3734,6 +3734,13 @@ static int mlx5_fs_mode_validate(struct devlink *devlink, u32 id, · 3733 unmodified lines | ||
| 3734 | 3734 | char *value = val.vstr; |
| 3735 | 3735 | u8 eswitch_mode; |
| 3736 | 3736 | |
| 3737 | + eswitch_mode = mlx5_eswitch_mode(dev); | |
| 3738 | + if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) { | |
| 3739 | + NL_SET_ERR_MSG_FMT_MOD(extack, | |
| 3740 | + "Changing fs mode is not supported when eswitch offloads enabled."); | |
| 3741 | + return -EOPNOTSUPP; | |
| 3742 | + } | |
| 3743 | + | |
| 3737 | 3744 | if (!strcmp(value, "dmfs")) |
| 3738 | 3745 | return 0; |
| 3739 | 3746 | |
| @@ -3759,14 +3766,6 @@ static int mlx5_fs_mode_validate(struct devlink *devlink, u32 id, · 19 unmodified lines | ||
| 3759 | 3766 | return -EINVAL; |
| 3760 | 3767 | } |
| 3761 | 3768 | |
| 3762 | − eswitch_mode = mlx5_eswitch_mode(dev); | |
| 3763 | − if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) { | |
| 3764 | − NL_SET_ERR_MSG_FMT_MOD(extack, | |
| 3765 | − "Moving to %s is not supported when eswitch offloads enabled.", | |
| 3766 | − value); | |
| 3767 | − return -EOPNOTSUPP; | |
| 3768 | − } | |
| 3769 | − | |
| 3770 | 3769 | return 0; |
| 3771 | 3770 | } |
| 3772 | 3771 | |
| @@ -6,13 +6,15 @@ · 5 unmodified lines | ||
| 6 | 6 | #include "fw_reset.h" |
| 7 | 7 | #include "diag/fw_tracer.h" |
| 8 | 8 | #include "lib/tout.h" |
| 9 | +#include "sf/sf.h" | |
| 9 | 10 | |
| 10 | 11 | enum { |
| 11 | 12 | MLX5_FW_RESET_FLAGS_RESET_REQUESTED, |
| 12 | 13 | MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, |
| 13 | 14 | MLX5_FW_RESET_FLAGS_PENDING_COMP, |
| 14 | 15 | MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, |
| 15 | − MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED | |
| 16 | + MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, | |
| 17 | + MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, | |
| 16 | 18 | }; |
| 17 | 19 | |
| 18 | 20 | struct mlx5_fw_reset { |
| @@ -219,7 +221,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev) · 200 unmodified lines | ||
| 219 | 221 | return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false); |
| 220 | 222 | } |
| 221 | 223 | |
| 222 | −static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded) | |
| 224 | +static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) | |
| 223 | 225 | { |
| 224 | 226 | struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; |
| 225 | 227 | struct devlink *devlink = priv_to_devlink(dev); |
| @@ -228,8 +230,7 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unload · 2 unmodified lines | ||
| 228 | 230 | if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) { |
| 229 | 231 | complete(&fw_reset->done); |
| 230 | 232 | } else { |
| 231 | − if (!unloaded) | |
| 232 | − mlx5_unload_one(dev, false); | |
| 233 | + mlx5_sync_reset_unload_flow(dev, false); | |
| 233 | 234 | if (mlx5_health_wait_pci_up(dev)) |
| 234 | 235 | mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); |
| 235 | 236 | else |
| @@ -272,7 +273,7 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work) · 36 unmodified lines | ||
| 272 | 273 | |
| 273 | 274 | mlx5_sync_reset_clear_reset_requested(dev, false); |
| 274 | 275 | mlx5_enter_error_state(dev, true); |
| 275 | − mlx5_fw_reset_complete_reload(dev, false); | |
| 276 | + mlx5_fw_reset_complete_reload(dev); | |
| 276 | 277 | } |
| 277 | 278 | |
| 278 | 279 | #define MLX5_RESET_POLL_INTERVAL (HZ / 10) |
| @@ -428,6 +429,11 @@ static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev, · 149 unmodified lines | ||
| 428 | 429 | return false; |
| 429 | 430 | } |
| 430 | 431 | |
| 432 | + if (!mlx5_core_is_ecpf(dev) && !mlx5_sf_table_empty(dev)) { | |
| 433 | + mlx5_core_warn(dev, "SFs should be removed before reset\n"); | |
| 434 | + return false; | |
| 435 | + } | |
| 436 | + | |
| 431 | 437 | #if IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE) |
| 432 | 438 | if (reset_method != MLX5_MFRL_REG_PCI_RESET_METHOD_HOT_RESET) { |
| 433 | 439 | err = mlx5_check_hotplug_interrupt(dev, bridge); |
| @@ -586,6 +592,65 @@ static int mlx5_sync_pci_reset(struct mlx5_core_dev *dev, u8 reset_method) · 152 unmodified lines | ||
| 586 | 592 | return err; |
| 587 | 593 | } |
| 588 | 594 | |
| 595 | +void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked) | |
| 596 | +{ | |
| 597 | + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; | |
| 598 | + unsigned long timeout; | |
| 599 | + int poll_freq = 20; | |
| 600 | + bool reset_action; | |
| 601 | + u8 rst_state; | |
| 602 | + int err; | |
| 603 | + | |
| 604 | + if (locked) | |
| 605 | + mlx5_unload_one_devl_locked(dev, false); | |
| 606 | + else | |
| 607 | + mlx5_unload_one(dev, false); | |
| 608 | + | |
| 609 | + if (!test_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags)) | |
| 610 | + return; | |
| 611 | + | |
| 612 | + mlx5_set_fw_rst_ack(dev); | |
| 613 | + mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); | |
| 614 | + | |
| 615 | + reset_action = false; | |
| 616 | + timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); | |
| 617 | + do { | |
| 618 | + rst_state = mlx5_get_fw_rst_state(dev); | |
| 619 | + if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || | |
| 620 | + rst_state == MLX5_FW_RST_STATE_IDLE) { | |
| 621 | + reset_action = true; | |
| 622 | + break; | |
| 623 | + } | |
| 624 | + if (rst_state == MLX5_FW_RST_STATE_DROP_MODE) { | |
| 625 | + mlx5_core_info(dev, "Sync Reset Drop mode ack\n"); | |
| 626 | + mlx5_set_fw_rst_ack(dev); | |
| 627 | + poll_freq = 1000; | |
| 628 | + } | |
| 629 | + msleep(poll_freq); | |
| 630 | + } while (!time_after(jiffies, timeout)); | |
| 631 | + | |
| 632 | + if (!reset_action) { | |
| 633 | + mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", | |
| 634 | + rst_state); | |
| 635 | + fw_reset->ret = -ETIMEDOUT; | |
| 636 | + goto done; | |
| 637 | + } | |
| 638 | + | |
| 639 | + mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", | |
| 640 | + rst_state); | |
| 641 | + if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { | |
| 642 | + err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); | |
| 643 | + if (err) { | |
| 644 | + mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", | |
| 645 | + err); | |
| 646 | + fw_reset->ret = err; | |
| 647 | + } | |
| 648 | + } | |
| 649 | + | |
| 650 | +done: | |
| 651 | + clear_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); | |
| 652 | +} | |
| 653 | + | |
| 589 | 654 | static void mlx5_sync_reset_now_event(struct work_struct *work) |
| 590 | 655 | { |
| 591 | 656 | struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, |
| @@ -613,17 +678,13 @@ static void mlx5_sync_reset_now_event(struct work_struct *work) · 21 unmodified lines | ||
| 613 | 678 | mlx5_enter_error_state(dev, true); |
| 614 | 679 | done: |
| 615 | 680 | fw_reset->ret = err; |
| 616 | − mlx5_fw_reset_complete_reload(dev, false); | |
| 681 | + mlx5_fw_reset_complete_reload(dev); | |
| 617 | 682 | } |
| 618 | 683 | |
| 619 | 684 | static void mlx5_sync_reset_unload_event(struct work_struct *work) |
| 620 | 685 | { |
| 621 | 686 | struct mlx5_fw_reset *fw_reset; |
| 622 | 687 | struct mlx5_core_dev *dev; |
| 623 | − unsigned long timeout; | |
| 624 | − int poll_freq = 20; | |
| 625 | − bool reset_action; | |
| 626 | − u8 rst_state; | |
| 627 | 688 | int err; |
| 628 | 689 | |
| 629 | 690 | fw_reset = container_of(work, struct mlx5_fw_reset, reset_unload_work); |
| @@ -632,6 +693,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work) · 2 unmodified lines | ||
| 632 | 693 | if (mlx5_sync_reset_clear_reset_requested(dev, false)) |
| 633 | 694 | return; |
| 634 | 695 | |
| 696 | + set_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); | |
| 635 | 697 | mlx5_core_warn(dev, "Sync Reset Unload. Function is forced down.\n"); |
| 636 | 698 | |
| 637 | 699 | err = mlx5_cmd_fast_teardown_hca(dev); |
| @@ -640,49 +702,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work) · 2 unmodified lines | ||
| 640 | 702 | else |
| 641 | 703 | mlx5_enter_error_state(dev, true); |
| 642 | 704 | |
| 643 | − if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) | |
| 644 | − mlx5_unload_one_devl_locked(dev, false); | |
| 645 | − else | |
| 646 | − mlx5_unload_one(dev, false); | |
| 647 | − | |
| 648 | − mlx5_set_fw_rst_ack(dev); | |
| 649 | − mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); | |
| 650 | − | |
| 651 | − reset_action = false; | |
| 652 | − timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); | |
| 653 | − do { | |
| 654 | − rst_state = mlx5_get_fw_rst_state(dev); | |
| 655 | − if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || | |
| 656 | − rst_state == MLX5_FW_RST_STATE_IDLE) { | |
| 657 | − reset_action = true; | |
| 658 | − break; | |
| 659 | − } | |
| 660 | − if (rst_state == MLX5_FW_RST_STATE_DROP_MODE) { | |
| 661 | − mlx5_core_info(dev, "Sync Reset Drop mode ack\n"); | |
| 662 | − mlx5_set_fw_rst_ack(dev); | |
| 663 | − poll_freq = 1000; | |
| 664 | − } | |
| 665 | − msleep(poll_freq); | |
| 666 | − } while (!time_after(jiffies, timeout)); | |
| 667 | − | |
| 668 | − if (!reset_action) { | |
| 669 | − mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", | |
| 670 | − rst_state); | |
| 671 | − fw_reset->ret = -ETIMEDOUT; | |
| 672 | − goto done; | |
| 673 | − } | |
| 674 | − | |
| 675 | − mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", rst_state); | |
| 676 | − if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { | |
| 677 | − err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); | |
| 678 | − if (err) { | |
| 679 | − mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", err); | |
| 680 | − fw_reset->ret = err; | |
| 681 | − } | |
| 682 | − } | |
| 683 | − | |
| 684 | −done: | |
| 685 | − mlx5_fw_reset_complete_reload(dev, true); | |
| 705 | + mlx5_fw_reset_complete_reload(dev); | |
| 686 | 706 | } |
| 687 | 707 | |
| 688 | 708 | static void mlx5_sync_reset_abort_event(struct work_struct *work) |
| @@ -12,6 +12,7 @@ int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, · 11 unmodified lines | ||
| 12 | 12 | int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); |
| 13 | 13 | |
| 14 | 14 | int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); |
| 15 | +void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked); | |
| 15 | 16 | int mlx5_fw_reset_verify_fw_complete(struct mlx5_core_dev *dev, |
| 16 | 17 | struct netlink_ext_ack *extack); |
| 17 | 18 | void mlx5_fw_reset_events_start(struct mlx5_core_dev *dev); |
| @@ -518,3 +518,13 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) · 517 unmodified lines | ||
| 518 | 518 | WARN_ON(!xa_empty(&table->function_ids)); |
| 519 | 519 | kfree(table); |
| 520 | 520 | } |
| 521 | + | |
| 522 | +bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) | |
| 523 | +{ | |
| 524 | + struct mlx5_sf_table *table = dev->priv.sf_table; | |
| 525 | + | |
| 526 | + if (!table) | |
| 527 | + return true; | |
| 528 | + | |
| 529 | + return xa_empty(&table->function_ids); | |
| 530 | +} | |
| @@ -17,6 +17,7 @@ void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev); · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | int mlx5_sf_table_init(struct mlx5_core_dev *dev); |
| 19 | 19 | void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev); |
| 20 | +bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev); | |
| 20 | 21 | |
| 21 | 22 | int mlx5_devlink_sf_port_new(struct devlink *devlink, |
| 22 | 23 | const struct devlink_port_new_attrs *add_attr, |
| @@ -61,6 +62,11 @@ static inline void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) · 38 unmodified lines | ||
| 61 | 62 | { |
| 62 | 63 | } |
| 63 | 64 | |
| 65 | +static inline bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) | |
| 66 | +{ | |
| 67 | + return true; | |
| 68 | +} | |
| 69 | + | |
| 64 | 70 | #endif |
| 65 | 71 | |
| 66 | 72 | #endif |
| @@ -117,7 +117,7 @@ static int hws_action_get_shared_stc_nic(struct mlx5hws_context *ctx, · 116 unmodified lines | ||
| 117 | 117 | mlx5hws_err(ctx, "No such stc_type: %d\n", stc_type); |
| 118 | 118 | pr_warn("HWS: Invalid stc_type: %d\n", stc_type); |
| 119 | 119 | ret = -EINVAL; |
| 120 | − goto unlock_and_out; | |
| 120 | + goto free_shared_stc; | |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | 123 | ret = mlx5hws_action_alloc_single_stc(ctx, &stc_attr, tbl_type, |
| @@ -279,7 +279,7 @@ int mlx5hws_pat_get_pattern(struct mlx5hws_context *ctx, · 278 unmodified lines | ||
| 279 | 279 | return ret; |
| 280 | 280 | |
| 281 | 281 | clean_pattern: |
| 282 | − mlx5hws_cmd_header_modify_pattern_destroy(ctx->mdev, *pattern_id); | |
| 282 | + mlx5hws_cmd_header_modify_pattern_destroy(ctx->mdev, ptrn_id); | |
| 283 | 283 | out_unlock: |
| 284 | 284 | mutex_unlock(&ctx->pattern_cache->lock); |
| 285 | 285 | return ret; |
| @@ -527,7 +527,6 @@ int mlx5hws_pat_calc_nop(__be64 *pattern, size_t num_actions, · 241 unmodified lines | ||
| 527 | 527 | u32 *nop_locations, __be64 *new_pat) |
| 528 | 528 | { |
| 529 | 529 | u16 prev_src_field = INVALID_FIELD, prev_dst_field = INVALID_FIELD; |
| 530 | − u16 src_field, dst_field; | |
| 531 | 530 | u8 action_type; |
| 532 | 531 | bool dependent; |
| 533 | 532 | size_t i, j; |
| @@ -539,6 +538,9 @@ int mlx5hws_pat_calc_nop(__be64 *pattern, size_t num_actions, · 5 unmodified lines | ||
| 539 | 538 | return 0; |
| 540 | 539 | |
| 541 | 540 | for (i = 0, j = 0; i < num_actions; i++, j++) { |
| 541 | + u16 src_field = INVALID_FIELD; | |
| 542 | + u16 dst_field = INVALID_FIELD; | |
| 543 | + | |
| 542 | 544 | if (j >= max_actions) |
| 543 | 545 | return -EINVAL; |
| 544 | 546 | |
| @@ -124,6 +124,7 @@ static int hws_pool_buddy_init(struct mlx5hws_pool *pool) · 123 unmodified lines | ||
| 124 | 124 | mlx5hws_err(pool->ctx, "Failed to create resource type: %d size %zu\n", |
| 125 | 125 | pool->type, pool->alloc_log_sz); |
| 126 | 126 | mlx5hws_buddy_cleanup(buddy); |
| 127 | + kfree(buddy); | |
| 127 | 128 | return -ENOMEM; |
| 128 | 129 | } |
| 129 | 130 | |
| @@ -52,6 +52,8 @@ int __fbnic_open(struct fbnic_net *fbn) · 51 unmodified lines | ||
| 52 | 52 | fbnic_bmc_rpc_init(fbd); |
| 53 | 53 | fbnic_rss_reinit(fbd, fbn); |
| 54 | 54 | |
| 55 | + phylink_resume(fbn->phylink); | |
| 56 | + | |
| 55 | 57 | return 0; |
| 56 | 58 | time_stop: |
| 57 | 59 | fbnic_time_stop(fbn); |
| @@ -84,6 +86,8 @@ static int fbnic_stop(struct net_device *netdev) · 26 unmodified lines | ||
| 84 | 86 | { |
| 85 | 87 | struct fbnic_net *fbn = netdev_priv(netdev); |
| 86 | 88 | |
| 89 | + phylink_suspend(fbn->phylink, fbnic_bmc_present(fbn->fbd)); | |
| 90 | + | |
| 87 | 91 | fbnic_down(fbn); |
| 88 | 92 | fbnic_pcs_free_irq(fbn->fbd); |
| 89 | 93 | |
| @@ -118,14 +118,12 @@ static void fbnic_service_task_start(struct fbnic_net *fbn) · 117 unmodified lines | ||
| 118 | 118 | struct fbnic_dev *fbd = fbn->fbd; |
| 119 | 119 | |
| 120 | 120 | schedule_delayed_work(&fbd->service_task, HZ); |
| 121 | − phylink_resume(fbn->phylink); | |
| 122 | 121 | } |
| 123 | 122 | |
| 124 | 123 | static void fbnic_service_task_stop(struct fbnic_net *fbn) |
| 125 | 124 | { |
| 126 | 125 | struct fbnic_dev *fbd = fbn->fbd; |
| 127 | 126 | |
| 128 | − phylink_suspend(fbn->phylink, fbnic_bmc_present(fbd)); | |
| 129 | 127 | cancel_delayed_work(&fbd->service_task); |
| 130 | 128 | } |
| 131 | 129 | |
| @@ -444,11 +442,10 @@ static int __fbnic_pm_resume(struct device *dev) · 312 unmodified lines | ||
| 444 | 442 | |
| 445 | 443 | /* Re-enable mailbox */ |
| 446 | 444 | err = fbnic_fw_request_mbx(fbd); |
| 445 | + devl_unlock(priv_to_devlink(fbd)); | |
| 447 | 446 | if (err) |
| 448 | 447 | goto err_free_irqs; |
| 449 | 448 | |
| 450 | − devl_unlock(priv_to_devlink(fbd)); | |
| 451 | − | |
| 452 | 449 | /* Only send log history if log buffer is empty to prevent duplicate |
| 453 | 450 | * log entries. |
| 454 | 451 | */ |
| @@ -465,20 +462,20 @@ static int __fbnic_pm_resume(struct device *dev) · 10 unmodified lines | ||
| 465 | 462 | |
| 466 | 463 | rtnl_lock(); |
| 467 | 464 | |
| 468 | − if (netif_running(netdev)) { | |
| 465 | + if (netif_running(netdev)) | |
| 469 | 466 | err = __fbnic_open(fbn); |
| 470 | − if (err) | |
| 471 | − goto err_free_mbx; | |
| 472 | − } | |
| 473 | 467 | |
| 474 | 468 | rtnl_unlock(); |
| 469 | + if (err) | |
| 470 | + goto err_free_mbx; | |
| 475 | 471 | |
| 476 | 472 | return 0; |
| 477 | 473 | err_free_mbx: |
| 478 | 474 | fbnic_fw_log_disable(fbd); |
| 479 | 475 | |
| 480 | − rtnl_unlock(); | |
| 476 | + devl_lock(priv_to_devlink(fbd)); | |
| 481 | 477 | fbnic_fw_free_mbx(fbd); |
| 478 | + devl_unlock(priv_to_devlink(fbd)); | |
| 482 | 479 | err_free_irqs: |
| 483 | 480 | fbnic_free_irqs(fbd); |
| 484 | 481 | err_invalidate_uc_addr: |
| @@ -49,6 +49,14 @@ static void dwxgmac2_core_init(struct mac_device_info *hw, · 48 unmodified lines | ||
| 49 | 49 | writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | +static void dwxgmac2_update_caps(struct stmmac_priv *priv) | |
| 53 | +{ | |
| 54 | + if (!priv->dma_cap.mbps_10_100) | |
| 55 | + priv->hw->link.caps &= ~(MAC_10 | MAC_100); | |
| 56 | + else if (!priv->dma_cap.half_duplex) | |
| 57 | + priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD); | |
| 58 | +} | |
| 59 | + | |
| 52 | 60 | static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable) |
| 53 | 61 | { |
| 54 | 62 | u32 tx = readl(ioaddr + XGMAC_TX_CONFIG); |
| @@ -1424,6 +1432,7 @@ static void dwxgmac2_set_arp_offload(struct mac_device_info *hw, bool en, · 1369 unmodified lines | ||
| 1424 | 1432 | |
| 1425 | 1433 | const struct stmmac_ops dwxgmac210_ops = { |
| 1426 | 1434 | .core_init = dwxgmac2_core_init, |
| 1435 | + .update_caps = dwxgmac2_update_caps, | |
| 1427 | 1436 | .set_mac = dwxgmac2_set_mac, |
| 1428 | 1437 | .rx_ipc = dwxgmac2_rx_ipc, |
| 1429 | 1438 | .rx_queue_enable = dwxgmac2_rx_queue_enable, |
| @@ -1532,8 +1541,8 @@ int dwxgmac2_setup(struct stmmac_priv *priv) · 102 unmodified lines | ||
| 1532 | 1541 | mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); |
| 1533 | 1542 | |
| 1534 | 1543 | mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | |
| 1535 | − MAC_1000FD | MAC_2500FD | MAC_5000FD | | |
| 1536 | − MAC_10000FD; | |
| 1544 | + MAC_10 | MAC_100 | MAC_1000FD | | |
| 1545 | + MAC_2500FD | MAC_5000FD | MAC_10000FD; | |
| 1537 | 1546 | mac->link.duplex = 0; |
| 1538 | 1547 | mac->link.speed10 = XGMAC_CONFIG_SS_10_MII; |
| 1539 | 1548 | mac->link.speed100 = XGMAC_CONFIG_SS_100_MII; |
| @@ -203,10 +203,6 @@ static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, · 202 unmodified lines | ||
| 203 | 203 | } |
| 204 | 204 | |
| 205 | 205 | writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); |
| 206 | − | |
| 207 | − /* Enable MTL RX overflow */ | |
| 208 | − value = readl(ioaddr + XGMAC_MTL_QINTEN(channel)); | |
| 209 | − writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel)); | |
| 210 | 206 | } |
| 211 | 207 | |
| 212 | 208 | static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, |
| @@ -386,8 +382,11 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, · 173 unmodified lines | ||
| 386 | 382 | static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, |
| 387 | 383 | struct dma_features *dma_cap) |
| 388 | 384 | { |
| 385 | + struct stmmac_priv *priv; | |
| 389 | 386 | u32 hw_cap; |
| 390 | 387 | |
| 388 | + priv = container_of(dma_cap, struct stmmac_priv, dma_cap); | |
| 389 | + | |
| 391 | 390 | /* MAC HW feature 0 */ |
| 392 | 391 | hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0); |
| 393 | 392 | dma_cap->edma = (hw_cap & XGMAC_HWFEAT_EDMA) >> 31; |
| @@ -410,6 +409,8 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, · 16 unmodified lines | ||
| 410 | 409 | dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4; |
| 411 | 410 | dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3; |
| 412 | 411 | dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1; |
| 412 | + if (dma_cap->mbps_1000 && priv->synopsys_id >= DWXGMAC_CORE_2_20) | |
| 413 | + dma_cap->mbps_10_100 = 1; | |
| 413 | 414 | |
| 414 | 415 | /* MAC HW feature 1 */ |
| 415 | 416 | hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1); |
| @@ -2586,6 +2586,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) · 2585 unmodified lines | ||
| 2586 | 2586 | struct netdev_queue *nq = netdev_get_tx_queue(priv->dev, queue); |
| 2587 | 2587 | struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; |
| 2588 | 2588 | struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; |
| 2589 | + bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; | |
| 2589 | 2590 | struct xsk_buff_pool *pool = tx_q->xsk_pool; |
| 2590 | 2591 | unsigned int entry = tx_q->cur_tx; |
| 2591 | 2592 | struct dma_desc *tx_desc = NULL; |
| @@ -2673,7 +2674,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) · 81 unmodified lines | ||
| 2673 | 2674 | } |
| 2674 | 2675 | |
| 2675 | 2676 | stmmac_prepare_tx_desc(priv, tx_desc, 1, xdp_desc.len, |
| 2676 | − true, priv->mode, true, true, | |
| 2677 | + csum, priv->mode, true, true, | |
| 2677 | 2678 | xdp_desc.len); |
| 2678 | 2679 | |
| 2679 | 2680 | stmmac_enable_dma_transmission(priv, priv->ioaddr, queue); |
| @@ -4988,6 +4989,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, · 2308 unmodified lines | ||
| 4988 | 4989 | { |
| 4989 | 4990 | struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; |
| 4990 | 4991 | struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; |
| 4992 | + bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; | |
| 4991 | 4993 | unsigned int entry = tx_q->cur_tx; |
| 4992 | 4994 | struct dma_desc *tx_desc; |
| 4993 | 4995 | dma_addr_t dma_addr; |
| @@ -5039,7 +5041,7 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, · 45 unmodified lines | ||
| 5039 | 5041 | stmmac_set_desc_addr(priv, tx_desc, dma_addr); |
| 5040 | 5042 | |
| 5041 | 5043 | stmmac_prepare_tx_desc(priv, tx_desc, 1, xdpf->len, |
| 5042 | − true, priv->mode, true, true, | |
| 5044 | + csum, priv->mode, true, true, | |
| 5043 | 5045 | xdpf->len); |
| 5044 | 5046 | |
| 5045 | 5047 | tx_q->tx_count_frames++; |
| @@ -1812,6 +1812,11 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, · 1811 unmodified lines | ||
| 1812 | 1812 | |
| 1813 | 1813 | /* Enable NAPI handler before init callbacks */ |
| 1814 | 1814 | netif_napi_add(ndev, &net_device->chan_table[0].napi, netvsc_poll); |
| 1815 | + napi_enable(&net_device->chan_table[0].napi); | |
| 1816 | + netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, | |
| 1817 | + &net_device->chan_table[0].napi); | |
| 1818 | + netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, | |
| 1819 | + &net_device->chan_table[0].napi); | |
| 1815 | 1820 | |
| 1816 | 1821 | /* Open the channel */ |
| 1817 | 1822 | device->channel->next_request_id_callback = vmbus_next_request_id; |
| @@ -1831,12 +1836,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, · 13 unmodified lines | ||
| 1831 | 1836 | /* Channel is opened */ |
| 1832 | 1837 | netdev_dbg(ndev, "hv_netvsc channel opened successfully\n"); |
| 1833 | 1838 | |
| 1834 | − napi_enable(&net_device->chan_table[0].napi); | |
| 1835 | − netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, | |
| 1836 | − &net_device->chan_table[0].napi); | |
| 1837 | − netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, | |
| 1838 | − &net_device->chan_table[0].napi); | |
| 1839 | − | |
| 1840 | 1839 | /* Connect with the NetVsp */ |
| 1841 | 1840 | ret = netvsc_connect_vsp(device, net_device, device_info); |
| 1842 | 1841 | if (ret != 0) { |
| @@ -1854,14 +1853,14 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device, · 11 unmodified lines | ||
| 1854 | 1853 | |
| 1855 | 1854 | close: |
| 1856 | 1855 | RCU_INIT_POINTER(net_device_ctx->nvdev, NULL); |
| 1857 | − netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL); | |
| 1858 | − netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL); | |
| 1859 | − napi_disable(&net_device->chan_table[0].napi); | |
| 1860 | 1856 | |
| 1861 | 1857 | /* Now, we can close the channel safely */ |
| 1862 | 1858 | vmbus_close(device->channel); |
| 1863 | 1859 | |
| 1864 | 1860 | cleanup: |
| 1861 | + netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL); | |
| 1862 | + netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL); | |
| 1863 | + napi_disable(&net_device->chan_table[0].napi); | |
| 1865 | 1864 | netif_napi_del(&net_device->chan_table[0].napi); |
| 1866 | 1865 | |
| 1867 | 1866 | cleanup2: |
| @@ -1252,17 +1252,26 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) · 1251 unmodified lines | ||
| 1252 | 1252 | new_sc->rqstor_size = netvsc_rqstor_size(netvsc_ring_bytes); |
| 1253 | 1253 | new_sc->max_pkt_size = NETVSC_MAX_PKT_SIZE; |
| 1254 | 1254 | |
| 1255 | + /* Enable napi before opening the vmbus channel to avoid races | |
| 1256 | + * as the host placing data on the host->guest ring may be left | |
| 1257 | + * out if napi was not enabled. | |
| 1258 | + */ | |
| 1259 | + napi_enable(&nvchan->napi); | |
| 1260 | + netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, | |
| 1261 | + &nvchan->napi); | |
| 1262 | + netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, | |
| 1263 | + &nvchan->napi); | |
| 1264 | + | |
| 1255 | 1265 | ret = vmbus_open(new_sc, netvsc_ring_bytes, |
| 1256 | 1266 | netvsc_ring_bytes, NULL, 0, |
| 1257 | 1267 | netvsc_channel_cb, nvchan); |
| 1258 | − if (ret == 0) { | |
| 1259 | − napi_enable(&nvchan->napi); | |
| 1260 | − netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, | |
| 1261 | − &nvchan->napi); | |
| 1262 | − netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, | |
| 1263 | − &nvchan->napi); | |
| 1264 | − } else { | |
| 1268 | + if (ret != 0) { | |
| 1265 | 1269 | netdev_notice(ndev, "sub channel open failed: %d\n", ret); |
| 1270 | + netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, | |
| 1271 | + NULL); | |
| 1272 | + netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, | |
| 1273 | + NULL); | |
| 1274 | + napi_disable(&nvchan->napi); | |
| 1266 | 1275 | } |
| 1267 | 1276 | |
| 1268 | 1277 | if (atomic_inc_return(&nvscdev->open_chn) == nvscdev->num_chn) |
| @@ -484,6 +484,7 @@ static inline void vsc8584_config_macsec_intr(struct phy_device *phydev) · 483 unmodified lines | ||
| 484 | 484 | void vsc85xx_link_change_notify(struct phy_device *phydev); |
| 485 | 485 | void vsc8584_config_ts_intr(struct phy_device *phydev); |
| 486 | 486 | int vsc8584_ptp_init(struct phy_device *phydev); |
| 487 | +void vsc8584_ptp_deinit(struct phy_device *phydev); | |
| 487 | 488 | int vsc8584_ptp_probe_once(struct phy_device *phydev); |
| 488 | 489 | int vsc8584_ptp_probe(struct phy_device *phydev); |
| 489 | 490 | irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev); |
| @@ -498,6 +499,9 @@ static inline int vsc8584_ptp_init(struct phy_device *phydev) · 8 unmodified lines | ||
| 498 | 499 | { |
| 499 | 500 | return 0; |
| 500 | 501 | } |
| 502 | +static inline void vsc8584_ptp_deinit(struct phy_device *phydev) | |
| 503 | +{ | |
| 504 | +} | |
| 501 | 505 | static inline int vsc8584_ptp_probe_once(struct phy_device *phydev) |
| 502 | 506 | { |
| 503 | 507 | return 0; |
| @@ -2359,9 +2359,7 @@ static int vsc85xx_probe(struct phy_device *phydev) · 2358 unmodified lines | ||
| 2359 | 2359 | |
| 2360 | 2360 | static void vsc85xx_remove(struct phy_device *phydev) |
| 2361 | 2361 | { |
| 2362 | − struct vsc8531_private *priv = phydev->priv; | |
| 2363 | − | |
| 2364 | − skb_queue_purge(&priv->rx_skbs_list); | |
| 2362 | + vsc8584_ptp_deinit(phydev); | |
| 2365 | 2363 | } |
| 2366 | 2364 | |
| 2367 | 2365 | /* Microsemi VSC85xx PHYs */ |
| @@ -1298,7 +1298,6 @@ static void vsc8584_set_input_clk_configured(struct phy_device *phydev) · 1297 unmodified lines | ||
| 1298 | 1298 | |
| 1299 | 1299 | static int __vsc8584_init_ptp(struct phy_device *phydev) |
| 1300 | 1300 | { |
| 1301 | − struct vsc8531_private *vsc8531 = phydev->priv; | |
| 1302 | 1301 | static const u32 ltc_seq_e[] = { 0, 400000, 0, 0, 0 }; |
| 1303 | 1302 | static const u8 ltc_seq_a[] = { 8, 6, 5, 4, 2 }; |
| 1304 | 1303 | u32 val; |
| @@ -1515,17 +1514,7 @@ static int __vsc8584_init_ptp(struct phy_device *phydev) · 210 unmodified lines | ||
| 1515 | 1514 | |
| 1516 | 1515 | vsc85xx_ts_eth_cmp1_sig(phydev); |
| 1517 | 1516 | |
| 1518 | − vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; | |
| 1519 | − vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; | |
| 1520 | − vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; | |
| 1521 | − vsc8531->mii_ts.ts_info = vsc85xx_ts_info; | |
| 1522 | − phydev->mii_ts = &vsc8531->mii_ts; | |
| 1523 | − | |
| 1524 | − memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); | |
| 1525 | − | |
| 1526 | − vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, | |
| 1527 | − &phydev->mdio.dev); | |
| 1528 | − return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); | |
| 1517 | + return 0; | |
| 1529 | 1518 | } |
| 1530 | 1519 | |
| 1531 | 1520 | void vsc8584_config_ts_intr(struct phy_device *phydev) |
| @@ -1552,6 +1541,16 @@ int vsc8584_ptp_init(struct phy_device *phydev) · 20 unmodified lines | ||
| 1552 | 1541 | return 0; |
| 1553 | 1542 | } |
| 1554 | 1543 | |
| 1544 | +void vsc8584_ptp_deinit(struct phy_device *phydev) | |
| 1545 | +{ | |
| 1546 | + struct vsc8531_private *vsc8531 = phydev->priv; | |
| 1547 | + | |
| 1548 | + if (vsc8531->ptp->ptp_clock) { | |
| 1549 | + ptp_clock_unregister(vsc8531->ptp->ptp_clock); | |
| 1550 | + skb_queue_purge(&vsc8531->rx_skbs_list); | |
| 1551 | + } | |
| 1552 | +} | |
| 1553 | + | |
| 1555 | 1554 | irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev) |
| 1556 | 1555 | { |
| 1557 | 1556 | struct vsc8531_private *priv = phydev->priv; |
| @@ -1612,7 +1611,16 @@ int vsc8584_ptp_probe(struct phy_device *phydev) · 54 unmodified lines | ||
| 1612 | 1611 | |
| 1613 | 1612 | vsc8531->ptp->phydev = phydev; |
| 1614 | 1613 | |
| 1615 | − return 0; | |
| 1614 | + vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; | |
| 1615 | + vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; | |
| 1616 | + vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; | |
| 1617 | + vsc8531->mii_ts.ts_info = vsc85xx_ts_info; | |
| 1618 | + phydev->mii_ts = &vsc8531->mii_ts; | |
| 1619 | + | |
| 1620 | + memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); | |
| 1621 | + vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, | |
| 1622 | + &phydev->mdio.dev); | |
| 1623 | + return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); | |
| 1616 | 1624 | } |
| 1617 | 1625 | |
| 1618 | 1626 | int vsc8584_ptp_probe_once(struct phy_device *phydev) |
| @@ -1355,6 +1355,9 @@ static const struct usb_device_id products[] = { · 1354 unmodified lines | ||
| 1355 | 1355 | {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ |
| 1356 | 1356 | {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ |
| 1357 | 1357 | {QMI_QUIRK_SET_DTR(0x1bc7, 0x1031, 3)}, /* Telit LE910C1-EUX */ |
| 1358 | + {QMI_QUIRK_SET_DTR(0x1bc7, 0x1034, 2)}, /* Telit LE910C4-WWX */ | |
| 1359 | + {QMI_QUIRK_SET_DTR(0x1bc7, 0x1037, 4)}, /* Telit LE910C4-WWX */ | |
| 1360 | + {QMI_QUIRK_SET_DTR(0x1bc7, 0x1038, 3)}, /* Telit LE910C4-WWX */ | |
| 1358 | 1361 | {QMI_QUIRK_SET_DTR(0x1bc7, 0x103a, 0)}, /* Telit LE910C4-WWX */ |
| 1359 | 1362 | {QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */ |
| 1360 | 1363 | {QMI_QUIRK_SET_DTR(0x1bc7, 0x1050, 2)}, /* Telit FN980 */ |
| @@ -5758,14 +5758,15 @@ static void virtnet_freeze_down(struct virtio_device *vdev) · 5757 unmodified lines | ||
| 5758 | 5758 | disable_rx_mode_work(vi); |
| 5759 | 5759 | flush_work(&vi->rx_mode_work); |
| 5760 | 5760 | |
| 5761 | − netif_tx_lock_bh(vi->dev); | |
| 5762 | − netif_device_detach(vi->dev); | |
| 5763 | − netif_tx_unlock_bh(vi->dev); | |
| 5764 | 5761 | if (netif_running(vi->dev)) { |
| 5765 | 5762 | rtnl_lock(); |
| 5766 | 5763 | virtnet_close(vi->dev); |
| 5767 | 5764 | rtnl_unlock(); |
| 5768 | 5765 | } |
| 5766 | + | |
| 5767 | + netif_tx_lock_bh(vi->dev); | |
| 5768 | + netif_device_detach(vi->dev); | |
| 5769 | + netif_tx_unlock_bh(vi->dev); | |
| 5769 | 5770 | } |
| 5770 | 5771 | |
| 5771 | 5772 | static int init_vqs(struct virtnet_info *vi); |
| @@ -17,8 +17,8 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | /** |
| 19 | 19 | * of_match_device - Tell if a struct device matches an of_device_id list |
| 20 | − * @matches: array of of device match structures to search in | |
| 21 | − * @dev: the of device structure to match against | |
| 20 | + * @matches: array of of_device_id match structures to search in | |
| 21 | + * @dev: the OF device structure to match against | |
| 22 | 22 | * |
| 23 | 23 | * Used by a driver to check whether an platform_device present in the |
| 24 | 24 | * system is in its list of supported devices. |
| @@ -935,10 +935,15 @@ static int of_changeset_add_prop_helper(struct of_changeset *ocs, · 934 unmodified lines | ||
| 935 | 935 | return -ENOMEM; |
| 936 | 936 | |
| 937 | 937 | ret = of_changeset_add_property(ocs, np, new_pp); |
| 938 | − if (ret) | |
| 938 | + if (ret) { | |
| 939 | 939 | __of_prop_free(new_pp); |
| 940 | + return ret; | |
| 941 | + } | |
| 940 | 942 | |
| 941 | − return ret; | |
| 943 | + new_pp->next = np->deadprops; | |
| 944 | + np->deadprops = new_pp; | |
| 945 | + | |
| 946 | + return 0; | |
| 942 | 947 | } |
| 943 | 948 | |
| 944 | 949 | /** |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/memblock.h> |
| 26 | 26 | #include <linux/kmemleak.h> |
| 27 | 27 | #include <linux/cma.h> |
| 28 | +#include <linux/dma-map-ops.h> | |
| 28 | 29 | |
| 29 | 30 | #include "of_private.h" |
| 30 | 31 | |
| @@ -175,13 +176,17 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, · 144 unmodified lines | ||
| 175 | 176 | base = dt_mem_next_cell(dt_root_addr_cells, &prop); |
| 176 | 177 | size = dt_mem_next_cell(dt_root_size_cells, &prop); |
| 177 | 178 | |
| 178 | − if (size && | |
| 179 | − early_init_dt_reserve_memory(base, size, nomap) == 0) | |
| 179 | + if (size && early_init_dt_reserve_memory(base, size, nomap) == 0) { | |
| 180 | + /* Architecture specific contiguous memory fixup. */ | |
| 181 | + if (of_flat_dt_is_compatible(node, "shared-dma-pool") && | |
| 182 | + of_get_flat_dt_prop(node, "reusable", NULL)) | |
| 183 | + dma_contiguous_early_fixup(base, size); | |
| 180 | 184 | pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", |
| 181 | 185 | uname, &base, (unsigned long)(size / SZ_1M)); |
| 182 | − else | |
| 186 | + } else { | |
| 183 | 187 | pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", |
| 184 | 188 | uname, &base, (unsigned long)(size / SZ_1M)); |
| 189 | + } | |
| 185 | 190 | |
| 186 | 191 | len -= t_len; |
| 187 | 192 | } |
| @@ -472,7 +477,10 @@ static int __init __reserved_mem_alloc_size(unsigned long node, const char *unam · 284 unmodified lines | ||
| 472 | 477 | uname, (unsigned long)(size / SZ_1M)); |
| 473 | 478 | return -ENOMEM; |
| 474 | 479 | } |
| 475 | − | |
| 480 | + /* Architecture specific contiguous memory fixup. */ | |
| 481 | + if (of_flat_dt_is_compatible(node, "shared-dma-pool") && | |
| 482 | + of_get_flat_dt_prop(node, "reusable", NULL)) | |
| 483 | + dma_contiguous_early_fixup(base, size); | |
| 476 | 484 | /* Save region in the reserved_mem array */ |
| 477 | 485 | fdt_reserved_mem_save_node(node, uname, base, size); |
| 478 | 486 | return 0; |
| @@ -771,6 +779,7 @@ int of_reserved_mem_region_to_resource(const struct device_node *np, · 292 unmodified lines | ||
| 771 | 779 | return -EINVAL; |
| 772 | 780 | |
| 773 | 781 | resource_set_range(res, rmem->base, rmem->size); |
| 782 | + res->flags = IORESOURCE_MEM; | |
| 774 | 783 | res->name = rmem->name; |
| 775 | 784 | return 0; |
| 776 | 785 | } |
| @@ -539,6 +539,7 @@ config PINCTRL_STMFX · 538 unmodified lines | ||
| 539 | 539 | tristate "STMicroelectronics STMFX GPIO expander pinctrl driver" |
| 540 | 540 | depends on I2C |
| 541 | 541 | depends on OF_GPIO |
| 542 | + depends on HAS_IOMEM | |
| 542 | 543 | select GENERIC_PINCONF |
| 543 | 544 | select GPIOLIB_IRQCHIP |
| 544 | 545 | select MFD_STMFX |
| @@ -2696,7 +2696,7 @@ static int airoha_pinconf_get(struct pinctrl_dev *pctrl_dev, · 2695 unmodified lines | ||
| 2696 | 2696 | arg = 1; |
| 2697 | 2697 | break; |
| 2698 | 2698 | default: |
| 2699 | − return -EOPNOTSUPP; | |
| 2699 | + return -ENOTSUPP; | |
| 2700 | 2700 | } |
| 2701 | 2701 | |
| 2702 | 2702 | *config = pinconf_to_config_packed(param, arg); |
| @@ -2788,7 +2788,7 @@ static int airoha_pinconf_set(struct pinctrl_dev *pctrl_dev, · 85 unmodified lines | ||
| 2788 | 2788 | break; |
| 2789 | 2789 | } |
| 2790 | 2790 | default: |
| 2791 | − return -EOPNOTSUPP; | |
| 2791 | + return -ENOTSUPP; | |
| 2792 | 2792 | } |
| 2793 | 2793 | } |
| 2794 | 2794 | |
| @@ -2805,10 +2805,10 @@ static int airoha_pinconf_group_get(struct pinctrl_dev *pctrl_dev, · 10 unmodified lines | ||
| 2805 | 2805 | if (airoha_pinconf_get(pctrl_dev, |
| 2806 | 2806 | airoha_pinctrl_groups[group].pins[i], |
| 2807 | 2807 | config)) |
| 2808 | − return -EOPNOTSUPP; | |
| 2808 | + return -ENOTSUPP; | |
| 2809 | 2809 | |
| 2810 | 2810 | if (i && cur_config != *config) |
| 2811 | − return -EOPNOTSUPP; | |
| 2811 | + return -ENOTSUPP; | |
| 2812 | 2812 | |
| 2813 | 2813 | cur_config = *config; |
| 2814 | 2814 | } |
| @@ -1093,7 +1093,7 @@ static const struct of_device_id aml_pctl_of_match[] = { · 1092 unmodified lines | ||
| 1093 | 1093 | { .compatible = "amlogic,pinctrl-s6", .data = &s6_priv_data, }, |
| 1094 | 1094 | { /* sentinel */ } |
| 1095 | 1095 | }; |
| 1096 | −MODULE_DEVICE_TABLE(of, aml_pctl_dt_match); | |
| 1096 | +MODULE_DEVICE_TABLE(of, aml_pctl_of_match); | |
| 1097 | 1097 | |
| 1098 | 1098 | static struct platform_driver aml_pctl_driver = { |
| 1099 | 1099 | .driver = { |
| @@ -504,7 +504,7 @@ static int init_acpi(struct device *dev) · 503 unmodified lines | ||
| 504 | 504 | |
| 505 | 505 | dev_set_drvdata(dev, &hsmp_pdev->sock[sock_ind]); |
| 506 | 506 | |
| 507 | − return ret; | |
| 507 | + return 0; | |
| 508 | 508 | } |
| 509 | 509 | |
| 510 | 510 | static const struct bin_attribute hsmp_metric_tbl_attr = { |
| @@ -356,6 +356,11 @@ ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size) · 355 unmodified lines | ||
| 356 | 356 | if (!sock || !buf) |
| 357 | 357 | return -EINVAL; |
| 358 | 358 | |
| 359 | + if (!sock->metric_tbl_addr) { | |
| 360 | + dev_err(sock->dev, "Metrics table address not available\n"); | |
| 361 | + return -ENOMEM; | |
| 362 | + } | |
| 363 | + | |
| 359 | 364 | /* Do not support lseek(), also don't allow more than the size of metric table */ |
| 360 | 365 | if (size != sizeof(struct hsmp_metric_table)) { |
| 361 | 366 | dev_err(sock->dev, "Wrong buffer size\n"); |
| @@ -28,10 +28,15 @@ static struct quirk_entry quirk_spurious_8042 = { · 27 unmodified lines | ||
| 28 | 28 | .spurious_8042 = true, |
| 29 | 29 | }; |
| 30 | 30 | |
| 31 | +static struct quirk_entry quirk_s2idle_spurious_8042 = { | |
| 32 | + .s2idle_bug_mmio = FCH_PM_BASE + FCH_PM_SCRATCH, | |
| 33 | + .spurious_8042 = true, | |
| 34 | +}; | |
| 35 | + | |
| 31 | 36 | static const struct dmi_system_id fwbug_list[] = { |
| 32 | 37 | { |
| 33 | 38 | .ident = "L14 Gen2 AMD", |
| 34 | − .driver_data = &quirk_s2idle_bug, | |
| 39 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 35 | 40 | .matches = { |
| 36 | 41 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 37 | 42 | DMI_MATCH(DMI_PRODUCT_NAME, "20X5"), |
| @@ -39,7 +44,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 39 | 44 | }, |
| 40 | 45 | { |
| 41 | 46 | .ident = "T14s Gen2 AMD", |
| 42 | − .driver_data = &quirk_s2idle_bug, | |
| 47 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 43 | 48 | .matches = { |
| 44 | 49 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 45 | 50 | DMI_MATCH(DMI_PRODUCT_NAME, "20XF"), |
| @@ -47,7 +52,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 47 | 52 | }, |
| 48 | 53 | { |
| 49 | 54 | .ident = "X13 Gen2 AMD", |
| 50 | − .driver_data = &quirk_s2idle_bug, | |
| 55 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 51 | 56 | .matches = { |
| 52 | 57 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 53 | 58 | DMI_MATCH(DMI_PRODUCT_NAME, "20XH"), |
| @@ -55,7 +60,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 55 | 60 | }, |
| 56 | 61 | { |
| 57 | 62 | .ident = "T14 Gen2 AMD", |
| 58 | − .driver_data = &quirk_s2idle_bug, | |
| 63 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 59 | 64 | .matches = { |
| 60 | 65 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 61 | 66 | DMI_MATCH(DMI_PRODUCT_NAME, "20XK"), |
| @@ -63,7 +68,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 63 | 68 | }, |
| 64 | 69 | { |
| 65 | 70 | .ident = "T14 Gen1 AMD", |
| 66 | − .driver_data = &quirk_s2idle_bug, | |
| 71 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 67 | 72 | .matches = { |
| 68 | 73 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 69 | 74 | DMI_MATCH(DMI_PRODUCT_NAME, "20UD"), |
| @@ -71,7 +76,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 71 | 76 | }, |
| 72 | 77 | { |
| 73 | 78 | .ident = "T14 Gen1 AMD", |
| 74 | − .driver_data = &quirk_s2idle_bug, | |
| 79 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 75 | 80 | .matches = { |
| 76 | 81 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 77 | 82 | DMI_MATCH(DMI_PRODUCT_NAME, "20UE"), |
| @@ -79,7 +84,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 79 | 84 | }, |
| 80 | 85 | { |
| 81 | 86 | .ident = "T14s Gen1 AMD", |
| 82 | − .driver_data = &quirk_s2idle_bug, | |
| 87 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 83 | 88 | .matches = { |
| 84 | 89 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 85 | 90 | DMI_MATCH(DMI_PRODUCT_NAME, "20UH"), |
| @@ -87,7 +92,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 87 | 92 | }, |
| 88 | 93 | { |
| 89 | 94 | .ident = "T14s Gen1 AMD", |
| 90 | − .driver_data = &quirk_s2idle_bug, | |
| 95 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 91 | 96 | .matches = { |
| 92 | 97 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 93 | 98 | DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"), |
| @@ -95,7 +100,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 95 | 100 | }, |
| 96 | 101 | { |
| 97 | 102 | .ident = "P14s Gen1 AMD", |
| 98 | − .driver_data = &quirk_s2idle_bug, | |
| 103 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 99 | 104 | .matches = { |
| 100 | 105 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 101 | 106 | DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"), |
| @@ -103,7 +108,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 103 | 108 | }, |
| 104 | 109 | { |
| 105 | 110 | .ident = "P14s Gen2 AMD", |
| 106 | − .driver_data = &quirk_s2idle_bug, | |
| 111 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 107 | 112 | .matches = { |
| 108 | 113 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 109 | 114 | DMI_MATCH(DMI_PRODUCT_NAME, "21A0"), |
| @@ -111,7 +116,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 111 | 116 | }, |
| 112 | 117 | { |
| 113 | 118 | .ident = "P14s Gen2 AMD", |
| 114 | − .driver_data = &quirk_s2idle_bug, | |
| 119 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 115 | 120 | .matches = { |
| 116 | 121 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 117 | 122 | DMI_MATCH(DMI_PRODUCT_NAME, "21A1"), |
| @@ -152,7 +157,7 @@ static const struct dmi_system_id fwbug_list[] = { · 34 unmodified lines | ||
| 152 | 157 | }, |
| 153 | 158 | { |
| 154 | 159 | .ident = "IdeaPad 1 14AMN7", |
| 155 | − .driver_data = &quirk_s2idle_bug, | |
| 160 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 156 | 161 | .matches = { |
| 157 | 162 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 158 | 163 | DMI_MATCH(DMI_PRODUCT_NAME, "82VF"), |
| @@ -160,7 +165,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 160 | 165 | }, |
| 161 | 166 | { |
| 162 | 167 | .ident = "IdeaPad 1 15AMN7", |
| 163 | − .driver_data = &quirk_s2idle_bug, | |
| 168 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 164 | 169 | .matches = { |
| 165 | 170 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 166 | 171 | DMI_MATCH(DMI_PRODUCT_NAME, "82VG"), |
| @@ -168,7 +173,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 168 | 173 | }, |
| 169 | 174 | { |
| 170 | 175 | .ident = "IdeaPad 1 15AMN7", |
| 171 | − .driver_data = &quirk_s2idle_bug, | |
| 176 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 172 | 177 | .matches = { |
| 173 | 178 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 174 | 179 | DMI_MATCH(DMI_PRODUCT_NAME, "82X5"), |
| @@ -176,7 +181,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 176 | 181 | }, |
| 177 | 182 | { |
| 178 | 183 | .ident = "IdeaPad Slim 3 14AMN8", |
| 179 | − .driver_data = &quirk_s2idle_bug, | |
| 184 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 180 | 185 | .matches = { |
| 181 | 186 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 182 | 187 | DMI_MATCH(DMI_PRODUCT_NAME, "82XN"), |
| @@ -184,7 +189,7 @@ static const struct dmi_system_id fwbug_list[] = { · 1 unmodified line | ||
| 184 | 189 | }, |
| 185 | 190 | { |
| 186 | 191 | .ident = "IdeaPad Slim 3 15AMN8", |
| 187 | − .driver_data = &quirk_s2idle_bug, | |
| 192 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 188 | 193 | .matches = { |
| 189 | 194 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 190 | 195 | DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"), |
| @@ -193,7 +198,7 @@ static const struct dmi_system_id fwbug_list[] = { · 2 unmodified lines | ||
| 193 | 198 | /* https://gitlab.freedesktop.org/drm/amd/-/issues/4434 */ |
| 194 | 199 | { |
| 195 | 200 | .ident = "Lenovo Yoga 6 13ALC6", |
| 196 | − .driver_data = &quirk_s2idle_bug, | |
| 201 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 197 | 202 | .matches = { |
| 198 | 203 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), |
| 199 | 204 | DMI_MATCH(DMI_PRODUCT_NAME, "82ND"), |
| @@ -202,7 +207,7 @@ static const struct dmi_system_id fwbug_list[] = { · 2 unmodified lines | ||
| 202 | 207 | /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */ |
| 203 | 208 | { |
| 204 | 209 | .ident = "HP Laptop 15s-eq2xxx", |
| 205 | − .driver_data = &quirk_s2idle_bug, | |
| 210 | + .driver_data = &quirk_s2idle_spurious_8042, | |
| 206 | 211 | .matches = { |
| 207 | 212 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), |
| 208 | 213 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"), |
| @@ -285,6 +290,16 @@ void amd_pmc_quirks_init(struct amd_pmc_dev *dev) · 76 unmodified lines | ||
| 285 | 290 | { |
| 286 | 291 | const struct dmi_system_id *dmi_id; |
| 287 | 292 | |
| 293 | + /* | |
| 294 | + * IRQ1 may cause an interrupt during resume even without a keyboard | |
| 295 | + * press. | |
| 296 | + * | |
| 297 | + * Affects Renoir, Cezanne and Barcelo SoCs | |
| 298 | + * | |
| 299 | + * A solution is available in PMFW 64.66.0, but it must be activated by | |
| 300 | + * SBIOS. If SBIOS is known to have the fix a quirk can be added for | |
| 301 | + * a given system to avoid workaround. | |
| 302 | + */ | |
| 288 | 303 | if (dev->cpu_id == AMD_CPU_ID_CZN) |
| 289 | 304 | dev->disable_8042_wakeup = true; |
| 290 | 305 | |
| @@ -295,6 +310,5 @@ void amd_pmc_quirks_init(struct amd_pmc_dev *dev) · 4 unmodified lines | ||
| 295 | 310 | if (dev->quirks->s2idle_bug_mmio) |
| 296 | 311 | pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", |
| 297 | 312 | dmi_id->ident); |
| 298 | − if (dev->quirks->spurious_8042) | |
| 299 | − dev->disable_8042_wakeup = true; | |
| 313 | + dev->disable_8042_wakeup = dev->quirks->spurious_8042; | |
| 300 | 314 | } |
| @@ -530,19 +530,6 @@ static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev) · 529 unmodified lines | ||
| 530 | 530 | static int amd_pmc_wa_irq1(struct amd_pmc_dev *pdev) |
| 531 | 531 | { |
| 532 | 532 | struct device *d; |
| 533 | − int rc; | |
| 534 | − | |
| 535 | − /* cezanne platform firmware has a fix in 64.66.0 */ | |
| 536 | − if (pdev->cpu_id == AMD_CPU_ID_CZN) { | |
| 537 | − if (!pdev->major) { | |
| 538 | − rc = amd_pmc_get_smu_version(pdev); | |
| 539 | − if (rc) | |
| 540 | − return rc; | |
| 541 | − } | |
| 542 | − | |
| 543 | − if (pdev->major > 64 || (pdev->major == 64 && pdev->minor > 65)) | |
| 544 | − return 0; | |
| 545 | − } | |
| 546 | 533 | |
| 547 | 534 | d = bus_find_device_by_name(&serio_bus, NULL, "serio0"); |
| 548 | 535 | if (!d) |
| @@ -39,6 +39,7 @@ struct token_sysfs_data { · 38 unmodified lines | ||
| 39 | 39 | struct smbios_device { |
| 40 | 40 | struct list_head list; |
| 41 | 41 | struct device *device; |
| 42 | + int priority; | |
| 42 | 43 | int (*call_fn)(struct calling_interface_buffer *arg); |
| 43 | 44 | }; |
| 44 | 45 | |
| @@ -145,7 +146,7 @@ int dell_smbios_error(int value) · 100 unmodified lines | ||
| 145 | 146 | } |
| 146 | 147 | EXPORT_SYMBOL_GPL(dell_smbios_error); |
| 147 | 148 | |
| 148 | −int dell_smbios_register_device(struct device *d, void *call_fn) | |
| 149 | +int dell_smbios_register_device(struct device *d, int priority, void *call_fn) | |
| 149 | 150 | { |
| 150 | 151 | struct smbios_device *priv; |
| 151 | 152 | |
| @@ -154,6 +155,7 @@ int dell_smbios_register_device(struct device *d, void *call_fn) · 2 unmodified lines | ||
| 154 | 155 | return -ENOMEM; |
| 155 | 156 | get_device(d); |
| 156 | 157 | priv->device = d; |
| 158 | + priv->priority = priority; | |
| 157 | 159 | priv->call_fn = call_fn; |
| 158 | 160 | mutex_lock(&smbios_mutex); |
| 159 | 161 | list_add_tail(&priv->list, &smbios_device_list); |
| @@ -292,28 +294,25 @@ EXPORT_SYMBOL_GPL(dell_smbios_call_filter); · 132 unmodified lines | ||
| 292 | 294 | |
| 293 | 295 | int dell_smbios_call(struct calling_interface_buffer *buffer) |
| 294 | 296 | { |
| 295 | − int (*call_fn)(struct calling_interface_buffer *) = NULL; | |
| 296 | − struct device *selected_dev = NULL; | |
| 297 | + struct smbios_device *selected = NULL; | |
| 297 | 298 | struct smbios_device *priv; |
| 298 | 299 | int ret; |
| 299 | 300 | |
| 300 | 301 | mutex_lock(&smbios_mutex); |
| 301 | 302 | list_for_each_entry(priv, &smbios_device_list, list) { |
| 302 | − if (!selected_dev || priv->device->id >= selected_dev->id) { | |
| 303 | − dev_dbg(priv->device, "Trying device ID: %d\n", | |
| 304 | − priv->device->id); | |
| 305 | − call_fn = priv->call_fn; | |
| 306 | − selected_dev = priv->device; | |
| 303 | + if (!selected || priv->priority >= selected->priority) { | |
| 304 | + dev_dbg(priv->device, "Trying device ID: %d\n", priv->priority); | |
| 305 | + selected = priv; | |
| 307 | 306 | } |
| 308 | 307 | } |
| 309 | 308 | |
| 310 | − if (!selected_dev) { | |
| 309 | + if (!selected) { | |
| 311 | 310 | ret = -ENODEV; |
| 312 | 311 | pr_err("No dell-smbios drivers are loaded\n"); |
| 313 | 312 | goto out_smbios_call; |
| 314 | 313 | } |
| 315 | 314 | |
| 316 | − ret = call_fn(buffer); | |
| 315 | + ret = selected->call_fn(buffer); | |
| 317 | 316 | |
| 318 | 317 | out_smbios_call: |
| 319 | 318 | mutex_unlock(&smbios_mutex); |
| @@ -125,8 +125,7 @@ int init_dell_smbios_smm(void) · 124 unmodified lines | ||
| 125 | 125 | if (ret) |
| 126 | 126 | goto fail_platform_device_add; |
| 127 | 127 | |
| 128 | − ret = dell_smbios_register_device(&platform_device->dev, | |
| 129 | − &dell_smbios_smm_call); | |
| 128 | + ret = dell_smbios_register_device(&platform_device->dev, 0, &dell_smbios_smm_call); | |
| 130 | 129 | if (ret) |
| 131 | 130 | goto fail_register; |
| 132 | 131 | |
| @@ -264,9 +264,7 @@ static int dell_smbios_wmi_probe(struct wmi_device *wdev, const void *context) · 263 unmodified lines | ||
| 264 | 264 | if (ret) |
| 265 | 265 | return ret; |
| 266 | 266 | |
| 267 | − /* ID is used by dell-smbios to set priority of drivers */ | |
| 268 | − wdev->dev.id = 1; | |
| 269 | − ret = dell_smbios_register_device(&wdev->dev, &dell_smbios_wmi_call); | |
| 267 | + ret = dell_smbios_register_device(&wdev->dev, 1, &dell_smbios_wmi_call); | |
| 270 | 268 | if (ret) |
| 271 | 269 | return ret; |
| 272 | 270 | |
| @@ -64,7 +64,7 @@ struct calling_interface_structure { · 63 unmodified lines | ||
| 64 | 64 | struct calling_interface_token tokens[]; |
| 65 | 65 | } __packed; |
| 66 | 66 | |
| 67 | −int dell_smbios_register_device(struct device *d, void *call_fn); | |
| 67 | +int dell_smbios_register_device(struct device *d, int priority, void *call_fn); | |
| 68 | 68 | void dell_smbios_unregister_device(struct device *d); |
| 69 | 69 | |
| 70 | 70 | int dell_smbios_error(int value); |
| @@ -92,9 +92,9 @@ static const char * const victus_thermal_profile_boards[] = { · 91 unmodified lines | ||
| 92 | 92 | "8A25" |
| 93 | 93 | }; |
| 94 | 94 | |
| 95 | −/* DMI Board names of Victus 16-s1000 laptops */ | |
| 95 | +/* DMI Board names of Victus 16-r1000 and Victus 16-s1000 laptops */ | |
| 96 | 96 | static const char * const victus_s_thermal_profile_boards[] = { |
| 97 | − "8C9C" | |
| 97 | + "8C99", "8C9C" | |
| 98 | 98 | }; |
| 99 | 99 | |
| 100 | 100 | enum hp_wmi_radio { |
| @@ -193,6 +193,10 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3 · 192 unmodified lines | ||
| 193 | 193 | *con_id = "privacy-led"; |
| 194 | 194 | *gpio_flags = GPIO_ACTIVE_HIGH; |
| 195 | 195 | break; |
| 196 | + case INT3472_GPIO_TYPE_HOTPLUG_DETECT: | |
| 197 | + *con_id = "hpd"; | |
| 198 | + *gpio_flags = GPIO_ACTIVE_HIGH; | |
| 199 | + break; | |
| 196 | 200 | case INT3472_GPIO_TYPE_POWER_ENABLE: |
| 197 | 201 | *con_id = "avdd"; |
| 198 | 202 | *gpio_flags = GPIO_ACTIVE_HIGH; |
| @@ -223,6 +227,7 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3 · 24 unmodified lines | ||
| 223 | 227 | * 0x0b Power enable |
| 224 | 228 | * 0x0c Clock enable |
| 225 | 229 | * 0x0d Privacy LED |
| 230 | + * 0x13 Hotplug detect | |
| 226 | 231 | * |
| 227 | 232 | * There are some known platform specific quirks where that does not quite |
| 228 | 233 | * hold up; for example where a pin with type 0x01 (Power down) is mapped to |
| @@ -292,6 +297,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, · 63 unmodified lines | ||
| 292 | 297 | switch (type) { |
| 293 | 298 | case INT3472_GPIO_TYPE_RESET: |
| 294 | 299 | case INT3472_GPIO_TYPE_POWERDOWN: |
| 300 | + case INT3472_GPIO_TYPE_HOTPLUG_DETECT: | |
| 295 | 301 | ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, con_id, gpio_flags); |
| 296 | 302 | if (ret) |
| 297 | 303 | err_msg = "Failed to map GPIO pin to sensor\n"; |
| @@ -192,9 +192,14 @@ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *valu · 191 unmodified lines | ||
| 192 | 192 | static int write_eff_lat_ctrl(struct uncore_data *data, unsigned int val, enum uncore_index index) |
| 193 | 193 | { |
| 194 | 194 | struct tpmi_uncore_cluster_info *cluster_info; |
| 195 | + struct tpmi_uncore_struct *uncore_root; | |
| 195 | 196 | u64 control; |
| 196 | 197 | |
| 197 | 198 | cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); |
| 199 | + uncore_root = cluster_info->uncore_root; | |
| 200 | + | |
| 201 | + if (uncore_root->write_blocked) | |
| 202 | + return -EPERM; | |
| 198 | 203 | |
| 199 | 204 | if (cluster_info->root_domain) |
| 200 | 205 | return -ENODATA; |
| @@ -40,7 +40,6 @@ struct pca9450 { · 39 unmodified lines | ||
| 40 | 40 | struct device *dev; |
| 41 | 41 | struct regmap *regmap; |
| 42 | 42 | struct gpio_desc *sd_vsel_gpio; |
| 43 | − struct notifier_block restart_nb; | |
| 44 | 43 | enum pca9450_chip_type type; |
| 45 | 44 | unsigned int rcnt; |
| 46 | 45 | int irq; |
| @@ -1100,10 +1099,9 @@ static irqreturn_t pca9450_irq_handler(int irq, void *data) · 1053 unmodified lines | ||
| 1100 | 1099 | return IRQ_HANDLED; |
| 1101 | 1100 | } |
| 1102 | 1101 | |
| 1103 | −static int pca9450_i2c_restart_handler(struct notifier_block *nb, | |
| 1104 | − unsigned long action, void *data) | |
| 1102 | +static int pca9450_i2c_restart_handler(struct sys_off_data *data) | |
| 1105 | 1103 | { |
| 1106 | − struct pca9450 *pca9450 = container_of(nb, struct pca9450, restart_nb); | |
| 1104 | + struct pca9450 *pca9450 = data->cb_data; | |
| 1107 | 1105 | struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev); |
| 1108 | 1106 | |
| 1109 | 1107 | dev_dbg(&i2c->dev, "Restarting device..\n"); |
| @@ -1261,10 +1259,9 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) · 151 unmodified lines | ||
| 1261 | 1259 | pca9450->sd_vsel_fixed_low = |
| 1262 | 1260 | of_property_read_bool(ldo5->dev.of_node, "nxp,sd-vsel-fixed-low"); |
| 1263 | 1261 | |
| 1264 | − pca9450->restart_nb.notifier_call = pca9450_i2c_restart_handler; | |
| 1265 | − pca9450->restart_nb.priority = PCA9450_RESTART_HANDLER_PRIORITY; | |
| 1266 | − | |
| 1267 | − if (register_restart_handler(&pca9450->restart_nb)) | |
| 1262 | + if (devm_register_sys_off_handler(&i2c->dev, SYS_OFF_MODE_RESTART, | |
| 1263 | + PCA9450_RESTART_HANDLER_PRIORITY, | |
| 1264 | + pca9450_i2c_restart_handler, pca9450)) | |
| 1268 | 1265 | dev_warn(&i2c->dev, "Failed to register restart handler\n"); |
| 1269 | 1266 | |
| 1270 | 1267 | dev_info(&i2c->dev, "%s probed.\n", |
| @@ -454,9 +454,9 @@ static int tps65219_regulator_probe(struct platform_device *pdev) · 453 unmodified lines | ||
| 454 | 454 | irq_type->irq_name, |
| 455 | 455 | irq_data); |
| 456 | 456 | if (error) |
| 457 | − return dev_err_probe(tps->dev, PTR_ERR(rdev), | |
| 458 | − "Failed to request %s IRQ %d: %d\n", | |
| 459 | − irq_type->irq_name, irq, error); | |
| 457 | + return dev_err_probe(tps->dev, error, | |
| 458 | + "Failed to request %s IRQ %d\n", | |
| 459 | + irq_type->irq_name, irq); | |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | 462 | for (i = 0; i < pmic->dev_irq_size; ++i) { |
| @@ -477,9 +477,9 @@ static int tps65219_regulator_probe(struct platform_device *pdev) · 14 unmodified lines | ||
| 477 | 477 | irq_type->irq_name, |
| 478 | 478 | irq_data); |
| 479 | 479 | if (error) |
| 480 | − return dev_err_probe(tps->dev, PTR_ERR(rdev), | |
| 481 | − "Failed to request %s IRQ %d: %d\n", | |
| 482 | − irq_type->irq_name, irq, error); | |
| 480 | + return dev_err_probe(tps->dev, error, | |
| 481 | + "Failed to request %s IRQ %d\n", | |
| 482 | + irq_type->irq_name, irq); | |
| 483 | 483 | } |
| 484 | 484 | |
| 485 | 485 | return 0; |
| @@ -77,6 +77,13 @@ unsigned long sclp_console_full; · 76 unmodified lines | ||
| 77 | 77 | /* The currently active SCLP command word. */ |
| 78 | 78 | static sclp_cmdw_t active_cmd; |
| 79 | 79 | |
| 80 | +static inline struct sccb_header *sclpint_to_sccb(u32 sccb_int) | |
| 81 | +{ | |
| 82 | + if (sccb_int) | |
| 83 | + return __va(sccb_int); | |
| 84 | + return NULL; | |
| 85 | +} | |
| 86 | + | |
| 80 | 87 | static inline void sclp_trace(int prio, char *id, u32 a, u64 b, bool err) |
| 81 | 88 | { |
| 82 | 89 | struct sclp_trace_entry e; |
| @@ -620,7 +627,7 @@ __sclp_find_req(u32 sccb) · 537 unmodified lines | ||
| 620 | 627 | |
| 621 | 628 | static bool ok_response(u32 sccb_int, sclp_cmdw_t cmd) |
| 622 | 629 | { |
| 623 | − struct sccb_header *sccb = (struct sccb_header *)__va(sccb_int); | |
| 630 | + struct sccb_header *sccb = sclpint_to_sccb(sccb_int); | |
| 624 | 631 | struct evbuf_header *evbuf; |
| 625 | 632 | u16 response; |
| 626 | 633 | |
| @@ -659,7 +666,7 @@ static void sclp_interrupt_handler(struct ext_code ext_code, · 32 unmodified lines | ||
| 659 | 666 | |
| 660 | 667 | /* INT: Interrupt received (a=intparm, b=cmd) */ |
| 661 | 668 | sclp_trace_sccb(0, "INT", param32, active_cmd, active_cmd, |
| 662 | − (struct sccb_header *)__va(finished_sccb), | |
| 669 | + sclpint_to_sccb(finished_sccb), | |
| 663 | 670 | !ok_response(finished_sccb, active_cmd)); |
| 664 | 671 | |
| 665 | 672 | if (finished_sccb) { |
| @@ -323,8 +323,6 @@ enum fnic_state { · 322 unmodified lines | ||
| 323 | 323 | FNIC_IN_ETH_TRANS_FC_MODE, |
| 324 | 324 | }; |
| 325 | 325 | |
| 326 | −struct mempool; | |
| 327 | − | |
| 328 | 326 | enum fnic_role_e { |
| 329 | 327 | FNIC_ROLE_FCP_INITIATOR = 0, |
| 330 | 328 | }; |
| @@ -6606,6 +6606,8 @@ static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha, · 6605 unmodified lines | ||
| 6606 | 6606 | |
| 6607 | 6607 | ep = qla4xxx_ep_connect(ha->host, (struct sockaddr *)dst_addr, 0); |
| 6608 | 6608 | vfree(dst_addr); |
| 6609 | + if (IS_ERR(ep)) | |
| 6610 | + return NULL; | |
| 6609 | 6611 | return ep; |
| 6610 | 6612 | } |
| 6611 | 6613 | |
| @@ -330,13 +330,11 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi) · 329 unmodified lines | ||
| 330 | 330 | } |
| 331 | 331 | |
| 332 | 332 | if (config.speed_hz > perclk_rate / 2) { |
| 333 | − dev_err(fsl_lpspi->dev, | |
| 334 | − "per-clk should be at least two times of transfer speed"); | |
| 335 | − return -EINVAL; | |
| 333 | + div = 2; | |
| 334 | + } else { | |
| 335 | + div = DIV_ROUND_UP(perclk_rate, config.speed_hz); | |
| 336 | 336 | } |
| 337 | 337 | |
| 338 | − div = DIV_ROUND_UP(perclk_rate, config.speed_hz); | |
| 339 | − | |
| 340 | 338 | for (prescale = 0; prescale <= prescale_max; prescale++) { |
| 341 | 339 | scldiv = div / (1 << prescale) - 2; |
| 342 | 340 | if (scldiv >= 0 && scldiv < 256) { |
| @@ -265,6 +265,9 @@ static bool spi_mem_internal_supports_op(struct spi_mem *mem, · 264 unmodified lines | ||
| 265 | 265 | */ |
| 266 | 266 | bool spi_mem_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) |
| 267 | 267 | { |
| 268 | + /* Make sure the operation frequency is correct before going futher */ | |
| 269 | + spi_mem_adjust_op_freq(mem, (struct spi_mem_op *)op); | |
| 270 | + | |
| 268 | 271 | if (spi_mem_check_op(op)) |
| 269 | 272 | return false; |
| 270 | 273 | |
| @@ -577,6 +580,7 @@ EXPORT_SYMBOL_GPL(spi_mem_adjust_op_freq); · 306 unmodified lines | ||
| 577 | 580 | * spi_mem_calc_op_duration() - Derives the theoretical length (in ns) of an |
| 578 | 581 | * operation. This helps finding the best variant |
| 579 | 582 | * among a list of possible choices. |
| 583 | + * @mem: the SPI memory | |
| 580 | 584 | * @op: the operation to benchmark |
| 581 | 585 | * |
| 582 | 586 | * Some chips have per-op frequency limitations, PCBs usually have their own |
| @@ -210,13 +210,21 @@ static int qcom_spi_ooblayout_ecc(struct mtd_info *mtd, int section, · 209 unmodified lines | ||
| 210 | 210 | struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); |
| 211 | 211 | struct qpic_ecc *qecc = snandc->qspi->ecc; |
| 212 | 212 | |
| 213 | − if (section > 1) | |
| 214 | − return -ERANGE; | |
| 215 | − | |
| 216 | − oobregion->length = qecc->ecc_bytes_hw + qecc->spare_bytes; | |
| 217 | − oobregion->offset = mtd->oobsize - oobregion->length; | |
| 213 | + switch (section) { | |
| 214 | + case 0: | |
| 215 | + oobregion->offset = 0; | |
| 216 | + oobregion->length = qecc->bytes * (qecc->steps - 1) + | |
| 217 | + qecc->bbm_size; | |
| 218 | + return 0; | |
| 219 | + case 1: | |
| 220 | + oobregion->offset = qecc->bytes * (qecc->steps - 1) + | |
| 221 | + qecc->bbm_size + | |
| 222 | + qecc->steps * 4; | |
| 223 | + oobregion->length = mtd->oobsize - oobregion->offset; | |
| 224 | + return 0; | |
| 225 | + } | |
| 218 | 226 | |
| 219 | − return 0; | |
| 227 | + return -ERANGE; | |
| 220 | 228 | } |
| 221 | 229 | |
| 222 | 230 | static int qcom_spi_ooblayout_free(struct mtd_info *mtd, int section, |
| @@ -1196,7 +1204,7 @@ static int qcom_spi_program_oob(struct qcom_nand_controller *snandc, · 973 unmodified lines | ||
| 1196 | 1204 | u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; |
| 1197 | 1205 | |
| 1198 | 1206 | cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | |
| 1199 | − FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); | |
| 1207 | + FIELD_PREP(CW_PER_PAGE_MASK, 0); | |
| 1200 | 1208 | cfg1 = ecc_cfg->cfg1; |
| 1201 | 1209 | ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; |
| 1202 | 1210 | ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; |
| @@ -378,7 +378,7 @@ static void spi_st_remove(struct platform_device *pdev) · 377 unmodified lines | ||
| 378 | 378 | pinctrl_pm_select_sleep_state(&pdev->dev); |
| 379 | 379 | } |
| 380 | 380 | |
| 381 | −static int __maybe_unused spi_st_runtime_suspend(struct device *dev) | |
| 381 | +static int spi_st_runtime_suspend(struct device *dev) | |
| 382 | 382 | { |
| 383 | 383 | struct spi_controller *host = dev_get_drvdata(dev); |
| 384 | 384 | struct spi_st *spi_st = spi_controller_get_devdata(host); |
| @@ -391,7 +391,7 @@ static int __maybe_unused spi_st_runtime_suspend(struct device *dev) · 6 unmodified lines | ||
| 391 | 391 | return 0; |
| 392 | 392 | } |
| 393 | 393 | |
| 394 | −static int __maybe_unused spi_st_runtime_resume(struct device *dev) | |
| 394 | +static int spi_st_runtime_resume(struct device *dev) | |
| 395 | 395 | { |
| 396 | 396 | struct spi_controller *host = dev_get_drvdata(dev); |
| 397 | 397 | struct spi_st *spi_st = spi_controller_get_devdata(host); |
| @@ -428,8 +428,8 @@ static int __maybe_unused spi_st_resume(struct device *dev) · 30 unmodified lines | ||
| 428 | 428 | } |
| 429 | 429 | |
| 430 | 430 | static const struct dev_pm_ops spi_st_pm = { |
| 431 | − SET_SYSTEM_SLEEP_PM_OPS(spi_st_suspend, spi_st_resume) | |
| 432 | − SET_RUNTIME_PM_OPS(spi_st_runtime_suspend, spi_st_runtime_resume, NULL) | |
| 431 | + SYSTEM_SLEEP_PM_OPS(spi_st_suspend, spi_st_resume) | |
| 432 | + RUNTIME_PM_OPS(spi_st_runtime_suspend, spi_st_runtime_resume, NULL) | |
| 433 | 433 | }; |
| 434 | 434 | |
| 435 | 435 | static const struct of_device_id stm_spi_match[] = { |
| @@ -441,7 +441,7 @@ MODULE_DEVICE_TABLE(of, stm_spi_match); · 5 unmodified lines | ||
| 441 | 441 | static struct platform_driver spi_st_driver = { |
| 442 | 442 | .driver = { |
| 443 | 443 | .name = "spi-st", |
| 444 | − .pm = pm_sleep_ptr(&spi_st_pm), | |
| 444 | + .pm = pm_ptr(&spi_st_pm), | |
| 445 | 445 | .of_match_table = of_match_ptr(stm_spi_match), |
| 446 | 446 | }, |
| 447 | 447 | .probe = spi_st_probe, |
| @@ -1303,7 +1303,7 @@ static u32 ufshcd_pending_cmds(struct ufs_hba *hba) · 1302 unmodified lines | ||
| 1303 | 1303 | * |
| 1304 | 1304 | * Return: 0 upon success; -EBUSY upon timeout. |
| 1305 | 1305 | */ |
| 1306 | −static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, | |
| 1306 | +static int ufshcd_wait_for_pending_cmds(struct ufs_hba *hba, | |
| 1307 | 1307 | u64 wait_timeout_us) |
| 1308 | 1308 | { |
| 1309 | 1309 | int ret = 0; |
| @@ -1431,7 +1431,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) · 121 unmodified lines | ||
| 1431 | 1431 | down_write(&hba->clk_scaling_lock); |
| 1432 | 1432 | |
| 1433 | 1433 | if (!hba->clk_scaling.is_allowed || |
| 1434 | − ufshcd_wait_for_doorbell_clr(hba, timeout_us)) { | |
| 1434 | + ufshcd_wait_for_pending_cmds(hba, timeout_us)) { | |
| 1435 | 1435 | ret = -EBUSY; |
| 1436 | 1436 | up_write(&hba->clk_scaling_lock); |
| 1437 | 1437 | mutex_unlock(&hba->wb_mutex); |
| @@ -3199,7 +3199,8 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) · 1761 unmodified lines | ||
| 3199 | 3199 | } |
| 3200 | 3200 | |
| 3201 | 3201 | /* |
| 3202 | − * Return: 0 upon success; < 0 upon failure. | |
| 3202 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3203 | + * < 0 if another error occurred. | |
| 3203 | 3204 | */ |
| 3204 | 3205 | static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, |
| 3205 | 3206 | struct ufshcd_lrb *lrbp, int max_timeout) |
| @@ -3275,7 +3276,6 @@ retry: · 69 unmodified lines | ||
| 3275 | 3276 | } |
| 3276 | 3277 | } |
| 3277 | 3278 | |
| 3278 | − WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err); | |
| 3279 | 3279 | return err; |
| 3280 | 3280 | } |
| 3281 | 3281 | |
| @@ -3294,7 +3294,8 @@ static void ufshcd_dev_man_unlock(struct ufs_hba *hba) · 12 unmodified lines | ||
| 3294 | 3294 | } |
| 3295 | 3295 | |
| 3296 | 3296 | /* |
| 3297 | − * Return: 0 upon success; < 0 upon failure. | |
| 3297 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3298 | + * < 0 if another error occurred. | |
| 3298 | 3299 | */ |
| 3299 | 3300 | static int ufshcd_issue_dev_cmd(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, |
| 3300 | 3301 | const u32 tag, int timeout) |
| @@ -3317,7 +3318,8 @@ static int ufshcd_issue_dev_cmd(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, · 16 unmodified lines | ||
| 3317 | 3318 | * @cmd_type: specifies the type (NOP, Query...) |
| 3318 | 3319 | * @timeout: timeout in milliseconds |
| 3319 | 3320 | * |
| 3320 | − * Return: 0 upon success; < 0 upon failure. | |
| 3321 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3322 | + * < 0 if another error occurred. | |
| 3321 | 3323 | * |
| 3322 | 3324 | * NOTE: Since there is only one available tag for device management commands, |
| 3323 | 3325 | * it is expected you hold the hba->dev_cmd.lock mutex. |
| @@ -3363,6 +3365,10 @@ static inline void ufshcd_init_query(struct ufs_hba *hba, · 39 unmodified lines | ||
| 3363 | 3365 | (*request)->upiu_req.selector = selector; |
| 3364 | 3366 | } |
| 3365 | 3367 | |
| 3368 | +/* | |
| 3369 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3370 | + * < 0 if another error occurred. | |
| 3371 | + */ | |
| 3366 | 3372 | static int ufshcd_query_flag_retry(struct ufs_hba *hba, |
| 3367 | 3373 | enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res) |
| 3368 | 3374 | { |
| @@ -3383,7 +3389,6 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba, · 14 unmodified lines | ||
| 3383 | 3389 | dev_err(hba->dev, |
| 3384 | 3390 | "%s: query flag, opcode %d, idn %d, failed with error %d after %d retries\n", |
| 3385 | 3391 | __func__, opcode, idn, ret, retries); |
| 3386 | − WARN_ONCE(ret > 0, "Incorrect return value %d > 0\n", ret); | |
| 3387 | 3392 | return ret; |
| 3388 | 3393 | } |
| 3389 | 3394 | |
| @@ -3395,7 +3400,8 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba, · 5 unmodified lines | ||
| 3395 | 3400 | * @index: flag index to access |
| 3396 | 3401 | * @flag_res: the flag value after the query request completes |
| 3397 | 3402 | * |
| 3398 | − * Return: 0 for success; < 0 upon failure. | |
| 3403 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3404 | + * < 0 if another error occurred. | |
| 3399 | 3405 | */ |
| 3400 | 3406 | int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, |
| 3401 | 3407 | enum flag_idn idn, u8 index, bool *flag_res) |
| @@ -3451,7 +3457,6 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, · 49 unmodified lines | ||
| 3451 | 3457 | |
| 3452 | 3458 | out_unlock: |
| 3453 | 3459 | ufshcd_dev_man_unlock(hba); |
| 3454 | − WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err); | |
| 3455 | 3460 | return err; |
| 3456 | 3461 | } |
| 3457 | 3462 | |
| @@ -3464,8 +3469,9 @@ out_unlock: · 6 unmodified lines | ||
| 3464 | 3469 | * @selector: selector field |
| 3465 | 3470 | * @attr_val: the attribute value after the query request completes |
| 3466 | 3471 | * |
| 3467 | − * Return: 0 upon success; < 0 upon failure. | |
| 3468 | −*/ | |
| 3472 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3473 | + * < 0 if another error occurred. | |
| 3474 | + */ | |
| 3469 | 3475 | int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, |
| 3470 | 3476 | enum attr_idn idn, u8 index, u8 selector, u32 *attr_val) |
| 3471 | 3477 | { |
| @@ -3513,7 +3519,6 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, · 41 unmodified lines | ||
| 3513 | 3519 | |
| 3514 | 3520 | out_unlock: |
| 3515 | 3521 | ufshcd_dev_man_unlock(hba); |
| 3516 | − WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err); | |
| 3517 | 3522 | return err; |
| 3518 | 3523 | } |
| 3519 | 3524 | |
| @@ -3528,8 +3533,9 @@ out_unlock: · 8 unmodified lines | ||
| 3528 | 3533 | * @attr_val: the attribute value after the query request |
| 3529 | 3534 | * completes |
| 3530 | 3535 | * |
| 3531 | − * Return: 0 for success; < 0 upon failure. | |
| 3532 | −*/ | |
| 3536 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3537 | + * < 0 if another error occurred. | |
| 3538 | + */ | |
| 3533 | 3539 | int ufshcd_query_attr_retry(struct ufs_hba *hba, |
| 3534 | 3540 | enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector, |
| 3535 | 3541 | u32 *attr_val) |
| @@ -3551,12 +3557,12 @@ int ufshcd_query_attr_retry(struct ufs_hba *hba, · 15 unmodified lines | ||
| 3551 | 3557 | dev_err(hba->dev, |
| 3552 | 3558 | "%s: query attribute, idn %d, failed with error %d after %d retries\n", |
| 3553 | 3559 | __func__, idn, ret, QUERY_REQ_RETRIES); |
| 3554 | − WARN_ONCE(ret > 0, "Incorrect return value %d > 0\n", ret); | |
| 3555 | 3560 | return ret; |
| 3556 | 3561 | } |
| 3557 | 3562 | |
| 3558 | 3563 | /* |
| 3559 | − * Return: 0 if successful; < 0 upon failure. | |
| 3564 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3565 | + * < 0 if another error occurred. | |
| 3560 | 3566 | */ |
| 3561 | 3567 | static int __ufshcd_query_descriptor(struct ufs_hba *hba, |
| 3562 | 3568 | enum query_opcode opcode, enum desc_idn idn, u8 index, |
| @@ -3615,7 +3621,6 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, · 52 unmodified lines | ||
| 3615 | 3621 | out_unlock: |
| 3616 | 3622 | hba->dev_cmd.query.descriptor = NULL; |
| 3617 | 3623 | ufshcd_dev_man_unlock(hba); |
| 3618 | − WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err); | |
| 3619 | 3624 | return err; |
| 3620 | 3625 | } |
| 3621 | 3626 | |
| @@ -3632,7 +3637,8 @@ out_unlock: · 10 unmodified lines | ||
| 3632 | 3637 | * The buf_len parameter will contain, on return, the length parameter |
| 3633 | 3638 | * received on the response. |
| 3634 | 3639 | * |
| 3635 | − * Return: 0 for success; < 0 upon failure. | |
| 3640 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3641 | + * < 0 if another error occurred. | |
| 3636 | 3642 | */ |
| 3637 | 3643 | int ufshcd_query_descriptor_retry(struct ufs_hba *hba, |
| 3638 | 3644 | enum query_opcode opcode, |
| @@ -3650,7 +3656,6 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba, · 11 unmodified lines | ||
| 3650 | 3656 | break; |
| 3651 | 3657 | } |
| 3652 | 3658 | |
| 3653 | − WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err); | |
| 3654 | 3659 | return err; |
| 3655 | 3660 | } |
| 3656 | 3661 | |
| @@ -3663,7 +3668,8 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba, · 6 unmodified lines | ||
| 3663 | 3668 | * @param_read_buf: pointer to buffer where parameter would be read |
| 3664 | 3669 | * @param_size: sizeof(param_read_buf) |
| 3665 | 3670 | * |
| 3666 | − * Return: 0 in case of success; < 0 upon failure. | |
| 3671 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 3672 | + * < 0 if another error occurred. | |
| 3667 | 3673 | */ |
| 3668 | 3674 | int ufshcd_read_desc_param(struct ufs_hba *hba, |
| 3669 | 3675 | enum desc_idn desc_id, |
| @@ -3730,7 +3736,6 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, · 60 unmodified lines | ||
| 3730 | 3736 | out: |
| 3731 | 3737 | if (is_kmalloc) |
| 3732 | 3738 | kfree(desc_buf); |
| 3733 | − WARN_ONCE(ret > 0, "Incorrect return value %d > 0\n", ret); | |
| 3734 | 3739 | return ret; |
| 3735 | 3740 | } |
| 3736 | 3741 | |
| @@ -4781,7 +4786,8 @@ EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode); · 1044 unmodified lines | ||
| 4781 | 4786 | * |
| 4782 | 4787 | * Set fDeviceInit flag and poll until device toggles it. |
| 4783 | 4788 | * |
| 4784 | − * Return: 0 upon success; < 0 upon failure. | |
| 4789 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 4790 | + * < 0 if another error occurred. | |
| 4785 | 4791 | */ |
| 4786 | 4792 | static int ufshcd_complete_dev_init(struct ufs_hba *hba) |
| 4787 | 4793 | { |
| @@ -5135,7 +5141,8 @@ out: · 347 unmodified lines | ||
| 5135 | 5141 | * not respond with NOP IN UPIU within timeout of %NOP_OUT_TIMEOUT |
| 5136 | 5142 | * and we retry sending NOP OUT for %NOP_OUT_RETRIES iterations. |
| 5137 | 5143 | * |
| 5138 | − * Return: 0 upon success; < 0 upon failure. | |
| 5144 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 5145 | + * < 0 if another error occurred. | |
| 5139 | 5146 | */ |
| 5140 | 5147 | static int ufshcd_verify_dev_init(struct ufs_hba *hba) |
| 5141 | 5148 | { |
| @@ -5559,9 +5566,9 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) · 417 unmodified lines | ||
| 5559 | 5566 | irqreturn_t retval = IRQ_NONE; |
| 5560 | 5567 | struct uic_command *cmd; |
| 5561 | 5568 | |
| 5562 | − spin_lock(hba->host->host_lock); | |
| 5569 | + guard(spinlock_irqsave)(hba->host->host_lock); | |
| 5563 | 5570 | cmd = hba->active_uic_cmd; |
| 5564 | − if (WARN_ON_ONCE(!cmd)) | |
| 5571 | + if (!cmd) | |
| 5565 | 5572 | goto unlock; |
| 5566 | 5573 | |
| 5567 | 5574 | if (ufshcd_is_auto_hibern8_error(hba, intr_status)) |
| @@ -5586,8 +5593,6 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) · 18 unmodified lines | ||
| 5586 | 5593 | ufshcd_add_uic_command_trace(hba, cmd, UFS_CMD_COMP); |
| 5587 | 5594 | |
| 5588 | 5595 | unlock: |
| 5589 | − spin_unlock(hba->host->host_lock); | |
| 5590 | − | |
| 5591 | 5596 | return retval; |
| 5592 | 5597 | } |
| 5593 | 5598 | |
| @@ -5869,7 +5874,8 @@ static inline int ufshcd_enable_ee(struct ufs_hba *hba, u16 mask) · 275 unmodified lines | ||
| 5869 | 5874 | * as the device is allowed to manage its own way of handling background |
| 5870 | 5875 | * operations. |
| 5871 | 5876 | * |
| 5872 | − * Return: zero on success, non-zero on failure. | |
| 5877 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 5878 | + * < 0 if another error occurred. | |
| 5873 | 5879 | */ |
| 5874 | 5880 | static int ufshcd_enable_auto_bkops(struct ufs_hba *hba) |
| 5875 | 5881 | { |
| @@ -5908,7 +5914,8 @@ out: · 32 unmodified lines | ||
| 5908 | 5914 | * host is idle so that BKOPS are managed effectively without any negative |
| 5909 | 5915 | * impacts. |
| 5910 | 5916 | * |
| 5911 | − * Return: zero on success, non-zero on failure. | |
| 5917 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 5918 | + * < 0 if another error occurred. | |
| 5912 | 5919 | */ |
| 5913 | 5920 | static int ufshcd_disable_auto_bkops(struct ufs_hba *hba) |
| 5914 | 5921 | { |
| @@ -6058,6 +6065,10 @@ out: · 143 unmodified lines | ||
| 6058 | 6065 | __func__, err); |
| 6059 | 6066 | } |
| 6060 | 6067 | |
| 6068 | +/* | |
| 6069 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 6070 | + * < 0 if another error occurred. | |
| 6071 | + */ | |
| 6061 | 6072 | int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id) |
| 6062 | 6073 | { |
| 6063 | 6074 | struct utp_upiu_query_v4_0 *upiu_resp; |
| @@ -6920,7 +6931,7 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status) · 856 unmodified lines | ||
| 6920 | 6931 | bool queue_eh_work = false; |
| 6921 | 6932 | irqreturn_t retval = IRQ_NONE; |
| 6922 | 6933 | |
| 6923 | − spin_lock(hba->host->host_lock); | |
| 6934 | + guard(spinlock_irqsave)(hba->host->host_lock); | |
| 6924 | 6935 | hba->errors |= UFSHCD_ERROR_MASK & intr_status; |
| 6925 | 6936 | |
| 6926 | 6937 | if (hba->errors & INT_FATAL_ERRORS) { |
| @@ -6979,7 +6990,7 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status) · 52 unmodified lines | ||
| 6979 | 6990 | */ |
| 6980 | 6991 | hba->errors = 0; |
| 6981 | 6992 | hba->uic_error = 0; |
| 6982 | − spin_unlock(hba->host->host_lock); | |
| 6993 | + | |
| 6983 | 6994 | return retval; |
| 6984 | 6995 | } |
| 6985 | 6996 | |
| @@ -7454,7 +7465,8 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, · 468 unmodified lines | ||
| 7454 | 7465 | * @sg_list: Pointer to SG list when DATA IN/OUT UPIU is required in ARPMB operation |
| 7455 | 7466 | * @dir: DMA direction |
| 7456 | 7467 | * |
| 7457 | − * Return: zero on success, non-zero on failure. | |
| 7468 | + * Return: 0 upon success; > 0 in case the UFS device reported an OCS error; | |
| 7469 | + * < 0 if another error occurred. | |
| 7458 | 7470 | */ |
| 7459 | 7471 | int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu, |
| 7460 | 7472 | struct utp_upiu_req *rsp_upiu, struct ufs_ehs *req_ehs, |
| @@ -2070,17 +2070,6 @@ static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *data) · 2069 unmodified lines | ||
| 2070 | 2070 | return IRQ_HANDLED; |
| 2071 | 2071 | } |
| 2072 | 2072 | |
| 2073 | −static void ufs_qcom_irq_free(struct ufs_qcom_irq *uqi) | |
| 2074 | −{ | |
| 2075 | − for (struct ufs_qcom_irq *q = uqi; q->irq; q++) | |
| 2076 | − devm_free_irq(q->hba->dev, q->irq, q->hba); | |
| 2077 | − | |
| 2078 | − platform_device_msi_free_irqs_all(uqi->hba->dev); | |
| 2079 | − devm_kfree(uqi->hba->dev, uqi); | |
| 2080 | −} | |
| 2081 | − | |
| 2082 | −DEFINE_FREE(ufs_qcom_irq, struct ufs_qcom_irq *, if (_T) ufs_qcom_irq_free(_T)) | |
| 2083 | − | |
| 2084 | 2073 | static int ufs_qcom_config_esi(struct ufs_hba *hba) |
| 2085 | 2074 | { |
| 2086 | 2075 | struct ufs_qcom_host *host = ufshcd_get_variant(hba); |
| @@ -2095,18 +2084,18 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba) · 8 unmodified lines | ||
| 2095 | 2084 | */ |
| 2096 | 2085 | nr_irqs = hba->nr_hw_queues - hba->nr_queues[HCTX_TYPE_POLL]; |
| 2097 | 2086 | |
| 2098 | − struct ufs_qcom_irq *qi __free(ufs_qcom_irq) = | |
| 2099 | − devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL); | |
| 2100 | − if (!qi) | |
| 2101 | − return -ENOMEM; | |
| 2102 | − /* Preset so __free() has a pointer to hba in all error paths */ | |
| 2103 | − qi[0].hba = hba; | |
| 2104 | − | |
| 2105 | 2087 | ret = platform_device_msi_init_and_alloc_irqs(hba->dev, nr_irqs, |
| 2106 | 2088 | ufs_qcom_write_msi_msg); |
| 2107 | 2089 | if (ret) { |
| 2108 | − dev_err(hba->dev, "Failed to request Platform MSI %d\n", ret); | |
| 2109 | − return ret; | |
| 2090 | + dev_warn(hba->dev, "Platform MSI not supported or failed, continuing without ESI\n"); | |
| 2091 | + return ret; /* Continue without ESI */ | |
| 2092 | + } | |
| 2093 | + | |
| 2094 | + struct ufs_qcom_irq *qi = devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL); | |
| 2095 | + | |
| 2096 | + if (!qi) { | |
| 2097 | + platform_device_msi_free_irqs_all(hba->dev); | |
| 2098 | + return -ENOMEM; | |
| 2110 | 2099 | } |
| 2111 | 2100 | |
| 2112 | 2101 | for (int idx = 0; idx < nr_irqs; idx++) { |
| @@ -2117,15 +2106,17 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba) · 4 unmodified lines | ||
| 2117 | 2106 | ret = devm_request_irq(hba->dev, qi[idx].irq, ufs_qcom_mcq_esi_handler, |
| 2118 | 2107 | IRQF_SHARED, "qcom-mcq-esi", qi + idx); |
| 2119 | 2108 | if (ret) { |
| 2120 | − dev_err(hba->dev, "%s: Fail to request IRQ for %d, err = %d\n", | |
| 2109 | + dev_err(hba->dev, "%s: Failed to request IRQ for %d, err = %d\n", | |
| 2121 | 2110 | __func__, qi[idx].irq, ret); |
| 2122 | − qi[idx].irq = 0; | |
| 2111 | + /* Free previously allocated IRQs */ | |
| 2112 | + for (int j = 0; j < idx; j++) | |
| 2113 | + devm_free_irq(hba->dev, qi[j].irq, qi + j); | |
| 2114 | + platform_device_msi_free_irqs_all(hba->dev); | |
| 2115 | + devm_kfree(hba->dev, qi); | |
| 2123 | 2116 | return ret; |
| 2124 | 2117 | } |
| 2125 | 2118 | } |
| 2126 | 2119 | |
| 2127 | − retain_and_null_ptr(qi); | |
| 2128 | − | |
| 2129 | 2120 | if (host->hw_ver.major >= 6) { |
| 2130 | 2121 | ufshcd_rmwl(hba, ESI_VEC_MASK, FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1), |
| 2131 | 2122 | REG_UFS_CFG3); |
| @@ -630,6 +630,7 @@ static const struct pci_device_id ufshcd_pci_tbl[] = { · 629 unmodified lines | ||
| 630 | 630 | { PCI_VDEVICE(INTEL, 0xA847), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, |
| 631 | 631 | { PCI_VDEVICE(INTEL, 0x7747), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, |
| 632 | 632 | { PCI_VDEVICE(INTEL, 0xE447), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, |
| 633 | + { PCI_VDEVICE(INTEL, 0x4D47), (kernel_ulong_t)&ufs_intel_mtl_hba_vops }, | |
| 633 | 634 | { } /* terminate list */ |
| 634 | 635 | }; |
| 635 | 636 | |
| @@ -338,7 +338,8 @@ static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event) · 337 unmodified lines | ||
| 338 | 338 | schedule_work(&ci->usb_phy->chg_work); |
| 339 | 339 | break; |
| 340 | 340 | case CI_HDRC_CONTROLLER_PULLUP_EVENT: |
| 341 | − if (ci->role == CI_ROLE_GADGET) | |
| 341 | + if (ci->role == CI_ROLE_GADGET && | |
| 342 | + ci->gadget.speed == USB_SPEED_HIGH) | |
| 342 | 343 | imx_usbmisc_pullup(data->usbmisc_data, |
| 343 | 344 | ci->gadget.connected); |
| 344 | 345 | break; |
| @@ -1068,15 +1068,24 @@ static void usbmisc_imx7d_pullup(struct imx_usbmisc_data *data, bool on) · 1067 unmodified lines | ||
| 1068 | 1068 | unsigned long flags; |
| 1069 | 1069 | u32 val; |
| 1070 | 1070 | |
| 1071 | + if (on) | |
| 1072 | + return; | |
| 1073 | + | |
| 1071 | 1074 | spin_lock_irqsave(&usbmisc->lock, flags); |
| 1072 | 1075 | val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); |
| 1073 | − if (!on) { | |
| 1074 | − val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK; | |
| 1075 | − val |= MX7D_USBNC_USB_CTRL2_OPMODE(1); | |
| 1076 | − val |= MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN; | |
| 1077 | − } else { | |
| 1078 | − val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN; | |
| 1079 | − } | |
| 1076 | + val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK; | |
| 1077 | + val |= MX7D_USBNC_USB_CTRL2_OPMODE(1); | |
| 1078 | + val |= MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN; | |
| 1079 | + writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2); | |
| 1080 | + spin_unlock_irqrestore(&usbmisc->lock, flags); | |
| 1081 | + | |
| 1082 | + /* Last for at least 1 micro-frame to let host see disconnect signal */ | |
| 1083 | + usleep_range(125, 150); | |
| 1084 | + | |
| 1085 | + spin_lock_irqsave(&usbmisc->lock, flags); | |
| 1086 | + val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK; | |
| 1087 | + val |= MX7D_USBNC_USB_CTRL2_OPMODE(0); | |
| 1088 | + val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN; | |
| 1080 | 1089 | writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2); |
| 1081 | 1090 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
| 1082 | 1091 | } |
| @@ -1636,7 +1636,6 @@ static void __usb_hcd_giveback_urb(struct urb *urb) · 1635 unmodified lines | ||
| 1636 | 1636 | struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); |
| 1637 | 1637 | struct usb_anchor *anchor = urb->anchor; |
| 1638 | 1638 | int status = urb->unlinked; |
| 1639 | − unsigned long flags; | |
| 1640 | 1639 | |
| 1641 | 1640 | urb->hcpriv = NULL; |
| 1642 | 1641 | if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && |
| @@ -1654,14 +1653,13 @@ static void __usb_hcd_giveback_urb(struct urb *urb) · 11 unmodified lines | ||
| 1654 | 1653 | /* pass ownership to the completion handler */ |
| 1655 | 1654 | urb->status = status; |
| 1656 | 1655 | /* |
| 1657 | − * Only collect coverage in the softirq context and disable interrupts | |
| 1658 | − * to avoid scenarios with nested remote coverage collection sections | |
| 1659 | − * that KCOV does not support. | |
| 1660 | − * See the comment next to kcov_remote_start_usb_softirq() for details. | |
| 1656 | + * This function can be called in task context inside another remote | |
| 1657 | + * coverage collection section, but kcov doesn't support that kind of | |
| 1658 | + * recursion yet. Only collect coverage in softirq context for now. | |
| 1661 | 1659 | */ |
| 1662 | − flags = kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum); | |
| 1660 | + kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum); | |
| 1663 | 1661 | urb->complete(urb); |
| 1664 | − kcov_remote_stop_softirq(flags); | |
| 1662 | + kcov_remote_stop_softirq(); | |
| 1665 | 1663 | |
| 1666 | 1664 | usb_anchor_resume_wakeups(anchor); |
| 1667 | 1665 | atomic_dec(&urb->use_count); |
| @@ -1719,10 +1717,10 @@ static void usb_giveback_urb_bh(struct work_struct *work) · 51 unmodified lines | ||
| 1719 | 1717 | * @urb: urb being returned to the USB device driver. |
| 1720 | 1718 | * @status: completion status code for the URB. |
| 1721 | 1719 | * |
| 1722 | − * Context: atomic. The completion callback is invoked in caller's context. | |
| 1723 | − * For HCDs with HCD_BH flag set, the completion callback is invoked in BH | |
| 1724 | − * context (except for URBs submitted to the root hub which always complete in | |
| 1725 | − * caller's context). | |
| 1720 | + * Context: atomic. The completion callback is invoked either in a work queue | |
| 1721 | + * (BH) context or in the caller's context, depending on whether the HCD_BH | |
| 1722 | + * flag is set in the @hcd structure, except that URBs submitted to the | |
| 1723 | + * root hub always complete in BH context. | |
| 1726 | 1724 | * |
| 1727 | 1725 | * This hands the URB from HCD to its USB device driver, using its |
| 1728 | 1726 | * completion function. The HCD has freed all per-urb resources |
| @@ -2166,7 +2164,7 @@ static struct urb *request_single_step_set_feature_urb( · 437 unmodified lines | ||
| 2166 | 2164 | urb->complete = usb_ehset_completion; |
| 2167 | 2165 | urb->status = -EINPROGRESS; |
| 2168 | 2166 | urb->actual_length = 0; |
| 2169 | − urb->transfer_flags = URB_DIR_IN; | |
| 2167 | + urb->transfer_flags = URB_DIR_IN | URB_NO_TRANSFER_DMA_MAP; | |
| 2170 | 2168 | usb_get_urb(urb); |
| 2171 | 2169 | atomic_inc(&urb->use_count); |
| 2172 | 2170 | atomic_inc(&urb->dev->urbnum); |
| @@ -2230,9 +2228,15 @@ int ehset_single_step_set_feature(struct usb_hcd *hcd, int port) · 57 unmodified lines | ||
| 2230 | 2228 | |
| 2231 | 2229 | /* Complete remaining DATA and STATUS stages using the same URB */ |
| 2232 | 2230 | urb->status = -EINPROGRESS; |
| 2231 | + urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP; | |
| 2233 | 2232 | usb_get_urb(urb); |
| 2234 | 2233 | atomic_inc(&urb->use_count); |
| 2235 | 2234 | atomic_inc(&urb->dev->urbnum); |
| 2235 | + if (map_urb_for_dma(hcd, urb, GFP_KERNEL)) { | |
| 2236 | + usb_put_urb(urb); | |
| 2237 | + goto out1; | |
| 2238 | + } | |
| 2239 | + | |
| 2236 | 2240 | retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 0); |
| 2237 | 2241 | if (!retval && !wait_for_completion_timeout(&done, |
| 2238 | 2242 | msecs_to_jiffies(2000))) { |
| @@ -371,6 +371,7 @@ static const struct usb_device_id usb_quirk_list[] = { · 370 unmodified lines | ||
| 371 | 371 | { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM }, |
| 372 | 372 | |
| 373 | 373 | /* SanDisk Corp. SanDisk 3.2Gen1 */ |
| 374 | + { USB_DEVICE(0x0781, 0x5596), .driver_info = USB_QUIRK_DELAY_INIT }, | |
| 374 | 375 | { USB_DEVICE(0x0781, 0x55a3), .driver_info = USB_QUIRK_DELAY_INIT }, |
| 375 | 376 | |
| 376 | 377 | /* SanDisk Extreme 55AE */ |
| @@ -41,6 +41,7 @@ · 40 unmodified lines | ||
| 41 | 41 | #define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee |
| 42 | 42 | #define PCI_DEVICE_ID_INTEL_TGPH 0x43ee |
| 43 | 43 | #define PCI_DEVICE_ID_INTEL_JSP 0x4dee |
| 44 | +#define PCI_DEVICE_ID_INTEL_WCL 0x4d7e | |
| 44 | 45 | #define PCI_DEVICE_ID_INTEL_ADL 0x460e |
| 45 | 46 | #define PCI_DEVICE_ID_INTEL_ADL_PCH 0x51ee |
| 46 | 47 | #define PCI_DEVICE_ID_INTEL_ADLN 0x465e |
| @@ -431,6 +432,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = { · 384 unmodified lines | ||
| 431 | 432 | { PCI_DEVICE_DATA(INTEL, TGPLP, &dwc3_pci_intel_swnode) }, |
| 432 | 433 | { PCI_DEVICE_DATA(INTEL, TGPH, &dwc3_pci_intel_swnode) }, |
| 433 | 434 | { PCI_DEVICE_DATA(INTEL, JSP, &dwc3_pci_intel_swnode) }, |
| 435 | + { PCI_DEVICE_DATA(INTEL, WCL, &dwc3_pci_intel_swnode) }, | |
| 434 | 436 | { PCI_DEVICE_DATA(INTEL, ADL, &dwc3_pci_intel_swnode) }, |
| 435 | 437 | { PCI_DEVICE_DATA(INTEL, ADL_PCH, &dwc3_pci_intel_swnode) }, |
| 436 | 438 | { PCI_DEVICE_DATA(INTEL, ADLN, &dwc3_pci_intel_swnode) }, |
| @@ -288,7 +288,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc) · 287 unmodified lines | ||
| 288 | 288 | dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 8, |
| 289 | 289 | DWC3_TRBCTL_CONTROL_SETUP, false); |
| 290 | 290 | ret = dwc3_ep0_start_trans(dep); |
| 291 | − WARN_ON(ret < 0); | |
| 291 | + if (ret < 0) | |
| 292 | + dev_err(dwc->dev, "ep0 out start transfer failed: %d\n", ret); | |
| 293 | + | |
| 292 | 294 | for (i = 2; i < DWC3_ENDPOINTS_NUM; i++) { |
| 293 | 295 | struct dwc3_ep *dwc3_ep; |
| 294 | 296 | |
| @@ -1061,7 +1063,9 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, · 766 unmodified lines | ||
| 1061 | 1063 | ret = dwc3_ep0_start_trans(dep); |
| 1062 | 1064 | } |
| 1063 | 1065 | |
| 1064 | − WARN_ON(ret < 0); | |
| 1066 | + if (ret < 0) | |
| 1067 | + dev_err(dwc->dev, | |
| 1068 | + "ep0 data phase start transfer failed: %d\n", ret); | |
| 1065 | 1069 | } |
| 1066 | 1070 | |
| 1067 | 1071 | static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) |
| @@ -1078,7 +1082,12 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) · 10 unmodified lines | ||
| 1078 | 1082 | |
| 1079 | 1083 | static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) |
| 1080 | 1084 | { |
| 1081 | − WARN_ON(dwc3_ep0_start_control_status(dep)); | |
| 1085 | + int ret; | |
| 1086 | + | |
| 1087 | + ret = dwc3_ep0_start_control_status(dep); | |
| 1088 | + if (ret) | |
| 1089 | + dev_err(dwc->dev, | |
| 1090 | + "ep0 status phase start transfer failed: %d\n", ret); | |
| 1082 | 1091 | } |
| 1083 | 1092 | |
| 1084 | 1093 | static void dwc3_ep0_do_control_status(struct dwc3 *dwc, |
| @@ -1121,7 +1130,10 @@ void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep) · 36 unmodified lines | ||
| 1121 | 1130 | cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); |
| 1122 | 1131 | memset(¶ms, 0, sizeof(params)); |
| 1123 | 1132 | ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); |
| 1124 | − WARN_ON_ONCE(ret); | |
| 1133 | + if (ret) | |
| 1134 | + dev_err_ratelimited(dwc->dev, | |
| 1135 | + "ep0 data phase end transfer failed: %d\n", ret); | |
| 1136 | + | |
| 1125 | 1137 | dep->resource_index = 0; |
| 1126 | 1138 | } |
| 1127 | 1139 | |
| @@ -1772,7 +1772,11 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int · 1771 unmodified lines | ||
| 1772 | 1772 | dep->flags |= DWC3_EP_DELAY_STOP; |
| 1773 | 1773 | return 0; |
| 1774 | 1774 | } |
| 1775 | − WARN_ON_ONCE(ret); | |
| 1775 | + | |
| 1776 | + if (ret) | |
| 1777 | + dev_err_ratelimited(dep->dwc->dev, | |
| 1778 | + "end transfer failed: %d\n", ret); | |
| 1779 | + | |
| 1776 | 1780 | dep->resource_index = 0; |
| 1777 | 1781 | |
| 1778 | 1782 | if (!interrupt) |
| @@ -3777,6 +3781,15 @@ static void dwc3_gadget_endpoint_transfer_complete(struct dwc3_ep *dep, · 1998 unmodified lines | ||
| 3777 | 3781 | static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep, |
| 3778 | 3782 | const struct dwc3_event_depevt *event) |
| 3779 | 3783 | { |
| 3784 | + /* | |
| 3785 | + * During a device-initiated disconnect, a late xferNotReady event can | |
| 3786 | + * be generated after the End Transfer command resets the event filter, | |
| 3787 | + * but before the controller is halted. Ignore it to prevent a new | |
| 3788 | + * transfer from starting. | |
| 3789 | + */ | |
| 3790 | + if (!dep->dwc->connected) | |
| 3791 | + return; | |
| 3792 | + | |
| 3780 | 3793 | dwc3_gadget_endpoint_frame_from_event(dep, event); |
| 3781 | 3794 | |
| 3782 | 3795 | /* |
| @@ -4039,7 +4052,9 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) · 256 unmodified lines | ||
| 4039 | 4052 | dep->flags &= ~DWC3_EP_STALL; |
| 4040 | 4053 | |
| 4041 | 4054 | ret = dwc3_send_clear_stall_ep_cmd(dep); |
| 4042 | − WARN_ON_ONCE(ret); | |
| 4055 | + if (ret) | |
| 4056 | + dev_err_ratelimited(dwc->dev, | |
| 4057 | + "failed to clear STALL on %s\n", dep->name); | |
| 4043 | 4058 | } |
| 4044 | 4059 | } |
| 4045 | 4060 | |
| @@ -502,6 +502,7 @@ struct tegra_xudc { · 501 unmodified lines | ||
| 502 | 502 | struct clk_bulk_data *clks; |
| 503 | 503 | |
| 504 | 504 | bool device_mode; |
| 505 | + bool current_device_mode; | |
| 505 | 506 | struct work_struct usb_role_sw_work; |
| 506 | 507 | |
| 507 | 508 | struct phy **usb3_phy; |
| @@ -715,6 +716,8 @@ static void tegra_xudc_device_mode_on(struct tegra_xudc *xudc) · 207 unmodified lines | ||
| 715 | 716 | |
| 716 | 717 | phy_set_mode_ext(xudc->curr_utmi_phy, PHY_MODE_USB_OTG, |
| 717 | 718 | USB_ROLE_DEVICE); |
| 719 | + | |
| 720 | + xudc->current_device_mode = true; | |
| 718 | 721 | } |
| 719 | 722 | |
| 720 | 723 | static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc) |
| @@ -725,6 +728,8 @@ static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc) · 4 unmodified lines | ||
| 725 | 728 | |
| 726 | 729 | dev_dbg(xudc->dev, "device mode off\n"); |
| 727 | 730 | |
| 731 | + xudc->current_device_mode = false; | |
| 732 | + | |
| 728 | 733 | connected = !!(xudc_readl(xudc, PORTSC) & PORTSC_CCS); |
| 729 | 734 | |
| 730 | 735 | reinit_completion(&xudc->disconnect_complete); |
| @@ -4044,10 +4049,10 @@ static int __maybe_unused tegra_xudc_resume(struct device *dev) · 3313 unmodified lines | ||
| 4044 | 4049 | |
| 4045 | 4050 | spin_lock_irqsave(&xudc->lock, flags); |
| 4046 | 4051 | xudc->suspended = false; |
| 4052 | + if (xudc->device_mode != xudc->current_device_mode) | |
| 4053 | + schedule_work(&xudc->usb_role_sw_work); | |
| 4047 | 4054 | spin_unlock_irqrestore(&xudc->lock, flags); |
| 4048 | 4055 | |
| 4049 | − schedule_work(&xudc->usb_role_sw_work); | |
| 4050 | − | |
| 4051 | 4056 | pm_runtime_enable(dev); |
| 4052 | 4057 | |
| 4053 | 4058 | return 0; |
| @@ -704,8 +704,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, · 703 unmodified lines | ||
| 704 | 704 | if (!xhci->devs[i]) |
| 705 | 705 | continue; |
| 706 | 706 | |
| 707 | − retval = xhci_disable_slot(xhci, i); | |
| 708 | − xhci_free_virt_device(xhci, i); | |
| 707 | + retval = xhci_disable_and_free_slot(xhci, i); | |
| 709 | 708 | if (retval) |
| 710 | 709 | xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n", |
| 711 | 710 | i, retval); |
| @@ -865,21 +865,20 @@ free_tts: · 864 unmodified lines | ||
| 865 | 865 | * will be manipulated by the configure endpoint, allocate device, or update |
| 866 | 866 | * hub functions while this function is removing the TT entries from the list. |
| 867 | 867 | */ |
| 868 | −void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) | |
| 868 | +void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, | |
| 869 | + int slot_id) | |
| 869 | 870 | { |
| 870 | − struct xhci_virt_device *dev; | |
| 871 | 871 | int i; |
| 872 | 872 | int old_active_eps = 0; |
| 873 | 873 | |
| 874 | 874 | /* Slot ID 0 is reserved */ |
| 875 | − if (slot_id == 0 || !xhci->devs[slot_id]) | |
| 875 | + if (slot_id == 0 || !dev) | |
| 876 | 876 | return; |
| 877 | 877 | |
| 878 | − dev = xhci->devs[slot_id]; | |
| 879 | − | |
| 880 | − xhci->dcbaa->dev_context_ptrs[slot_id] = 0; | |
| 881 | − if (!dev) | |
| 882 | − return; | |
| 878 | + /* If device ctx array still points to _this_ device, clear it */ | |
| 879 | + if (dev->out_ctx && | |
| 880 | + xhci->dcbaa->dev_context_ptrs[slot_id] == cpu_to_le64(dev->out_ctx->dma)) | |
| 881 | + xhci->dcbaa->dev_context_ptrs[slot_id] = 0; | |
| 883 | 882 | |
| 884 | 883 | trace_xhci_free_virt_device(dev); |
| 885 | 884 | |
| @@ -920,8 +919,9 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) · 34 unmodified lines | ||
| 920 | 919 | dev->udev->slot_id = 0; |
| 921 | 920 | if (dev->rhub_port && dev->rhub_port->slot_id == slot_id) |
| 922 | 921 | dev->rhub_port->slot_id = 0; |
| 923 | − kfree(xhci->devs[slot_id]); | |
| 924 | − xhci->devs[slot_id] = NULL; | |
| 922 | + if (xhci->devs[slot_id] == dev) | |
| 923 | + xhci->devs[slot_id] = NULL; | |
| 924 | + kfree(dev); | |
| 925 | 925 | } |
| 926 | 926 | |
| 927 | 927 | /* |
| @@ -962,7 +962,7 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i · 34 unmodified lines | ||
| 962 | 962 | out: |
| 963 | 963 | /* we are now at a leaf device */ |
| 964 | 964 | xhci_debugfs_remove_slot(xhci, slot_id); |
| 965 | − xhci_free_virt_device(xhci, slot_id); | |
| 965 | + xhci_free_virt_device(xhci, vdev, slot_id); | |
| 966 | 966 | } |
| 967 | 967 | |
| 968 | 968 | int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, |
| @@ -47,8 +47,9 @@ · 46 unmodified lines | ||
| 47 | 47 | #define RENESAS_ROM_ERASE_MAGIC 0x5A65726F |
| 48 | 48 | #define RENESAS_ROM_WRITE_MAGIC 0x53524F4D |
| 49 | 49 | |
| 50 | −#define RENESAS_RETRY 10000 | |
| 51 | −#define RENESAS_DELAY 10 | |
| 50 | +#define RENESAS_RETRY 50000 /* 50000 * RENESAS_DELAY ~= 500ms */ | |
| 51 | +#define RENESAS_CHIP_ERASE_RETRY 500000 /* 500000 * RENESAS_DELAY ~= 5s */ | |
| 52 | +#define RENESAS_DELAY 10 | |
| 52 | 53 | |
| 53 | 54 | #define RENESAS_FW_NAME "renesas_usb_fw.mem" |
| 54 | 55 | |
| @@ -407,7 +408,7 @@ static void renesas_rom_erase(struct pci_dev *pdev) · 352 unmodified lines | ||
| 407 | 408 | /* sleep a bit while ROM is erased */ |
| 408 | 409 | msleep(20); |
| 409 | 410 | |
| 410 | − for (i = 0; i < RENESAS_RETRY; i++) { | |
| 411 | + for (i = 0; i < RENESAS_CHIP_ERASE_RETRY; i++) { | |
| 411 | 412 | retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, |
| 412 | 413 | &status); |
| 413 | 414 | status &= RENESAS_ROM_STATUS_ERASE; |
| @@ -1592,7 +1592,8 @@ static void xhci_handle_cmd_enable_slot(int slot_id, struct xhci_command *comman · 1591 unmodified lines | ||
| 1592 | 1592 | command->slot_id = 0; |
| 1593 | 1593 | } |
| 1594 | 1594 | |
| 1595 | −static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) | |
| 1595 | +static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id, | |
| 1596 | + u32 cmd_comp_code) | |
| 1596 | 1597 | { |
| 1597 | 1598 | struct xhci_virt_device *virt_dev; |
| 1598 | 1599 | struct xhci_slot_ctx *slot_ctx; |
| @@ -1607,6 +1608,10 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) · 8 unmodified lines | ||
| 1607 | 1608 | if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) |
| 1608 | 1609 | /* Delete default control endpoint resources */ |
| 1609 | 1610 | xhci_free_device_endpoint_resources(xhci, virt_dev, true); |
| 1611 | + if (cmd_comp_code == COMP_SUCCESS) { | |
| 1612 | + xhci->dcbaa->dev_context_ptrs[slot_id] = 0; | |
| 1613 | + xhci->devs[slot_id] = NULL; | |
| 1614 | + } | |
| 1610 | 1615 | } |
| 1611 | 1616 | |
| 1612 | 1617 | static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id) |
| @@ -1856,7 +1861,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, · 243 unmodified lines | ||
| 1856 | 1861 | xhci_handle_cmd_enable_slot(slot_id, cmd, cmd_comp_code); |
| 1857 | 1862 | break; |
| 1858 | 1863 | case TRB_DISABLE_SLOT: |
| 1859 | − xhci_handle_cmd_disable_slot(xhci, slot_id); | |
| 1864 | + xhci_handle_cmd_disable_slot(xhci, slot_id, cmd_comp_code); | |
| 1860 | 1865 | break; |
| 1861 | 1866 | case TRB_CONFIG_EP: |
| 1862 | 1867 | if (!cmd->completion) |
| @@ -309,6 +309,7 @@ int xhci_enable_interrupter(struct xhci_interrupter *ir) · 308 unmodified lines | ||
| 309 | 309 | return -EINVAL; |
| 310 | 310 | |
| 311 | 311 | iman = readl(&ir->ir_set->iman); |
| 312 | + iman &= ~IMAN_IP; | |
| 312 | 313 | iman |= IMAN_IE; |
| 313 | 314 | writel(iman, &ir->ir_set->iman); |
| 314 | 315 | |
| @@ -325,6 +326,7 @@ int xhci_disable_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir) · 10 unmodified lines | ||
| 325 | 326 | return -EINVAL; |
| 326 | 327 | |
| 327 | 328 | iman = readl(&ir->ir_set->iman); |
| 329 | + iman &= ~IMAN_IP; | |
| 328 | 330 | iman &= ~IMAN_IE; |
| 329 | 331 | writel(iman, &ir->ir_set->iman); |
| 330 | 332 | |
| @@ -3932,8 +3934,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd, · 3601 unmodified lines | ||
| 3932 | 3934 | * Obtaining a new device slot to inform the xHCI host that |
| 3933 | 3935 | * the USB device has been reset. |
| 3934 | 3936 | */ |
| 3935 | − ret = xhci_disable_slot(xhci, udev->slot_id); | |
| 3936 | − xhci_free_virt_device(xhci, udev->slot_id); | |
| 3937 | + ret = xhci_disable_and_free_slot(xhci, udev->slot_id); | |
| 3937 | 3938 | if (!ret) { |
| 3938 | 3939 | ret = xhci_alloc_dev(hcd, udev); |
| 3939 | 3940 | if (ret == 1) |
| @@ -4090,7 +4091,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) · 150 unmodified lines | ||
| 4090 | 4091 | xhci_disable_slot(xhci, udev->slot_id); |
| 4091 | 4092 | |
| 4092 | 4093 | spin_lock_irqsave(&xhci->lock, flags); |
| 4093 | − xhci_free_virt_device(xhci, udev->slot_id); | |
| 4094 | + xhci_free_virt_device(xhci, virt_dev, udev->slot_id); | |
| 4094 | 4095 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 4095 | 4096 | |
| 4096 | 4097 | } |
| @@ -4139,6 +4140,16 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) · 42 unmodified lines | ||
| 4139 | 4140 | return 0; |
| 4140 | 4141 | } |
| 4141 | 4142 | |
| 4143 | +int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id) | |
| 4144 | +{ | |
| 4145 | + struct xhci_virt_device *vdev = xhci->devs[slot_id]; | |
| 4146 | + int ret; | |
| 4147 | + | |
| 4148 | + ret = xhci_disable_slot(xhci, slot_id); | |
| 4149 | + xhci_free_virt_device(xhci, vdev, slot_id); | |
| 4150 | + return ret; | |
| 4151 | +} | |
| 4152 | + | |
| 4142 | 4153 | /* |
| 4143 | 4154 | * Checks if we have enough host controller resources for the default control |
| 4144 | 4155 | * endpoint. |
| @@ -4245,8 +4256,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) · 100 unmodified lines | ||
| 4245 | 4256 | return 1; |
| 4246 | 4257 | |
| 4247 | 4258 | disable_slot: |
| 4248 | − xhci_disable_slot(xhci, udev->slot_id); | |
| 4249 | − xhci_free_virt_device(xhci, udev->slot_id); | |
| 4259 | + xhci_disable_and_free_slot(xhci, udev->slot_id); | |
| 4250 | 4260 | |
| 4251 | 4261 | return 0; |
| 4252 | 4262 | } |
| @@ -4382,8 +4392,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, · 129 unmodified lines | ||
| 4382 | 4392 | dev_warn(&udev->dev, "Device not responding to setup %s.\n", act); |
| 4383 | 4393 | |
| 4384 | 4394 | mutex_unlock(&xhci->mutex); |
| 4385 | − ret = xhci_disable_slot(xhci, udev->slot_id); | |
| 4386 | − xhci_free_virt_device(xhci, udev->slot_id); | |
| 4395 | + ret = xhci_disable_and_free_slot(xhci, udev->slot_id); | |
| 4387 | 4396 | if (!ret) { |
| 4388 | 4397 | if (xhci_alloc_dev(hcd, udev) == 1) |
| 4389 | 4398 | xhci_setup_addressable_virt_dev(xhci, udev); |
| @@ -1791,7 +1791,7 @@ void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *), · 1790 unmodified lines | ||
| 1791 | 1791 | /* xHCI memory management */ |
| 1792 | 1792 | void xhci_mem_cleanup(struct xhci_hcd *xhci); |
| 1793 | 1793 | int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags); |
| 1794 | −void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id); | |
| 1794 | +void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, int slot_id); | |
| 1795 | 1795 | int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags); |
| 1796 | 1796 | int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev); |
| 1797 | 1797 | void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, |
| @@ -1888,6 +1888,7 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); · 90 unmodified lines | ||
| 1888 | 1888 | int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, |
| 1889 | 1889 | struct usb_tt *tt, gfp_t mem_flags); |
| 1890 | 1890 | int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id); |
| 1891 | +int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id); | |
| 1891 | 1892 | int xhci_ext_cap_init(struct xhci_hcd *xhci); |
| 1892 | 1893 | |
| 1893 | 1894 | int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); |
| @@ -252,7 +252,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, · 251 unmodified lines | ||
| 252 | 252 | return USB_STOR_TRANSPORT_ERROR; |
| 253 | 253 | } |
| 254 | 254 | |
| 255 | − residue = bcs->Residue; | |
| 255 | + residue = le32_to_cpu(bcs->Residue); | |
| 256 | 256 | if (bcs->Tag != us->tag) |
| 257 | 257 | return USB_STOR_TRANSPORT_ERROR; |
| 258 | 258 | |
| @@ -934,6 +934,13 @@ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451, · 933 unmodified lines | ||
| 934 | 934 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, |
| 935 | 935 | US_FL_SANE_SENSE ), |
| 936 | 936 | |
| 937 | +/* Added by Maël GUERIN <mael.guerin@murena.io> */ | |
| 938 | +UNUSUAL_DEV( 0x0603, 0x8611, 0x0000, 0xffff, | |
| 939 | + "Novatek", | |
| 940 | + "NTK96550-based camera", | |
| 941 | + USB_SC_SCSI, USB_PR_BULK, NULL, | |
| 942 | + US_FL_BULK_IGNORE_TAG ), | |
| 943 | + | |
| 937 | 944 | /* |
| 938 | 945 | * Reported by Hanno Boeck <hanno@gmx.de> |
| 939 | 946 | * Taken from the Lycoris Kernel |
| @@ -1494,6 +1501,28 @@ UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9999, · 554 unmodified lines | ||
| 1494 | 1501 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, |
| 1495 | 1502 | US_FL_NO_WP_DETECT ), |
| 1496 | 1503 | |
| 1504 | +/* | |
| 1505 | + * Reported by Zenm Chen <zenmchen@gmail.com> | |
| 1506 | + * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch | |
| 1507 | + * the device into Wi-Fi mode. | |
| 1508 | + */ | |
| 1509 | +UNUSUAL_DEV( 0x0bda, 0x1a2b, 0x0000, 0xffff, | |
| 1510 | + "Realtek", | |
| 1511 | + "DISK", | |
| 1512 | + USB_SC_DEVICE, USB_PR_DEVICE, NULL, | |
| 1513 | + US_FL_IGNORE_DEVICE ), | |
| 1514 | + | |
| 1515 | +/* | |
| 1516 | + * Reported by Zenm Chen <zenmchen@gmail.com> | |
| 1517 | + * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch | |
| 1518 | + * the device into Wi-Fi mode. | |
| 1519 | + */ | |
| 1520 | +UNUSUAL_DEV( 0x0bda, 0xa192, 0x0000, 0xffff, | |
| 1521 | + "Realtek", | |
| 1522 | + "DISK", | |
| 1523 | + USB_SC_DEVICE, USB_PR_DEVICE, NULL, | |
| 1524 | + US_FL_IGNORE_DEVICE ), | |
| 1525 | + | |
| 1497 | 1526 | UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, |
| 1498 | 1527 | "Maxtor", |
| 1499 | 1528 | "USB to SATA", |
| @@ -1485,6 +1485,9 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) · 1484 unmodified lines | ||
| 1485 | 1485 | struct fusb302_chip *chip = dev_id; |
| 1486 | 1486 | unsigned long flags; |
| 1487 | 1487 | |
| 1488 | + /* Disable our level triggered IRQ until our irq_work has cleared it */ | |
| 1489 | + disable_irq_nosync(chip->gpio_int_n_irq); | |
| 1490 | + | |
| 1488 | 1491 | spin_lock_irqsave(&chip->irq_lock, flags); |
| 1489 | 1492 | if (chip->irq_suspended) |
| 1490 | 1493 | chip->irq_while_suspended = true; |
| @@ -1627,6 +1630,7 @@ static void fusb302_irq_work(struct work_struct *work) · 136 unmodified lines | ||
| 1627 | 1630 | } |
| 1628 | 1631 | done: |
| 1629 | 1632 | mutex_unlock(&chip->lock); |
| 1633 | + enable_irq(chip->gpio_int_n_irq); | |
| 1630 | 1634 | } |
| 1631 | 1635 | |
| 1632 | 1636 | static int init_gpio(struct fusb302_chip *chip) |
| @@ -1751,10 +1755,9 @@ static int fusb302_probe(struct i2c_client *client) · 118 unmodified lines | ||
| 1751 | 1755 | goto destroy_workqueue; |
| 1752 | 1756 | } |
| 1753 | 1757 | |
| 1754 | − ret = devm_request_threaded_irq(dev, chip->gpio_int_n_irq, | |
| 1755 | − NULL, fusb302_irq_intn, | |
| 1756 | − IRQF_ONESHOT | IRQF_TRIGGER_LOW, | |
| 1757 | − "fsc_interrupt_int_n", chip); | |
| 1758 | + ret = request_irq(chip->gpio_int_n_irq, fusb302_irq_intn, | |
| 1759 | + IRQF_ONESHOT | IRQF_TRIGGER_LOW, | |
| 1760 | + "fsc_interrupt_int_n", chip); | |
| 1758 | 1761 | if (ret < 0) { |
| 1759 | 1762 | dev_err(dev, "cannot request IRQ for GPIO Int_N, ret=%d", ret); |
| 1760 | 1763 | goto tcpm_unregister_port; |
| @@ -1779,6 +1782,7 @@ static void fusb302_remove(struct i2c_client *client) · 18 unmodified lines | ||
| 1779 | 1782 | struct fusb302_chip *chip = i2c_get_clientdata(client); |
| 1780 | 1783 | |
| 1781 | 1784 | disable_irq_wake(chip->gpio_int_n_irq); |
| 1785 | + free_irq(chip->gpio_int_n_irq, chip); | |
| 1782 | 1786 | cancel_work_sync(&chip->irq_work); |
| 1783 | 1787 | cancel_delayed_work_sync(&chip->bc_lvl_handler); |
| 1784 | 1788 | tcpm_unregister_port(chip->tcpm_port); |
| @@ -188,6 +188,11 @@ static int max_contaminant_read_comparators(struct max_tcpci_chip *chip, u8 *ven · 187 unmodified lines | ||
| 188 | 188 | if (ret < 0) |
| 189 | 189 | return ret; |
| 190 | 190 | |
| 191 | + /* Disable low power mode */ | |
| 192 | + ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL, | |
| 193 | + FIELD_PREP(CCLPMODESEL, | |
| 194 | + LOW_POWER_MODE_DISABLE)); | |
| 195 | + | |
| 191 | 196 | /* Sleep to allow comparators settle */ |
| 192 | 197 | usleep_range(5000, 6000); |
| 193 | 198 | ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, TCPC_TCPC_CTRL_ORIENTATION, PLUG_ORNT_CC1); |
| @@ -324,6 +329,39 @@ static int max_contaminant_enable_dry_detection(struct max_tcpci_chip *chip) · 130 unmodified lines | ||
| 324 | 329 | return 0; |
| 325 | 330 | } |
| 326 | 331 | |
| 332 | +static int max_contaminant_enable_toggling(struct max_tcpci_chip *chip) | |
| 333 | +{ | |
| 334 | + struct regmap *regmap = chip->data.regmap; | |
| 335 | + int ret; | |
| 336 | + | |
| 337 | + /* Disable dry detection if enabled. */ | |
| 338 | + ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL, | |
| 339 | + FIELD_PREP(CCLPMODESEL, | |
| 340 | + LOW_POWER_MODE_DISABLE)); | |
| 341 | + if (ret) | |
| 342 | + return ret; | |
| 343 | + | |
| 344 | + ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL1, CCCONNDRY, 0); | |
| 345 | + if (ret) | |
| 346 | + return ret; | |
| 347 | + | |
| 348 | + ret = max_tcpci_write8(chip, TCPC_ROLE_CTRL, TCPC_ROLE_CTRL_DRP | | |
| 349 | + FIELD_PREP(TCPC_ROLE_CTRL_CC1, | |
| 350 | + TCPC_ROLE_CTRL_CC_RD) | | |
| 351 | + FIELD_PREP(TCPC_ROLE_CTRL_CC2, | |
| 352 | + TCPC_ROLE_CTRL_CC_RD)); | |
| 353 | + if (ret) | |
| 354 | + return ret; | |
| 355 | + | |
| 356 | + ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, | |
| 357 | + TCPC_TCPC_CTRL_EN_LK4CONN_ALRT, | |
| 358 | + TCPC_TCPC_CTRL_EN_LK4CONN_ALRT); | |
| 359 | + if (ret) | |
| 360 | + return ret; | |
| 361 | + | |
| 362 | + return max_tcpci_write8(chip, TCPC_COMMAND, TCPC_CMD_LOOK4CONNECTION); | |
| 363 | +} | |
| 364 | + | |
| 327 | 365 | bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect_while_debounce, |
| 328 | 366 | bool *cc_handled) |
| 329 | 367 | { |
| @@ -340,6 +378,12 @@ bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect · 10 unmodified lines | ||
| 340 | 378 | if (ret < 0) |
| 341 | 379 | return false; |
| 342 | 380 | |
| 381 | + if (cc_status & TCPC_CC_STATUS_TOGGLING) { | |
| 382 | + if (chip->contaminant_state == DETECTED) | |
| 383 | + return true; | |
| 384 | + return false; | |
| 385 | + } | |
| 386 | + | |
| 343 | 387 | if (chip->contaminant_state == NOT_DETECTED || chip->contaminant_state == SINK) { |
| 344 | 388 | if (!disconnect_while_debounce) |
| 345 | 389 | msleep(100); |
| @@ -372,6 +416,12 @@ bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect · 26 unmodified lines | ||
| 372 | 416 | max_contaminant_enable_dry_detection(chip); |
| 373 | 417 | return true; |
| 374 | 418 | } |
| 419 | + | |
| 420 | + ret = max_contaminant_enable_toggling(chip); | |
| 421 | + if (ret) | |
| 422 | + dev_err(chip->dev, | |
| 423 | + "Failed to enable toggling, ret=%d", | |
| 424 | + ret); | |
| 375 | 425 | } |
| 376 | 426 | } else if (chip->contaminant_state == DETECTED) { |
| 377 | 427 | if (!(cc_status & TCPC_CC_STATUS_TOGGLING)) { |
| @@ -379,6 +429,14 @@ bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect · 1 unmodified line | ||
| 379 | 429 | if (chip->contaminant_state == DETECTED) { |
| 380 | 430 | max_contaminant_enable_dry_detection(chip); |
| 381 | 431 | return true; |
| 432 | + } else { | |
| 433 | + ret = max_contaminant_enable_toggling(chip); | |
| 434 | + if (ret) { | |
| 435 | + dev_err(chip->dev, | |
| 436 | + "Failed to enable toggling, ret=%d", | |
| 437 | + ret); | |
| 438 | + return true; | |
| 439 | + } | |
| 382 | 440 | } |
| 383 | 441 | } |
| 384 | 442 | } |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #define CCOVPDIS BIT(6) |
| 22 | 22 | #define SBURPCTRL BIT(5) |
| 23 | 23 | #define CCLPMODESEL GENMASK(4, 3) |
| 24 | +#define LOW_POWER_MODE_DISABLE 0 | |
| 24 | 25 | #define ULTRA_LOW_POWER_MODE 1 |
| 25 | 26 | #define CCRPCTRL GENMASK(2, 0) |
| 26 | 27 | #define UA_1_SRC 1 |
| @@ -99,6 +99,7 @@ struct vhost_net_ubuf_ref { · 98 unmodified lines | ||
| 99 | 99 | atomic_t refcount; |
| 100 | 100 | wait_queue_head_t wait; |
| 101 | 101 | struct vhost_virtqueue *vq; |
| 102 | + struct rcu_head rcu; | |
| 102 | 103 | }; |
| 103 | 104 | |
| 104 | 105 | #define VHOST_NET_BATCH 64 |
| @@ -250,9 +251,13 @@ vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy) · 145 unmodified lines | ||
| 250 | 251 | |
| 251 | 252 | static int vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs) |
| 252 | 253 | { |
| 253 | − int r = atomic_sub_return(1, &ubufs->refcount); | |
| 254 | + int r; | |
| 255 | + | |
| 256 | + rcu_read_lock(); | |
| 257 | + r = atomic_sub_return(1, &ubufs->refcount); | |
| 254 | 258 | if (unlikely(!r)) |
| 255 | 259 | wake_up(&ubufs->wait); |
| 260 | + rcu_read_unlock(); | |
| 256 | 261 | return r; |
| 257 | 262 | } |
| 258 | 263 | |
| @@ -265,7 +270,7 @@ static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs) · 6 unmodified lines | ||
| 265 | 270 | static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs) |
| 266 | 271 | { |
| 267 | 272 | vhost_net_ubuf_put_and_wait(ubufs); |
| 268 | − kfree(ubufs); | |
| 273 | + kfree_rcu(ubufs, rcu); | |
| 269 | 274 | } |
| 270 | 275 | |
| 271 | 276 | static void vhost_net_clear_ubuf_info(struct vhost_net *n) |
| @@ -360,11 +360,15 @@ static int virtinput_freeze(struct virtio_device *vdev) · 359 unmodified lines | ||
| 360 | 360 | { |
| 361 | 361 | struct virtio_input *vi = vdev->priv; |
| 362 | 362 | unsigned long flags; |
| 363 | + void *buf; | |
| 363 | 364 | |
| 364 | 365 | spin_lock_irqsave(&vi->lock, flags); |
| 365 | 366 | vi->ready = false; |
| 366 | 367 | spin_unlock_irqrestore(&vi->lock, flags); |
| 367 | 368 | |
| 369 | + virtio_reset_device(vdev); | |
| 370 | + while ((buf = virtqueue_detach_unused_buf(vi->sts)) != NULL) | |
| 371 | + kfree(buf); | |
| 368 | 372 | vdev->config->del_vqs(vdev); |
| 369 | 373 | return 0; |
| 370 | 374 | } |
| @@ -140,9 +140,9 @@ EXPORT_SYMBOL_GPL(vp_legacy_set_status); · 139 unmodified lines | ||
| 140 | 140 | * vp_legacy_queue_vector - set the MSIX vector for a specific virtqueue |
| 141 | 141 | * @ldev: the legacy virtio-pci device |
| 142 | 142 | * @index: queue index |
| 143 | − * @vector: the config vector | |
| 143 | + * @vector: the queue vector | |
| 144 | 144 | * |
| 145 | − * Returns the config vector read from the device | |
| 145 | + * Returns the queue vector read from the device | |
| 146 | 146 | */ |
| 147 | 147 | u16 vp_legacy_queue_vector(struct virtio_pci_legacy_device *ldev, |
| 148 | 148 | u16 index, u16 vector) |
| @@ -546,9 +546,9 @@ EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset); · 545 unmodified lines | ||
| 546 | 546 | * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue |
| 547 | 547 | * @mdev: the modern virtio-pci device |
| 548 | 548 | * @index: queue index |
| 549 | − * @vector: the config vector | |
| 549 | + * @vector: the queue vector | |
| 550 | 550 | * |
| 551 | − * Returns the config vector read from the device | |
| 551 | + * Returns the queue vector read from the device | |
| 552 | 552 | */ |
| 553 | 553 | u16 vp_modern_queue_vector(struct virtio_pci_modern_device *mdev, |
| 554 | 554 | u16 index, u16 vector) |
| @@ -718,26 +718,6 @@ int xs_watch_msg(struct xs_watch_event *event) · 717 unmodified lines | ||
| 718 | 718 | return 0; |
| 719 | 719 | } |
| 720 | 720 | |
| 721 | −/* | |
| 722 | − * Certain older XenBus toolstack cannot handle reading values that are | |
| 723 | − * not populated. Some Xen 3.4 installation are incapable of doing this | |
| 724 | − * so if we are running on anything older than 4 do not attempt to read | |
| 725 | − * control/platform-feature-xs_reset_watches. | |
| 726 | − */ | |
| 727 | −static bool xen_strict_xenbus_quirk(void) | |
| 728 | −{ | |
| 729 | −#ifdef CONFIG_X86 | |
| 730 | − uint32_t eax, ebx, ecx, edx, base; | |
| 731 | − | |
| 732 | − base = xen_cpuid_base(); | |
| 733 | − cpuid(base + 1, &eax, &ebx, &ecx, &edx); | |
| 734 | − | |
| 735 | − if ((eax >> 16) < 4) | |
| 736 | − return true; | |
| 737 | −#endif | |
| 738 | − return false; | |
| 739 | − | |
| 740 | −} | |
| 741 | 721 | static void xs_reset_watches(void) |
| 742 | 722 | { |
| 743 | 723 | int err; |
| @@ -745,9 +725,6 @@ static void xs_reset_watches(void) · 1 unmodified line | ||
| 745 | 725 | if (!xen_hvm_domain() || xen_initial_domain()) |
| 746 | 726 | return; |
| 747 | 727 | |
| 748 | − if (xen_strict_xenbus_quirk()) | |
| 749 | − return; | |
| 750 | − | |
| 751 | 728 | if (!xenbus_read_unsigned("control", |
| 752 | 729 | "platform-feature-xs_reset_watches", 0)) |
| 753 | 730 | return; |
| @@ -183,6 +183,9 @@ static int debugfs_reconfigure(struct fs_context *fc) · 182 unmodified lines | ||
| 183 | 183 | struct debugfs_fs_info *sb_opts = sb->s_fs_info; |
| 184 | 184 | struct debugfs_fs_info *new_opts = fc->s_fs_info; |
| 185 | 185 | |
| 186 | + if (!new_opts) | |
| 187 | + return 0; | |
| 188 | + | |
| 186 | 189 | sync_filesystem(sb); |
| 187 | 190 | |
| 188 | 191 | /* structure copy of new mount options to sb */ |
| @@ -282,10 +285,16 @@ static int debugfs_fill_super(struct super_block *sb, struct fs_context *fc) · 93 unmodified lines | ||
| 282 | 285 | |
| 283 | 286 | static int debugfs_get_tree(struct fs_context *fc) |
| 284 | 287 | { |
| 288 | + int err; | |
| 289 | + | |
| 285 | 290 | if (!(debugfs_allow & DEBUGFS_ALLOW_API)) |
| 286 | 291 | return -EPERM; |
| 287 | 292 | |
| 288 | − return get_tree_single(fc, debugfs_fill_super); | |
| 293 | + err = get_tree_single(fc, debugfs_fill_super); | |
| 294 | + if (err) | |
| 295 | + return err; | |
| 296 | + | |
| 297 | + return debugfs_reconfigure(fc); | |
| 289 | 298 | } |
| 290 | 299 | |
| 291 | 300 | static void debugfs_free_fc(struct fs_context *fc) |
| @@ -253,13 +253,14 @@ nfs_page_group_unlock(struct nfs_page *req) · 252 unmodified lines | ||
| 253 | 253 | nfs_page_clear_headlock(req); |
| 254 | 254 | } |
| 255 | 255 | |
| 256 | −/* | |
| 257 | − * nfs_page_group_sync_on_bit_locked | |
| 256 | +/** | |
| 257 | + * nfs_page_group_sync_on_bit_locked - Test if all requests have @bit set | |
| 258 | + * @req: request in page group | |
| 259 | + * @bit: PG_* bit that is used to sync page group | |
| 258 | 260 | * |
| 259 | 261 | * must be called with page group lock held |
| 260 | 262 | */ |
| 261 | −static bool | |
| 262 | −nfs_page_group_sync_on_bit_locked(struct nfs_page *req, unsigned int bit) | |
| 263 | +bool nfs_page_group_sync_on_bit_locked(struct nfs_page *req, unsigned int bit) | |
| 263 | 264 | { |
| 264 | 265 | struct nfs_page *head = req->wb_head; |
| 265 | 266 | struct nfs_page *tmp; |
| @@ -153,20 +153,10 @@ nfs_page_set_inode_ref(struct nfs_page *req, struct inode *inode) · 152 unmodified lines | ||
| 153 | 153 | } |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | −static int | |
| 157 | −nfs_cancel_remove_inode(struct nfs_page *req, struct inode *inode) | |
| 156 | +static void nfs_cancel_remove_inode(struct nfs_page *req, struct inode *inode) | |
| 158 | 157 | { |
| 159 | − int ret; | |
| 160 | − | |
| 161 | − if (!test_bit(PG_REMOVE, &req->wb_flags)) | |
| 162 | − return 0; | |
| 163 | − ret = nfs_page_group_lock(req); | |
| 164 | − if (ret) | |
| 165 | − return ret; | |
| 166 | 158 | if (test_and_clear_bit(PG_REMOVE, &req->wb_flags)) |
| 167 | 159 | nfs_page_set_inode_ref(req, inode); |
| 168 | − nfs_page_group_unlock(req); | |
| 169 | − return 0; | |
| 170 | 160 | } |
| 171 | 161 | |
| 172 | 162 | /** |
| @@ -585,19 +575,18 @@ retry: · 412 unmodified lines | ||
| 585 | 575 | } |
| 586 | 576 | } |
| 587 | 577 | |
| 578 | + ret = nfs_page_group_lock(head); | |
| 579 | + if (ret < 0) | |
| 580 | + goto out_unlock; | |
| 581 | + | |
| 588 | 582 | /* Ensure that nobody removed the request before we locked it */ |
| 589 | 583 | if (head != folio->private) { |
| 584 | + nfs_page_group_unlock(head); | |
| 590 | 585 | nfs_unlock_and_release_request(head); |
| 591 | 586 | goto retry; |
| 592 | 587 | } |
| 593 | 588 | |
| 594 | − ret = nfs_cancel_remove_inode(head, inode); | |
| 595 | − if (ret < 0) | |
| 596 | − goto out_unlock; | |
| 597 | − | |
| 598 | − ret = nfs_page_group_lock(head); | |
| 599 | − if (ret < 0) | |
| 600 | − goto out_unlock; | |
| 589 | + nfs_cancel_remove_inode(head, inode); | |
| 601 | 590 | |
| 602 | 591 | /* lock each request in the page group */ |
| 603 | 592 | for (subreq = head->wb_this_page; |
| @@ -786,7 +775,8 @@ static void nfs_inode_remove_request(struct nfs_page *req) · 182 unmodified lines | ||
| 786 | 775 | { |
| 787 | 776 | struct nfs_inode *nfsi = NFS_I(nfs_page_to_inode(req)); |
| 788 | 777 | |
| 789 | − if (nfs_page_group_sync_on_bit(req, PG_REMOVE)) { | |
| 778 | + nfs_page_group_lock(req); | |
| 779 | + if (nfs_page_group_sync_on_bit_locked(req, PG_REMOVE)) { | |
| 790 | 780 | struct folio *folio = nfs_page_to_folio(req->wb_head); |
| 791 | 781 | struct address_space *mapping = folio->mapping; |
| 792 | 782 | |
| @@ -798,6 +788,7 @@ static void nfs_inode_remove_request(struct nfs_page *req) · 5 unmodified lines | ||
| 798 | 788 | } |
| 799 | 789 | spin_unlock(&mapping->i_private_lock); |
| 800 | 790 | } |
| 791 | + nfs_page_group_unlock(req); | |
| 801 | 792 | |
| 802 | 793 | if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) { |
| 803 | 794 | atomic_long_dec(&nfsi->nrequests); |
| @@ -4496,7 +4496,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst, · 4495 unmodified lines | ||
| 4496 | 4496 | for (int i = 1; i < num_rqst; i++) { |
| 4497 | 4497 | struct smb_rqst *old = &old_rq[i - 1]; |
| 4498 | 4498 | struct smb_rqst *new = &new_rq[i]; |
| 4499 | − struct folio_queue *buffer; | |
| 4499 | + struct folio_queue *buffer = NULL; | |
| 4500 | 4500 | size_t size = iov_iter_count(&old->rq_iter); |
| 4501 | 4501 | |
| 4502 | 4502 | orig_len += smb_rqst_len(server, old); |
| @@ -187,10 +187,15 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc) · 186 unmodified lines | ||
| 187 | 187 | unsigned short flags; |
| 188 | 188 | unsigned int fragments; |
| 189 | 189 | u64 lookup_table_start, xattr_id_table_start, next_table; |
| 190 | − int err; | |
| 190 | + int err, devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE); | |
| 191 | 191 | |
| 192 | 192 | TRACE("Entered squashfs_fill_superblock\n"); |
| 193 | 193 | |
| 194 | + if (!devblksize) { | |
| 195 | + errorf(fc, "squashfs: unable to set blocksize\n"); | |
| 196 | + return -EINVAL; | |
| 197 | + } | |
| 198 | + | |
| 194 | 199 | sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL); |
| 195 | 200 | if (sb->s_fs_info == NULL) { |
| 196 | 201 | ERROR("Failed to allocate squashfs_sb_info\n"); |
| @@ -201,12 +206,7 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc) · 4 unmodified lines | ||
| 201 | 206 | |
| 202 | 207 | msblk->panic_on_errors = (opts->errors == Opt_errors_panic); |
| 203 | 208 | |
| 204 | − msblk->devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE); | |
| 205 | − if (!msblk->devblksize) { | |
| 206 | − errorf(fc, "squashfs: unable to set blocksize\n"); | |
| 207 | − return -EINVAL; | |
| 208 | − } | |
| 209 | − | |
| 209 | + msblk->devblksize = devblksize; | |
| 210 | 210 | msblk->devblksize_log2 = ffz(~msblk->devblksize); |
| 211 | 211 | |
| 212 | 212 | mutex_init(&msblk->meta_index_mutex); |
| @@ -185,6 +185,7 @@ struct atmdev_ops { /* only send is required */ · 184 unmodified lines | ||
| 185 | 185 | int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, |
| 186 | 186 | void __user *arg); |
| 187 | 187 | #endif |
| 188 | + int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb); | |
| 188 | 189 | int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); |
| 189 | 190 | int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb); |
| 190 | 191 | int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); |
| @@ -656,6 +656,7 @@ enum { · 655 unmodified lines | ||
| 656 | 656 | QUEUE_FLAG_SQ_SCHED, /* single queue style io dispatch */ |
| 657 | 657 | QUEUE_FLAG_DISABLE_WBT_DEF, /* for sched to disable/enable wbt */ |
| 658 | 658 | QUEUE_FLAG_NO_ELV_SWITCH, /* can't switch elevator any more */ |
| 659 | + QUEUE_FLAG_QOS_ENABLED, /* qos is enabled */ | |
| 659 | 660 | QUEUE_FLAG_MAX |
| 660 | 661 | }; |
| 661 | 662 | |
| @@ -288,14 +288,6 @@ static inline void *offset_to_ptr(const int *off) · 287 unmodified lines | ||
| 288 | 288 | #define __ADDRESSABLE(sym) \ |
| 289 | 289 | ___ADDRESSABLE(sym, __section(".discard.addressable")) |
| 290 | 290 | |
| 291 | −#define __ADDRESSABLE_ASM(sym) \ | |
| 292 | − .pushsection .discard.addressable,"aw"; \ | |
| 293 | − .align ARCH_SEL(8,4); \ | |
| 294 | − ARCH_SEL(.quad, .long) __stringify(sym); \ | |
| 295 | − .popsection; | |
| 296 | − | |
| 297 | −#define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym)) | |
| 298 | − | |
| 299 | 291 | /* |
| 300 | 292 | * This returns a constant expression while determining if an argument is |
| 301 | 293 | * a constant expression, most importantly without evaluating the argument. |
| @@ -153,6 +153,9 @@ static inline void dma_free_contiguous(struct device *dev, struct page *page, · 152 unmodified lines | ||
| 153 | 153 | { |
| 154 | 154 | __free_pages(page, get_order(size)); |
| 155 | 155 | } |
| 156 | +static inline void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) | |
| 157 | +{ | |
| 158 | +} | |
| 156 | 159 | #endif /* CONFIG_DMA_CMA*/ |
| 157 | 160 | |
| 158 | 161 | #ifdef CONFIG_DMA_DECLARE_COHERENT |
| @@ -264,12 +264,7 @@ static inline bool iosys_map_is_set(const struct iosys_map *map) · 263 unmodified lines | ||
| 264 | 264 | */ |
| 265 | 265 | static inline void iosys_map_clear(struct iosys_map *map) |
| 266 | 266 | { |
| 267 | − if (map->is_iomem) { | |
| 268 | − map->vaddr_iomem = NULL; | |
| 269 | − map->is_iomem = false; | |
| 270 | − } else { | |
| 271 | − map->vaddr = NULL; | |
| 272 | − } | |
| 267 | + memset(map, 0, sizeof(*map)); | |
| 273 | 268 | } |
| 274 | 269 | |
| 275 | 270 | /** |
| @@ -160,7 +160,7 @@ size_t iterate_folioq(struct iov_iter *iter, size_t len, void *priv, void *priv2 · 159 unmodified lines | ||
| 160 | 160 | |
| 161 | 161 | do { |
| 162 | 162 | struct folio *folio = folioq_folio(folioq, slot); |
| 163 | − size_t part, remain, consumed; | |
| 163 | + size_t part, remain = 0, consumed; | |
| 164 | 164 | size_t fsize; |
| 165 | 165 | void *base; |
| 166 | 166 | |
| @@ -168,14 +168,16 @@ size_t iterate_folioq(struct iov_iter *iter, size_t len, void *priv, void *priv2 · 1 unmodified line | ||
| 168 | 168 | break; |
| 169 | 169 | |
| 170 | 170 | fsize = folioq_folio_size(folioq, slot); |
| 171 | − base = kmap_local_folio(folio, skip); | |
| 172 | − part = umin(len, PAGE_SIZE - skip % PAGE_SIZE); | |
| 173 | − remain = step(base, progress, part, priv, priv2); | |
| 174 | − kunmap_local(base); | |
| 175 | − consumed = part - remain; | |
| 176 | − len -= consumed; | |
| 177 | − progress += consumed; | |
| 178 | − skip += consumed; | |
| 171 | + if (skip < fsize) { | |
| 172 | + base = kmap_local_folio(folio, skip); | |
| 173 | + part = umin(len, PAGE_SIZE - skip % PAGE_SIZE); | |
| 174 | + remain = step(base, progress, part, priv, priv2); | |
| 175 | + kunmap_local(base); | |
| 176 | + consumed = part - remain; | |
| 177 | + len -= consumed; | |
| 178 | + progress += consumed; | |
| 179 | + skip += consumed; | |
| 180 | + } | |
| 179 | 181 | if (skip >= fsize) { |
| 180 | 182 | skip = 0; |
| 181 | 183 | slot++; |
| @@ -57,47 +57,21 @@ static inline void kcov_remote_start_usb(u64 id) · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | /* |
| 59 | 59 | * The softirq flavor of kcov_remote_*() functions is introduced as a temporary |
| 60 | − * workaround for KCOV's lack of nested remote coverage sections support. | |
| 61 | − * | |
| 62 | − * Adding support is tracked in https://bugzilla.kernel.org/show_bug.cgi?id=210337. | |
| 63 | − * | |
| 64 | − * kcov_remote_start_usb_softirq(): | |
| 65 | − * | |
| 66 | − * 1. Only collects coverage when called in the softirq context. This allows | |
| 67 | − * avoiding nested remote coverage collection sections in the task context. | |
| 68 | − * For example, USB/IP calls usb_hcd_giveback_urb() in the task context | |
| 69 | − * within an existing remote coverage collection section. Thus, KCOV should | |
| 70 | − * not attempt to start collecting coverage within the coverage collection | |
| 71 | − * section in __usb_hcd_giveback_urb() in this case. | |
| 72 | − * | |
| 73 | − * 2. Disables interrupts for the duration of the coverage collection section. | |
| 74 | − * This allows avoiding nested remote coverage collection sections in the | |
| 75 | − * softirq context (a softirq might occur during the execution of a work in | |
| 76 | − * the BH workqueue, which runs with in_serving_softirq() > 0). | |
| 77 | − * For example, usb_giveback_urb_bh() runs in the BH workqueue with | |
| 78 | − * interrupts enabled, so __usb_hcd_giveback_urb() might be interrupted in | |
| 79 | − * the middle of its remote coverage collection section, and the interrupt | |
| 80 | − * handler might invoke __usb_hcd_giveback_urb() again. | |
| 60 | + * work around for kcov's lack of nested remote coverage sections support in | |
| 61 | + * task context. Adding support for nested sections is tracked in: | |
| 62 | + * https://bugzilla.kernel.org/show_bug.cgi?id=210337 | |
| 81 | 63 | */ |
| 82 | 64 | |
| 83 | −static inline unsigned long kcov_remote_start_usb_softirq(u64 id) | |
| 65 | +static inline void kcov_remote_start_usb_softirq(u64 id) | |
| 84 | 66 | { |
| 85 | − unsigned long flags = 0; | |
| 86 | − | |
| 87 | − if (in_serving_softirq()) { | |
| 88 | − local_irq_save(flags); | |
| 67 | + if (in_serving_softirq() && !in_hardirq()) | |
| 89 | 68 | kcov_remote_start_usb(id); |
| 90 | − } | |
| 91 | − | |
| 92 | − return flags; | |
| 93 | 69 | } |
| 94 | 70 | |
| 95 | −static inline void kcov_remote_stop_softirq(unsigned long flags) | |
| 71 | +static inline void kcov_remote_stop_softirq(void) | |
| 96 | 72 | { |
| 97 | − if (in_serving_softirq()) { | |
| 73 | + if (in_serving_softirq() && !in_hardirq()) | |
| 98 | 74 | kcov_remote_stop(); |
| 99 | − local_irq_restore(flags); | |
| 100 | − } | |
| 101 | 75 | } |
| 102 | 76 | |
| 103 | 77 | #ifdef CONFIG_64BIT |
| @@ -131,11 +105,8 @@ static inline u64 kcov_common_handle(void) · 27 unmodified lines | ||
| 131 | 105 | } |
| 132 | 106 | static inline void kcov_remote_start_common(u64 id) {} |
| 133 | 107 | static inline void kcov_remote_start_usb(u64 id) {} |
| 134 | −static inline unsigned long kcov_remote_start_usb_softirq(u64 id) | |
| 135 | −{ | |
| 136 | − return 0; | |
| 137 | −} | |
| 138 | −static inline void kcov_remote_stop_softirq(unsigned long flags) {} | |
| 108 | +static inline void kcov_remote_start_usb_softirq(u64 id) {} | |
| 109 | +static inline void kcov_remote_stop_softirq(void) {} | |
| 139 | 110 | |
| 140 | 111 | #endif /* CONFIG_KCOV */ |
| 141 | 112 | #endif /* _LINUX_KCOV_H */ |
| @@ -40,8 +40,9 @@ extern unsigned long long max_possible_pfn; · 39 unmodified lines | ||
| 40 | 40 | * via a driver, and never indicated in the firmware-provided memory map as |
| 41 | 41 | * system RAM. This corresponds to IORESOURCE_SYSRAM_DRIVER_MANAGED in the |
| 42 | 42 | * kernel resource tree. |
| 43 | − * @MEMBLOCK_RSRV_NOINIT: memory region for which struct pages are | |
| 44 | − * not initialized (only for reserved regions). | |
| 43 | + * @MEMBLOCK_RSRV_NOINIT: reserved memory region for which struct pages are not | |
| 44 | + * fully initialized. Users of this flag are responsible to properly initialize | |
| 45 | + * struct pages of this region | |
| 45 | 46 | * @MEMBLOCK_RSRV_KERN: memory region that is reserved for kernel use, |
| 46 | 47 | * either explictitly with memblock_reserve_kern() or via memblock |
| 47 | 48 | * allocation APIs. All memblock allocations set this flag. |
| @@ -79,6 +79,7 @@ void migration_entry_wait_on_locked(swp_entry_t entry, spinlock_t *ptl) · 78 unmodified lines | ||
| 79 | 79 | void folio_migrate_flags(struct folio *newfolio, struct folio *folio); |
| 80 | 80 | int folio_migrate_mapping(struct address_space *mapping, |
| 81 | 81 | struct folio *newfolio, struct folio *folio, int extra_count); |
| 82 | +int set_movable_ops(const struct movable_operations *ops, enum pagetype type); | |
| 82 | 83 | |
| 83 | 84 | #else |
| 84 | 85 | |
| @@ -100,6 +101,10 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping, · 15 unmodified lines | ||
| 100 | 101 | { |
| 101 | 102 | return -ENOSYS; |
| 102 | 103 | } |
| 104 | +static inline int set_movable_ops(const struct movable_operations *ops, enum pagetype type) | |
| 105 | +{ | |
| 106 | + return -ENOSYS; | |
| 107 | +} | |
| 103 | 108 | |
| 104 | 109 | #endif /* CONFIG_MIGRATION */ |
| 105 | 110 | |
| @@ -160,6 +160,7 @@ extern void nfs_join_page_group(struct nfs_page *head, · 159 unmodified lines | ||
| 160 | 160 | extern int nfs_page_group_lock(struct nfs_page *); |
| 161 | 161 | extern void nfs_page_group_unlock(struct nfs_page *); |
| 162 | 162 | extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); |
| 163 | +extern bool nfs_page_group_sync_on_bit_locked(struct nfs_page *, unsigned int); | |
| 163 | 164 | extern int nfs_page_set_headlock(struct nfs_page *req); |
| 164 | 165 | extern void nfs_page_clear_headlock(struct nfs_page *req); |
| 165 | 166 | extern bool nfs_async_iocounter_wait(struct rpc_task *, struct nfs_lock_context *); |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #define INT3472_GPIO_TYPE_CLK_ENABLE 0x0c |
| 28 | 28 | #define INT3472_GPIO_TYPE_PRIVACY_LED 0x0d |
| 29 | 29 | #define INT3472_GPIO_TYPE_HANDSHAKE 0x12 |
| 30 | +#define INT3472_GPIO_TYPE_HOTPLUG_DETECT 0x13 | |
| 30 | 31 | |
| 31 | 32 | #define INT3472_PDEV_MAX_NAME_LEN 23 |
| 32 | 33 | #define INT3472_MAX_SENSOR_GPIOS 3 |
| @@ -4213,6 +4213,8 @@ int skb_copy_and_crc32c_datagram_iter(const struct sk_buff *skb, int offset, · 4212 unmodified lines | ||
| 4213 | 4213 | struct iov_iter *to, int len, u32 *crcp); |
| 4214 | 4214 | int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset, |
| 4215 | 4215 | struct iov_iter *from, int len); |
| 4216 | +int skb_copy_datagram_from_iter_full(struct sk_buff *skb, int offset, | |
| 4217 | + struct iov_iter *from, int len); | |
| 4216 | 4218 | int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *frm); |
| 4217 | 4219 | void skb_free_datagram(struct sock *sk, struct sk_buff *skb); |
| 4218 | 4220 | int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); |
| @@ -328,8 +328,6 @@ static inline · 327 unmodified lines | ||
| 328 | 328 | bool virtio_get_shm_region(struct virtio_device *vdev, |
| 329 | 329 | struct virtio_shm_region *region, u8 id) |
| 330 | 330 | { |
| 331 | − if (!region->len) | |
| 332 | − return false; | |
| 333 | 331 | if (!vdev->config->get_shm_region) |
| 334 | 332 | return false; |
| 335 | 333 | return vdev->config->get_shm_region(vdev, region, id); |
| @@ -93,7 +93,7 @@ int hci_update_class_sync(struct hci_dev *hdev); · 92 unmodified lines | ||
| 93 | 93 | |
| 94 | 94 | int hci_update_eir_sync(struct hci_dev *hdev); |
| 95 | 95 | int hci_update_class_sync(struct hci_dev *hdev); |
| 96 | −int hci_update_name_sync(struct hci_dev *hdev); | |
| 96 | +int hci_update_name_sync(struct hci_dev *hdev, const u8 *name); | |
| 97 | 97 | int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode); |
| 98 | 98 | |
| 99 | 99 | int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #ifndef _ROSE_H |
| 9 | 9 | #define _ROSE_H |
| 10 | 10 | |
| 11 | +#include <linux/refcount.h> | |
| 11 | 12 | #include <linux/rose.h> |
| 12 | 13 | #include <net/ax25.h> |
| 13 | 14 | #include <net/sock.h> |
| @@ -96,7 +97,7 @@ struct rose_neigh { · 82 unmodified lines | ||
| 96 | 97 | ax25_cb *ax25; |
| 97 | 98 | struct net_device *dev; |
| 98 | 99 | unsigned short count; |
| 99 | − unsigned short use; | |
| 100 | + refcount_t use; | |
| 100 | 101 | unsigned int number; |
| 101 | 102 | char restarted; |
| 102 | 103 | char dce_mode; |
| @@ -151,6 +152,21 @@ struct rose_sock { · 48 unmodified lines | ||
| 151 | 152 | |
| 152 | 153 | #define rose_sk(sk) ((struct rose_sock *)(sk)) |
| 153 | 154 | |
| 155 | +static inline void rose_neigh_hold(struct rose_neigh *rose_neigh) | |
| 156 | +{ | |
| 157 | + refcount_inc(&rose_neigh->use); | |
| 158 | +} | |
| 159 | + | |
| 160 | +static inline void rose_neigh_put(struct rose_neigh *rose_neigh) | |
| 161 | +{ | |
| 162 | + if (refcount_dec_and_test(&rose_neigh->use)) { | |
| 163 | + if (rose_neigh->ax25) | |
| 164 | + ax25_cb_put(rose_neigh->ax25); | |
| 165 | + kfree(rose_neigh->digipeat); | |
| 166 | + kfree(rose_neigh); | |
| 167 | + } | |
| 168 | +} | |
| 169 | + | |
| 154 | 170 | /* af_rose.c */ |
| 155 | 171 | extern ax25_address rose_callsign; |
| 156 | 172 | extern int sysctl_rose_restart_request_timeout; |
| @@ -107,8 +107,8 @@ · 106 unmodified lines | ||
| 107 | 107 | #define CS35L56_DSP1_PMEM_5114 0x3804FE8 |
| 108 | 108 | |
| 109 | 109 | #define CS35L63_DSP1_FW_VER CS35L56_DSP1_FW_VER |
| 110 | −#define CS35L63_DSP1_HALO_STATE 0x280396C | |
| 111 | −#define CS35L63_DSP1_PM_CUR_STATE 0x28042C8 | |
| 110 | +#define CS35L63_DSP1_HALO_STATE 0x2803C04 | |
| 111 | +#define CS35L63_DSP1_PM_CUR_STATE 0x2804518 | |
| 112 | 112 | #define CS35L63_PROTECTION_STATUS 0x340009C |
| 113 | 113 | #define CS35L63_TRANSDUCER_ACTUAL_PS 0x34000F4 |
| 114 | 114 | #define CS35L63_MAIN_RENDER_USER_MUTE 0x3400020 |
| @@ -306,6 +306,7 @@ struct cs35l56_base { · 191 unmodified lines | ||
| 306 | 306 | struct gpio_desc *reset_gpio; |
| 307 | 307 | struct cs35l56_spi_payload *spi_payload_buf; |
| 308 | 308 | const struct cs35l56_fw_reg *fw_reg; |
| 309 | + const struct cirrus_amp_cal_controls *calibration_controls; | |
| 309 | 310 | }; |
| 310 | 311 | |
| 311 | 312 | static inline bool cs35l56_is_otp_register(unsigned int reg) |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | // |
| 3 | 3 | // ALSA SoC Texas Instruments TAS2781 Audio Smart Amplifier |
| 4 | 4 | // |
| 5 | −// Copyright (C) 2022 - 2024 Texas Instruments Incorporated | |
| 5 | +// Copyright (C) 2022 - 2025 Texas Instruments Incorporated | |
| 6 | 6 | // https://www.ti.com |
| 7 | 7 | // |
| 8 | 8 | // The TAS2781 driver implements a flexible and configurable |
| @@ -15,7 +15,7 @@ · 6 unmodified lines | ||
| 15 | 15 | #ifndef __TAS2781_TLV_H__ |
| 16 | 16 | #define __TAS2781_TLV_H__ |
| 17 | 17 | |
| 18 | −static const __maybe_unused DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 50, 0); | |
| 19 | −static const __maybe_unused DECLARE_TLV_DB_SCALE(amp_vol_tlv, 1100, 50, 0); | |
| 18 | +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2781_dvc_tlv, -10000, 50, 0); | |
| 19 | +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2781_amp_tlv, 1100, 50, 0); | |
| 20 | 20 | |
| 21 | 21 | #endif |
| @@ -89,6 +89,7 @@ struct pfru_payload_hdr { · 88 unmodified lines | ||
| 89 | 89 | __u32 hw_ver; |
| 90 | 90 | __u32 rt_ver; |
| 91 | 91 | __u8 platform_id[16]; |
| 92 | + __u32 svn_ver; | |
| 92 | 93 | }; |
| 93 | 94 | |
| 94 | 95 | enum pfru_dsm_status { |
| @@ -173,7 +173,7 @@ typedef struct mdp_superblock_s { · 172 unmodified lines | ||
| 173 | 173 | #else |
| 174 | 174 | #error unspecified endianness |
| 175 | 175 | #endif |
| 176 | − __u32 resync_offset; /* 11 resync checkpoint sector count */ | |
| 176 | + __u32 recovery_cp; /* 11 resync checkpoint sector count */ | |
| 177 | 177 | /* There are only valid for minor_version > 90 */ |
| 178 | 178 | __u64 reshape_position; /* 12,13 next address in array-space for reshape */ |
| 179 | 179 | __u32 new_level; /* 14 new level we are reshaping to */ |
| @@ -260,7 +260,7 @@ · 259 unmodified lines | ||
| 260 | 260 | * When fork_owner is set to VHOST_FORK_OWNER_KTHREAD: |
| 261 | 261 | * - Vhost will create vhost workers as kernel threads. |
| 262 | 262 | */ |
| 263 | −#define VHOST_SET_FORK_FROM_OWNER _IOW(VHOST_VIRTIO, 0x83, __u8) | |
| 263 | +#define VHOST_SET_FORK_FROM_OWNER _IOW(VHOST_VIRTIO, 0x84, __u8) | |
| 264 | 264 | |
| 265 | 265 | /** |
| 266 | 266 | * VHOST_GET_FORK_OWNER - Get the current fork_owner flag for the vhost device. |
| @@ -268,6 +268,6 @@ · 1 unmodified line | ||
| 268 | 268 | * |
| 269 | 269 | * @return: An 8-bit value indicating the current thread mode. |
| 270 | 270 | */ |
| 271 | −#define VHOST_GET_FORK_FROM_OWNER _IOR(VHOST_VIRTIO, 0x84, __u8) | |
| 271 | +#define VHOST_GET_FORK_FROM_OWNER _IOR(VHOST_VIRTIO, 0x85, __u8) | |
| 272 | 272 | |
| 273 | 273 | #endif |
| @@ -288,6 +288,7 @@ int io_futex_wait(struct io_kiocb *req, unsigned int issue_flags) · 287 unmodified lines | ||
| 288 | 288 | goto done_unlock; |
| 289 | 289 | } |
| 290 | 290 | |
| 291 | + req->flags |= REQ_F_ASYNC_DATA; | |
| 291 | 292 | req->async_data = ifd; |
| 292 | 293 | ifd->q = futex_q_init; |
| 293 | 294 | ifd->q.bitset = iof->futex_mask; |
| @@ -309,6 +310,8 @@ done: · 15 unmodified lines | ||
| 309 | 310 | if (ret < 0) |
| 310 | 311 | req_set_fail(req); |
| 311 | 312 | io_req_set_res(req, ret, 0); |
| 313 | + req->async_data = NULL; | |
| 314 | + req->flags &= ~REQ_F_ASYNC_DATA; | |
| 312 | 315 | kfree(ifd); |
| 313 | 316 | return IOU_COMPLETE; |
| 314 | 317 | } |
| @@ -2119,6 +2119,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, · 2118 unmodified lines | ||
| 2119 | 2119 | req->file = NULL; |
| 2120 | 2120 | req->tctx = current->io_uring; |
| 2121 | 2121 | req->cancel_seq_set = false; |
| 2122 | + req->async_data = NULL; | |
| 2122 | 2123 | |
| 2123 | 2124 | if (unlikely(opcode >= IORING_OP_LAST)) { |
| 2124 | 2125 | req->opcode = 0; |
| @@ -97,6 +97,7 @@ config KEXEC_JUMP · 96 unmodified lines | ||
| 97 | 97 | config KEXEC_HANDOVER |
| 98 | 98 | bool "kexec handover" |
| 99 | 99 | depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE |
| 100 | + depends on !DEFERRED_STRUCT_PAGE_INIT | |
| 100 | 101 | select MEMBLOCK_KHO_SCRATCH |
| 101 | 102 | select KEXEC_FILE |
| 102 | 103 | select DEBUG_FS |
| @@ -280,7 +280,7 @@ static inline void check_insane_mems_config(nodemask_t *nodes) · 279 unmodified lines | ||
| 280 | 280 | { |
| 281 | 281 | if (!cpusets_insane_config() && |
| 282 | 282 | movable_only_nodes(nodes)) { |
| 283 | − static_branch_enable(&cpusets_insane_config_key); | |
| 283 | + static_branch_enable_cpuslocked(&cpusets_insane_config_key); | |
| 284 | 284 | pr_info("Unsupported (movable nodes only) cpuset configuration detected (nmask=%*pbl)!\n" |
| 285 | 285 | "Cpuset allocations might fail even with a lot of memory available.\n", |
| 286 | 286 | nodemask_pr_args(nodes)); |
| @@ -1843,7 +1843,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, · 1556 unmodified lines | ||
| 1843 | 1843 | if (is_partition_valid(cs)) |
| 1844 | 1844 | adding = cpumask_and(tmp->addmask, |
| 1845 | 1845 | xcpus, parent->effective_xcpus); |
| 1846 | − } else if (is_partition_invalid(cs) && | |
| 1846 | + } else if (is_partition_invalid(cs) && !cpumask_empty(xcpus) && | |
| 1847 | 1847 | cpumask_subset(xcpus, parent->effective_xcpus)) { |
| 1848 | 1848 | struct cgroup_subsys_state *css; |
| 1849 | 1849 | struct cpuset *child; |
| @@ -3358,14 +3358,12 @@ static ssize_t cpuset_partition_write(struct kernfs_open_file *of, char *buf, · 1508 unmodified lines | ||
| 3358 | 3358 | else |
| 3359 | 3359 | return -EINVAL; |
| 3360 | 3360 | |
| 3361 | − css_get(&cs->css); | |
| 3362 | 3361 | cpus_read_lock(); |
| 3363 | 3362 | mutex_lock(&cpuset_mutex); |
| 3364 | 3363 | if (is_cpuset_online(cs)) |
| 3365 | 3364 | retval = update_prstate(cs, val); |
| 3366 | 3365 | mutex_unlock(&cpuset_mutex); |
| 3367 | 3366 | cpus_read_unlock(); |
| 3368 | − css_put(&cs->css); | |
| 3369 | 3367 | return retval ?: nbytes; |
| 3370 | 3368 | } |
| 3371 | 3369 | |
| @@ -3870,9 +3868,10 @@ retry: · 498 unmodified lines | ||
| 3870 | 3868 | partcmd = partcmd_invalidate; |
| 3871 | 3869 | /* |
| 3872 | 3870 | * On the other hand, an invalid partition root may be transitioned |
| 3873 | − * back to a regular one. | |
| 3871 | + * back to a regular one with a non-empty effective xcpus. | |
| 3874 | 3872 | */ |
| 3875 | − else if (is_partition_valid(parent) && is_partition_invalid(cs)) | |
| 3873 | + else if (is_partition_valid(parent) && is_partition_invalid(cs) && | |
| 3874 | + !cpumask_empty(cs->effective_xcpus)) | |
| 3876 | 3875 | partcmd = partcmd_update; |
| 3877 | 3876 | |
| 3878 | 3877 | if (partcmd >= 0) { |
| @@ -479,6 +479,9 @@ void css_rstat_exit(struct cgroup_subsys_state *css) · 478 unmodified lines | ||
| 479 | 479 | if (!css_uses_rstat(css)) |
| 480 | 480 | return; |
| 481 | 481 | |
| 482 | + if (!css->rstat_cpu) | |
| 483 | + return; | |
| 484 | + | |
| 482 | 485 | css_rstat_flush(css); |
| 483 | 486 | |
| 484 | 487 | /* sanity check */ |
| @@ -483,8 +483,6 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem) · 482 unmodified lines | ||
| 483 | 483 | pr_err("Reserved memory: unable to setup CMA region\n"); |
| 484 | 484 | return err; |
| 485 | 485 | } |
| 486 | − /* Architecture specific contiguous memory fixup. */ | |
| 487 | − dma_contiguous_early_fixup(rmem->base, rmem->size); | |
| 488 | 486 | |
| 489 | 487 | if (default_cma) |
| 490 | 488 | dma_contiguous_default_area = cma; |
| @@ -102,8 +102,8 @@ static int atomic_pool_expand(struct gen_pool *pool, size_t pool_size, · 101 unmodified lines | ||
| 102 | 102 | |
| 103 | 103 | #ifdef CONFIG_DMA_DIRECT_REMAP |
| 104 | 104 | addr = dma_common_contiguous_remap(page, pool_size, |
| 105 | − pgprot_dmacoherent(PAGE_KERNEL), | |
| 106 | − __builtin_return_address(0)); | |
| 105 | + pgprot_decrypted(pgprot_dmacoherent(PAGE_KERNEL)), | |
| 106 | + __builtin_return_address(0)); | |
| 107 | 107 | if (!addr) |
| 108 | 108 | goto free_page; |
| 109 | 109 | #else |
| @@ -2665,6 +2665,9 @@ static void perf_log_itrace_start(struct perf_event *event); · 2664 unmodified lines | ||
| 2665 | 2665 | |
| 2666 | 2666 | static void perf_event_unthrottle(struct perf_event *event, bool start) |
| 2667 | 2667 | { |
| 2668 | + if (event->state != PERF_EVENT_STATE_ACTIVE) | |
| 2669 | + return; | |
| 2670 | + | |
| 2668 | 2671 | event->hw.interrupts = 0; |
| 2669 | 2672 | if (start) |
| 2670 | 2673 | event->pmu->start(event, 0); |
| @@ -2674,6 +2677,9 @@ static void perf_event_unthrottle(struct perf_event *event, bool start) · 3 unmodified lines | ||
| 2674 | 2677 | |
| 2675 | 2678 | static void perf_event_throttle(struct perf_event *event) |
| 2676 | 2679 | { |
| 2680 | + if (event->state != PERF_EVENT_STATE_ACTIVE) | |
| 2681 | + return; | |
| 2682 | + | |
| 2677 | 2683 | event->hw.interrupts = MAX_INTERRUPTS; |
| 2678 | 2684 | event->pmu->stop(event, 0); |
| 2679 | 2685 | if (event == event->group_leader) |
| @@ -144,14 +144,34 @@ static int __kho_preserve_order(struct kho_mem_track *track, unsigned long pfn, · 143 unmodified lines | ||
| 144 | 144 | unsigned int order) |
| 145 | 145 | { |
| 146 | 146 | struct kho_mem_phys_bits *bits; |
| 147 | − struct kho_mem_phys *physxa; | |
| 147 | + struct kho_mem_phys *physxa, *new_physxa; | |
| 148 | 148 | const unsigned long pfn_high = pfn >> order; |
| 149 | 149 | |
| 150 | 150 | might_sleep(); |
| 151 | 151 | |
| 152 | − physxa = xa_load_or_alloc(&track->orders, order, sizeof(*physxa)); | |
| 153 | − if (IS_ERR(physxa)) | |
| 154 | − return PTR_ERR(physxa); | |
| 152 | + physxa = xa_load(&track->orders, order); | |
| 153 | + if (!physxa) { | |
| 154 | + int err; | |
| 155 | + | |
| 156 | + new_physxa = kzalloc(sizeof(*physxa), GFP_KERNEL); | |
| 157 | + if (!new_physxa) | |
| 158 | + return -ENOMEM; | |
| 159 | + | |
| 160 | + xa_init(&new_physxa->phys_bits); | |
| 161 | + physxa = xa_cmpxchg(&track->orders, order, NULL, new_physxa, | |
| 162 | + GFP_KERNEL); | |
| 163 | + | |
| 164 | + err = xa_err(physxa); | |
| 165 | + if (err || physxa) { | |
| 166 | + xa_destroy(&new_physxa->phys_bits); | |
| 167 | + kfree(new_physxa); | |
| 168 | + | |
| 169 | + if (err) | |
| 170 | + return err; | |
| 171 | + } else { | |
| 172 | + physxa = new_physxa; | |
| 173 | + } | |
| 174 | + } | |
| 155 | 175 | |
| 156 | 176 | bits = xa_load_or_alloc(&physxa->phys_bits, pfn_high / PRESERVE_BITS, |
| 157 | 177 | sizeof(*bits)); |
| @@ -544,6 +564,7 @@ err_free_scratch_areas: · 386 unmodified lines | ||
| 544 | 564 | err_free_scratch_desc: |
| 545 | 565 | memblock_free(kho_scratch, kho_scratch_cnt * sizeof(*kho_scratch)); |
| 546 | 566 | err_disable_kho: |
| 567 | + pr_warn("Failed to reserve scratch area, disabling kexec handover\n"); | |
| 547 | 568 | kho_enable = false; |
| 548 | 569 | } |
| 549 | 570 | |
| @@ -513,13 +513,14 @@ EXPORT_SYMBOL(param_array_ops); · 512 unmodified lines | ||
| 513 | 513 | int param_set_copystring(const char *val, const struct kernel_param *kp) |
| 514 | 514 | { |
| 515 | 515 | const struct kparam_string *kps = kp->str; |
| 516 | + const size_t len = strnlen(val, kps->maxlen); | |
| 516 | 517 | |
| 517 | − if (strnlen(val, kps->maxlen) == kps->maxlen) { | |
| 518 | + if (len == kps->maxlen) { | |
| 518 | 519 | pr_err("%s: string doesn't fit in %u chars.\n", |
| 519 | 520 | kp->name, kps->maxlen-1); |
| 520 | 521 | return -ENOSPC; |
| 521 | 522 | } |
| 522 | − strcpy(kps->string, val); | |
| 523 | + memcpy(kps->string, val, len + 1); | |
| 523 | 524 | return 0; |
| 524 | 525 | } |
| 525 | 526 | EXPORT_SYMBOL(param_set_copystring); |
| @@ -841,7 +842,7 @@ static void __init param_sysfs_builtin(void) · 315 unmodified lines | ||
| 841 | 842 | dot = strchr(kp->name, '.'); |
| 842 | 843 | if (!dot) { |
| 843 | 844 | /* This happens for core_param() */ |
| 844 | − strcpy(modname, "kernel"); | |
| 845 | + strscpy(modname, "kernel"); | |
| 845 | 846 | name_len = 0; |
| 846 | 847 | } else { |
| 847 | 848 | name_len = dot - kp->name + 1; |
| @@ -5749,6 +5749,9 @@ static int scx_enable(struct sched_ext_ops *ops, struct bpf_link *link) · 5748 unmodified lines | ||
| 5749 | 5749 | __setscheduler_class(p->policy, p->prio); |
| 5750 | 5750 | struct sched_enq_and_set_ctx ctx; |
| 5751 | 5751 | |
| 5752 | + if (!tryget_task_struct(p)) | |
| 5753 | + continue; | |
| 5754 | + | |
| 5752 | 5755 | if (old_class != new_class && p->se.sched_delayed) |
| 5753 | 5756 | dequeue_task(task_rq(p), p, DEQUEUE_SLEEP | DEQUEUE_DELAYED); |
| 5754 | 5757 | |
| @@ -5761,6 +5764,7 @@ static int scx_enable(struct sched_ext_ops *ops, struct bpf_link *link) · 6 unmodified lines | ||
| 5761 | 5764 | sched_enq_and_set_task(&ctx); |
| 5762 | 5765 | |
| 5763 | 5766 | check_class_changed(task_rq(p), p, old_class, p->prio); |
| 5767 | + put_task_struct(p); | |
| 5764 | 5768 | } |
| 5765 | 5769 | scx_task_iter_stop(&sti); |
| 5766 | 5770 | percpu_up_write(&scx_fork_rwsem); |
| @@ -1397,6 +1397,7 @@ error: · 1396 unmodified lines | ||
| 1397 | 1397 | ftrace_graph_active--; |
| 1398 | 1398 | gops->saved_func = NULL; |
| 1399 | 1399 | fgraph_lru_release_index(i); |
| 1400 | + unregister_pm_notifier(&ftrace_suspend_notifier); | |
| 1400 | 1401 | } |
| 1401 | 1402 | return ret; |
| 1402 | 1403 | } |
| @@ -4661,13 +4661,17 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, · 4660 unmodified lines | ||
| 4661 | 4661 | } else { |
| 4662 | 4662 | iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash); |
| 4663 | 4663 | } |
| 4664 | + } else { | |
| 4665 | + if (hash) | |
| 4666 | + iter->hash = alloc_and_copy_ftrace_hash(hash->size_bits, hash); | |
| 4667 | + else | |
| 4668 | + iter->hash = EMPTY_HASH; | |
| 4669 | + } | |
| 4664 | 4670 | |
| 4665 | − if (!iter->hash) { | |
| 4666 | − trace_parser_put(&iter->parser); | |
| 4667 | − goto out_unlock; | |
| 4668 | − } | |
| 4669 | − } else | |
| 4670 | − iter->hash = hash; | |
| 4671 | + if (!iter->hash) { | |
| 4672 | + trace_parser_put(&iter->parser); | |
| 4673 | + goto out_unlock; | |
| 4674 | + } | |
| 4671 | 4675 | |
| 4672 | 4676 | ret = 0; |
| 4673 | 4677 | |
| @@ -6543,9 +6547,6 @@ int ftrace_regex_release(struct inode *inode, struct file *file) · 1869 unmodified lines | ||
| 6543 | 6547 | ftrace_hash_move_and_update_ops(iter->ops, orig_hash, |
| 6544 | 6548 | iter->hash, filter_hash); |
| 6545 | 6549 | mutex_unlock(&ftrace_lock); |
| 6546 | − } else { | |
| 6547 | − /* For read only, the hash is the ops hash */ | |
| 6548 | − iter->hash = NULL; | |
| 6549 | 6550 | } |
| 6550 | 6551 | |
| 6551 | 6552 | mutex_unlock(&iter->ops->func_hash->regex_lock); |
| @@ -7666,7 +7666,7 @@ static __init int test_ringbuffer(void) · 7665 unmodified lines | ||
| 7666 | 7666 | rb_test_started = true; |
| 7667 | 7667 | |
| 7668 | 7668 | set_current_state(TASK_INTERRUPTIBLE); |
| 7669 | − /* Just run for 10 seconds */; | |
| 7669 | + /* Just run for 10 seconds */ | |
| 7670 | 7670 | schedule_timeout(10 * HZ); |
| 7671 | 7671 | |
| 7672 | 7672 | kthread_stop(rb_hammer); |
| @@ -1816,7 +1816,7 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf, · 1815 unmodified lines | ||
| 1816 | 1816 | |
| 1817 | 1817 | ret = get_user(ch, ubuf++); |
| 1818 | 1818 | if (ret) |
| 1819 | − return ret; | |
| 1819 | + goto fail; | |
| 1820 | 1820 | |
| 1821 | 1821 | read++; |
| 1822 | 1822 | cnt--; |
| @@ -1830,7 +1830,7 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf, · 7 unmodified lines | ||
| 1830 | 1830 | while (cnt && isspace(ch)) { |
| 1831 | 1831 | ret = get_user(ch, ubuf++); |
| 1832 | 1832 | if (ret) |
| 1833 | − return ret; | |
| 1833 | + goto fail; | |
| 1834 | 1834 | read++; |
| 1835 | 1835 | cnt--; |
| 1836 | 1836 | } |
| @@ -1848,12 +1848,14 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf, · 11 unmodified lines | ||
| 1848 | 1848 | while (cnt && !isspace(ch) && ch) { |
| 1849 | 1849 | if (parser->idx < parser->size - 1) |
| 1850 | 1850 | parser->buffer[parser->idx++] = ch; |
| 1851 | − else | |
| 1852 | − return -EINVAL; | |
| 1851 | + else { | |
| 1852 | + ret = -EINVAL; | |
| 1853 | + goto fail; | |
| 1854 | + } | |
| 1853 | 1855 | |
| 1854 | 1856 | ret = get_user(ch, ubuf++); |
| 1855 | 1857 | if (ret) |
| 1856 | − return ret; | |
| 1858 | + goto fail; | |
| 1857 | 1859 | read++; |
| 1858 | 1860 | cnt--; |
| 1859 | 1861 | } |
| @@ -1868,11 +1870,15 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf, · 8 unmodified lines | ||
| 1868 | 1870 | /* Make sure the parsed string always terminates with '\0'. */ |
| 1869 | 1871 | parser->buffer[parser->idx] = 0; |
| 1870 | 1872 | } else { |
| 1871 | − return -EINVAL; | |
| 1873 | + ret = -EINVAL; | |
| 1874 | + goto fail; | |
| 1872 | 1875 | } |
| 1873 | 1876 | |
| 1874 | 1877 | *ppos += read; |
| 1875 | 1878 | return read; |
| 1879 | +fail: | |
| 1880 | + trace_parser_fail(parser); | |
| 1881 | + return ret; | |
| 1876 | 1882 | } |
| 1877 | 1883 | |
| 1878 | 1884 | /* TODO add a seq_buf_to_buffer() */ |
| @@ -10632,10 +10638,10 @@ static void ftrace_dump_one(struct trace_array *tr, enum ftrace_dump_mode dump_m · 8753 unmodified lines | ||
| 10632 | 10638 | ret = print_trace_line(&iter); |
| 10633 | 10639 | if (ret != TRACE_TYPE_NO_CONSUME) |
| 10634 | 10640 | trace_consume(&iter); |
| 10641 | + | |
| 10642 | + trace_printk_seq(&iter.seq); | |
| 10635 | 10643 | } |
| 10636 | 10644 | touch_nmi_watchdog(); |
| 10637 | − | |
| 10638 | − trace_printk_seq(&iter.seq); | |
| 10639 | 10645 | } |
| 10640 | 10646 | |
| 10641 | 10647 | if (!cnt) |
| @@ -1292,6 +1292,7 @@ bool ftrace_event_is_function(struct trace_event_call *call); · 1291 unmodified lines | ||
| 1292 | 1292 | */ |
| 1293 | 1293 | struct trace_parser { |
| 1294 | 1294 | bool cont; |
| 1295 | + bool fail; | |
| 1295 | 1296 | char *buffer; |
| 1296 | 1297 | unsigned idx; |
| 1297 | 1298 | unsigned size; |
| @@ -1299,7 +1300,7 @@ struct trace_parser { · 1 unmodified line | ||
| 1299 | 1300 | |
| 1300 | 1301 | static inline bool trace_parser_loaded(struct trace_parser *parser) |
| 1301 | 1302 | { |
| 1302 | − return (parser->idx != 0); | |
| 1303 | + return !parser->fail && parser->idx != 0; | |
| 1303 | 1304 | } |
| 1304 | 1305 | |
| 1305 | 1306 | static inline bool trace_parser_cont(struct trace_parser *parser) |
| @@ -1313,6 +1314,11 @@ static inline void trace_parser_clear(struct trace_parser *parser) · 7 unmodified lines | ||
| 1313 | 1314 | parser->idx = 0; |
| 1314 | 1315 | } |
| 1315 | 1316 | |
| 1317 | +static inline void trace_parser_fail(struct trace_parser *parser) | |
| 1318 | +{ | |
| 1319 | + parser->fail = true; | |
| 1320 | +} | |
| 1321 | + | |
| 1316 | 1322 | extern int trace_parser_get_init(struct trace_parser *parser, int size); |
| 1317 | 1323 | extern void trace_parser_put(struct trace_parser *parser); |
| 1318 | 1324 | extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf, |
| @@ -27,14 +27,21 @@ struct fgraph_cpu_data { · 26 unmodified lines | ||
| 27 | 27 | unsigned long enter_funcs[FTRACE_RETFUNC_DEPTH]; |
| 28 | 28 | }; |
| 29 | 29 | |
| 30 | +struct fgraph_ent_args { | |
| 31 | + struct ftrace_graph_ent_entry ent; | |
| 32 | + /* Force the sizeof of args[] to have FTRACE_REGS_MAX_ARGS entries */ | |
| 33 | + unsigned long args[FTRACE_REGS_MAX_ARGS]; | |
| 34 | +}; | |
| 35 | + | |
| 30 | 36 | struct fgraph_data { |
| 31 | 37 | struct fgraph_cpu_data __percpu *cpu_data; |
| 32 | 38 | |
| 33 | 39 | /* Place to preserve last processed entry. */ |
| 34 | 40 | union { |
| 35 | − struct ftrace_graph_ent_entry ent; | |
| 41 | + struct fgraph_ent_args ent; | |
| 42 | + /* TODO allow retaddr to have args */ | |
| 36 | 43 | struct fgraph_retaddr_ent_entry rent; |
| 37 | − } ent; | |
| 44 | + }; | |
| 38 | 45 | struct ftrace_graph_ret_entry ret; |
| 39 | 46 | int failed; |
| 40 | 47 | int cpu; |
| @@ -627,10 +634,13 @@ get_return_for_leaf(struct trace_iterator *iter, · 586 unmodified lines | ||
| 627 | 634 | * Save current and next entries for later reference |
| 628 | 635 | * if the output fails. |
| 629 | 636 | */ |
| 630 | − if (unlikely(curr->ent.type == TRACE_GRAPH_RETADDR_ENT)) | |
| 631 | − data->ent.rent = *(struct fgraph_retaddr_ent_entry *)curr; | |
| 632 | − else | |
| 633 | − data->ent.ent = *curr; | |
| 637 | + if (unlikely(curr->ent.type == TRACE_GRAPH_RETADDR_ENT)) { | |
| 638 | + data->rent = *(struct fgraph_retaddr_ent_entry *)curr; | |
| 639 | + } else { | |
| 640 | + int size = min((int)sizeof(data->ent), (int)iter->ent_size); | |
| 641 | + | |
| 642 | + memcpy(&data->ent, curr, size); | |
| 643 | + } | |
| 634 | 644 | /* |
| 635 | 645 | * If the next event is not a return type, then |
| 636 | 646 | * we only care about what type it is. Otherwise we can |
| @@ -254,4 +254,10 @@ const struct movable_operations balloon_mops = { · 253 unmodified lines | ||
| 254 | 254 | .putback_page = balloon_page_putback, |
| 255 | 255 | }; |
| 256 | 256 | |
| 257 | +static int __init balloon_init(void) | |
| 258 | +{ | |
| 259 | + return set_movable_ops(&balloon_mops, PGTY_offline); | |
| 260 | +} | |
| 261 | +core_initcall(balloon_init); | |
| 262 | + | |
| 257 | 263 | #endif /* CONFIG_BALLOON_COMPACTION */ |
| @@ -845,6 +845,18 @@ static struct damos_filter *damos_nth_filter(int n, struct damos *s) · 844 unmodified lines | ||
| 845 | 845 | return NULL; |
| 846 | 846 | } |
| 847 | 847 | |
| 848 | +static struct damos_filter *damos_nth_ops_filter(int n, struct damos *s) | |
| 849 | +{ | |
| 850 | + struct damos_filter *filter; | |
| 851 | + int i = 0; | |
| 852 | + | |
| 853 | + damos_for_each_ops_filter(filter, s) { | |
| 854 | + if (i++ == n) | |
| 855 | + return filter; | |
| 856 | + } | |
| 857 | + return NULL; | |
| 858 | +} | |
| 859 | + | |
| 848 | 860 | static void damos_commit_filter_arg( |
| 849 | 861 | struct damos_filter *dst, struct damos_filter *src) |
| 850 | 862 | { |
| @@ -871,6 +883,7 @@ static void damos_commit_filter( · 20 unmodified lines | ||
| 871 | 883 | { |
| 872 | 884 | dst->type = src->type; |
| 873 | 885 | dst->matching = src->matching; |
| 886 | + dst->allow = src->allow; | |
| 874 | 887 | damos_commit_filter_arg(dst, src); |
| 875 | 888 | } |
| 876 | 889 | |
| @@ -908,7 +921,7 @@ static int damos_commit_ops_filters(struct damos *dst, struct damos *src) · 31 unmodified lines | ||
| 908 | 921 | int i = 0, j = 0; |
| 909 | 922 | |
| 910 | 923 | damos_for_each_ops_filter_safe(dst_filter, next, dst) { |
| 911 | − src_filter = damos_nth_filter(i++, src); | |
| 924 | + src_filter = damos_nth_ops_filter(i++, src); | |
| 912 | 925 | if (src_filter) |
| 913 | 926 | damos_commit_filter(dst_filter, src_filter); |
| 914 | 927 | else |
| @@ -2158,8 +2158,8 @@ static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme) · 2157 unmodified lines | ||
| 2158 | 2158 | { |
| 2159 | 2159 | damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); |
| 2160 | 2160 | kobject_put(&scheme->access_pattern->kobj); |
| 2161 | − kobject_put(&scheme->dests->kobj); | |
| 2162 | 2161 | damos_sysfs_dests_rm_dirs(scheme->dests); |
| 2162 | + kobject_put(&scheme->dests->kobj); | |
| 2163 | 2163 | damon_sysfs_quotas_rm_dirs(scheme->quotas); |
| 2164 | 2164 | kobject_put(&scheme->quotas->kobj); |
| 2165 | 2165 | kobject_put(&scheme->watermarks->kobj); |
| @@ -990,29 +990,34 @@ static void __init destroy_args(struct pgtable_debug_args *args) · 989 unmodified lines | ||
| 990 | 990 | |
| 991 | 991 | /* Free page table entries */ |
| 992 | 992 | if (args->start_ptep) { |
| 993 | + pmd_clear(args->pmdp); | |
| 993 | 994 | pte_free(args->mm, args->start_ptep); |
| 994 | 995 | mm_dec_nr_ptes(args->mm); |
| 995 | 996 | } |
| 996 | 997 | |
| 997 | 998 | if (args->start_pmdp) { |
| 999 | + pud_clear(args->pudp); | |
| 998 | 1000 | pmd_free(args->mm, args->start_pmdp); |
| 999 | 1001 | mm_dec_nr_pmds(args->mm); |
| 1000 | 1002 | } |
| 1001 | 1003 | |
| 1002 | 1004 | if (args->start_pudp) { |
| 1005 | + p4d_clear(args->p4dp); | |
| 1003 | 1006 | pud_free(args->mm, args->start_pudp); |
| 1004 | 1007 | mm_dec_nr_puds(args->mm); |
| 1005 | 1008 | } |
| 1006 | 1009 | |
| 1007 | − if (args->start_p4dp) | |
| 1010 | + if (args->start_p4dp) { | |
| 1011 | + pgd_clear(args->pgdp); | |
| 1008 | 1012 | p4d_free(args->mm, args->start_p4dp); |
| 1013 | + } | |
| 1009 | 1014 | |
| 1010 | 1015 | /* Free vma and mm struct */ |
| 1011 | 1016 | if (args->vma) |
| 1012 | 1017 | vm_area_free(args->vma); |
| 1013 | 1018 | |
| 1014 | 1019 | if (args->mm) |
| 1015 | − mmdrop(args->mm); | |
| 1020 | + mmput(args->mm); | |
| 1016 | 1021 | } |
| 1017 | 1022 | |
| 1018 | 1023 | static struct page * __init |
| @@ -780,9 +780,9 @@ bool __init_memblock memblock_validate_numa_coverage(unsigned long threshold_byt · 779 unmodified lines | ||
| 780 | 780 | } |
| 781 | 781 | |
| 782 | 782 | if ((nr_pages << PAGE_SHIFT) > threshold_bytes) { |
| 783 | − mem_size_mb = memblock_phys_mem_size() >> 20; | |
| 783 | + mem_size_mb = memblock_phys_mem_size() / SZ_1M; | |
| 784 | 784 | pr_err("NUMA: no nodes coverage for %luMB of %luMB RAM\n", |
| 785 | − (nr_pages << PAGE_SHIFT) >> 20, mem_size_mb); | |
| 785 | + (nr_pages << PAGE_SHIFT) / SZ_1M, mem_size_mb); | |
| 786 | 786 | return false; |
| 787 | 787 | } |
| 788 | 788 | |
| @@ -1091,13 +1091,20 @@ int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size) · 302 unmodified lines | ||
| 1091 | 1091 | |
| 1092 | 1092 | /** |
| 1093 | 1093 | * memblock_reserved_mark_noinit - Mark a reserved memory region with flag |
| 1094 | − * MEMBLOCK_RSRV_NOINIT which results in the struct pages not being initialized | |
| 1095 | − * for this region. | |
| 1094 | + * MEMBLOCK_RSRV_NOINIT | |
| 1095 | + * | |
| 1096 | 1096 | * @base: the base phys addr of the region |
| 1097 | 1097 | * @size: the size of the region |
| 1098 | 1098 | * |
| 1099 | − * struct pages will not be initialized for reserved memory regions marked with | |
| 1100 | − * %MEMBLOCK_RSRV_NOINIT. | |
| 1099 | + * The struct pages for the reserved regions marked %MEMBLOCK_RSRV_NOINIT will | |
| 1100 | + * not be fully initialized to allow the caller optimize their initialization. | |
| 1101 | + * | |
| 1102 | + * When %CONFIG_DEFERRED_STRUCT_PAGE_INIT is enabled, setting this flag | |
| 1103 | + * completely bypasses the initialization of struct pages for such region. | |
| 1104 | + * | |
| 1105 | + * When %CONFIG_DEFERRED_STRUCT_PAGE_INIT is disabled, struct pages in this | |
| 1106 | + * region will be initialized with default values but won't be marked as | |
| 1107 | + * reserved. | |
| 1101 | 1108 | * |
| 1102 | 1109 | * Return: 0 on success, -errno on failure. |
| 1103 | 1110 | */ |
| @@ -853,9 +853,17 @@ static int hwpoison_hugetlb_range(pte_t *ptep, unsigned long hmask, · 852 unmodified lines | ||
| 853 | 853 | #define hwpoison_hugetlb_range NULL |
| 854 | 854 | #endif |
| 855 | 855 | |
| 856 | +static int hwpoison_test_walk(unsigned long start, unsigned long end, | |
| 857 | + struct mm_walk *walk) | |
| 858 | +{ | |
| 859 | + /* We also want to consider pages mapped into VM_PFNMAP. */ | |
| 860 | + return 0; | |
| 861 | +} | |
| 862 | + | |
| 856 | 863 | static const struct mm_walk_ops hwpoison_walk_ops = { |
| 857 | 864 | .pmd_entry = hwpoison_pte_range, |
| 858 | 865 | .hugetlb_entry = hwpoison_hugetlb_range, |
| 866 | + .test_walk = hwpoison_test_walk, | |
| 859 | 867 | .walk_lock = PGWALK_RDLOCK, |
| 860 | 868 | }; |
| 861 | 869 | |
| @@ -43,8 +43,6 @@ · 42 unmodified lines | ||
| 43 | 43 | #include <linux/sched/sysctl.h> |
| 44 | 44 | #include <linux/memory-tiers.h> |
| 45 | 45 | #include <linux/pagewalk.h> |
| 46 | −#include <linux/balloon_compaction.h> | |
| 47 | −#include <linux/zsmalloc.h> | |
| 48 | 46 | |
| 49 | 47 | #include <asm/tlbflush.h> |
| 50 | 48 | |
| @@ -53,6 +51,33 @@ · 2 unmodified lines | ||
| 53 | 51 | #include "internal.h" |
| 54 | 52 | #include "swap.h" |
| 55 | 53 | |
| 54 | +static const struct movable_operations *offline_movable_ops; | |
| 55 | +static const struct movable_operations *zsmalloc_movable_ops; | |
| 56 | + | |
| 57 | +int set_movable_ops(const struct movable_operations *ops, enum pagetype type) | |
| 58 | +{ | |
| 59 | + /* | |
| 60 | + * We only allow for selected types and don't handle concurrent | |
| 61 | + * registration attempts yet. | |
| 62 | + */ | |
| 63 | + switch (type) { | |
| 64 | + case PGTY_offline: | |
| 65 | + if (offline_movable_ops && ops) | |
| 66 | + return -EBUSY; | |
| 67 | + offline_movable_ops = ops; | |
| 68 | + break; | |
| 69 | + case PGTY_zsmalloc: | |
| 70 | + if (zsmalloc_movable_ops && ops) | |
| 71 | + return -EBUSY; | |
| 72 | + zsmalloc_movable_ops = ops; | |
| 73 | + break; | |
| 74 | + default: | |
| 75 | + return -EINVAL; | |
| 76 | + } | |
| 77 | + return 0; | |
| 78 | +} | |
| 79 | +EXPORT_SYMBOL_GPL(set_movable_ops); | |
| 80 | + | |
| 56 | 81 | static const struct movable_operations *page_movable_ops(struct page *page) |
| 57 | 82 | { |
| 58 | 83 | VM_WARN_ON_ONCE_PAGE(!page_has_movable_ops(page), page); |
| @@ -62,15 +87,12 @@ static const struct movable_operations *page_movable_ops(struct page *page) · 3 unmodified lines | ||
| 62 | 87 | * it as movable, the page type must be sticky until the page gets freed |
| 63 | 88 | * back to the buddy. |
| 64 | 89 | */ |
| 65 | −#ifdef CONFIG_BALLOON_COMPACTION | |
| 66 | 90 | if (PageOffline(page)) |
| 67 | 91 | /* Only balloon compaction sets PageOffline pages movable. */ |
| 68 | − return &balloon_mops; | |
| 69 | −#endif /* CONFIG_BALLOON_COMPACTION */ | |
| 70 | −#if defined(CONFIG_ZSMALLOC) && defined(CONFIG_COMPACTION) | |
| 92 | + return offline_movable_ops; | |
| 71 | 93 | if (PageZsmalloc(page)) |
| 72 | − return &zsmalloc_mops; | |
| 73 | −#endif /* defined(CONFIG_ZSMALLOC) && defined(CONFIG_COMPACTION) */ | |
| 94 | + return zsmalloc_movable_ops; | |
| 95 | + | |
| 74 | 96 | return NULL; |
| 75 | 97 | } |
| 76 | 98 | |
| @@ -323,6 +323,25 @@ static inline bool arch_supports_page_table_move(void) · 322 unmodified lines | ||
| 323 | 323 | } |
| 324 | 324 | #endif |
| 325 | 325 | |
| 326 | +static inline bool uffd_supports_page_table_move(struct pagetable_move_control *pmc) | |
| 327 | +{ | |
| 328 | + /* | |
| 329 | + * If we are moving a VMA that has uffd-wp registered but with | |
| 330 | + * remap events disabled (new VMA will not be registered with uffd), we | |
| 331 | + * need to ensure that the uffd-wp state is cleared from all pgtables. | |
| 332 | + * This means recursing into lower page tables in move_page_tables(). | |
| 333 | + * | |
| 334 | + * We might get called with VMAs reversed when recovering from a | |
| 335 | + * failed page table move. In that case, the | |
| 336 | + * "old"-but-actually-"originally new" VMA during recovery will not have | |
| 337 | + * a uffd context. Recursing into lower page tables during the original | |
| 338 | + * move but not during the recovery move will cause trouble, because we | |
| 339 | + * run into already-existing page tables. So check both VMAs. | |
| 340 | + */ | |
| 341 | + return !vma_has_uffd_without_event_remap(pmc->old) && | |
| 342 | + !vma_has_uffd_without_event_remap(pmc->new); | |
| 343 | +} | |
| 344 | + | |
| 326 | 345 | #ifdef CONFIG_HAVE_MOVE_PMD |
| 327 | 346 | static bool move_normal_pmd(struct pagetable_move_control *pmc, |
| 328 | 347 | pmd_t *old_pmd, pmd_t *new_pmd) |
| @@ -335,6 +354,8 @@ static bool move_normal_pmd(struct pagetable_move_control *pmc, · 6 unmodified lines | ||
| 335 | 354 | |
| 336 | 355 | if (!arch_supports_page_table_move()) |
| 337 | 356 | return false; |
| 357 | + if (!uffd_supports_page_table_move(pmc)) | |
| 358 | + return false; | |
| 338 | 359 | /* |
| 339 | 360 | * The destination pmd shouldn't be established, free_pgtables() |
| 340 | 361 | * should have released it. |
| @@ -361,15 +382,6 @@ static bool move_normal_pmd(struct pagetable_move_control *pmc, · 20 unmodified lines | ||
| 361 | 382 | if (WARN_ON_ONCE(!pmd_none(*new_pmd))) |
| 362 | 383 | return false; |
| 363 | 384 | |
| 364 | − /* If this pmd belongs to a uffd vma with remap events disabled, we need | |
| 365 | − * to ensure that the uffd-wp state is cleared from all pgtables. This | |
| 366 | − * means recursing into lower page tables in move_page_tables(), and we | |
| 367 | − * can reuse the existing code if we simply treat the entry as "not | |
| 368 | − * moved". | |
| 369 | − */ | |
| 370 | − if (vma_has_uffd_without_event_remap(vma)) | |
| 371 | − return false; | |
| 372 | − | |
| 373 | 385 | /* |
| 374 | 386 | * We don't have to worry about the ordering of src and dst |
| 375 | 387 | * ptlocks because exclusive mmap_lock prevents deadlock. |
| @@ -418,6 +430,8 @@ static bool move_normal_pud(struct pagetable_move_control *pmc, · 42 unmodified lines | ||
| 418 | 430 | |
| 419 | 431 | if (!arch_supports_page_table_move()) |
| 420 | 432 | return false; |
| 433 | + if (!uffd_supports_page_table_move(pmc)) | |
| 434 | + return false; | |
| 421 | 435 | /* |
| 422 | 436 | * The destination pud shouldn't be established, free_pgtables() |
| 423 | 437 | * should have released it. |
| @@ -425,15 +439,6 @@ static bool move_normal_pud(struct pagetable_move_control *pmc, · 1 unmodified line | ||
| 425 | 439 | if (WARN_ON_ONCE(!pud_none(*new_pud))) |
| 426 | 440 | return false; |
| 427 | 441 | |
| 428 | − /* If this pud belongs to a uffd vma with remap events disabled, we need | |
| 429 | − * to ensure that the uffd-wp state is cleared from all pgtables. This | |
| 430 | − * means recursing into lower page tables in move_page_tables(), and we | |
| 431 | − * can reuse the existing code if we simply treat the entry as "not | |
| 432 | − * moved". | |
| 433 | − */ | |
| 434 | − if (vma_has_uffd_without_event_remap(vma)) | |
| 435 | − return false; | |
| 436 | − | |
| 437 | 442 | /* |
| 438 | 443 | * We don't have to worry about the ordering of src and dst |
| 439 | 444 | * ptlocks because exclusive mmap_lock prevents deadlock. |
| @@ -1620,7 +1625,7 @@ static void notify_uffd(struct vma_remap_struct *vrm, bool failed) · 1180 unmodified lines | ||
| 1620 | 1625 | |
| 1621 | 1626 | static bool vma_multi_allowed(struct vm_area_struct *vma) |
| 1622 | 1627 | { |
| 1623 | − struct file *file; | |
| 1628 | + struct file *file = vma->vm_file; | |
| 1624 | 1629 | |
| 1625 | 1630 | /* |
| 1626 | 1631 | * We can't support moving multiple uffd VMAs as notify requires |
| @@ -1633,15 +1638,17 @@ static bool vma_multi_allowed(struct vm_area_struct *vma) · 6 unmodified lines | ||
| 1633 | 1638 | * Custom get unmapped area might result in MREMAP_FIXED not |
| 1634 | 1639 | * being obeyed. |
| 1635 | 1640 | */ |
| 1636 | − file = vma->vm_file; | |
| 1637 | − if (file && !vma_is_shmem(vma) && !is_vm_hugetlb_page(vma)) { | |
| 1638 | − const struct file_operations *fop = file->f_op; | |
| 1639 | − | |
| 1640 | − if (fop->get_unmapped_area) | |
| 1641 | − return false; | |
| 1642 | − } | |
| 1641 | + if (!file || !file->f_op->get_unmapped_area) | |
| 1642 | + return true; | |
| 1643 | + /* Known good. */ | |
| 1644 | + if (vma_is_shmem(vma)) | |
| 1645 | + return true; | |
| 1646 | + if (is_vm_hugetlb_page(vma)) | |
| 1647 | + return true; | |
| 1648 | + if (file->f_op->get_unmapped_area == thp_get_unmapped_area) | |
| 1649 | + return true; | |
| 1643 | 1650 | |
| 1644 | − return true; | |
| 1651 | + return false; | |
| 1645 | 1652 | } |
| 1646 | 1653 | |
| 1647 | 1654 | static int check_prep_vma(struct vma_remap_struct *vrm) |
| @@ -1818,10 +1825,11 @@ static unsigned long remap_move(struct vma_remap_struct *vrm) · 170 unmodified lines | ||
| 1818 | 1825 | unsigned long start = vrm->addr; |
| 1819 | 1826 | unsigned long end = vrm->addr + vrm->old_len; |
| 1820 | 1827 | unsigned long new_addr = vrm->new_addr; |
| 1821 | − bool allowed = true, seen_vma = false; | |
| 1822 | 1828 | unsigned long target_addr = new_addr; |
| 1823 | 1829 | unsigned long res = -EFAULT; |
| 1824 | 1830 | unsigned long last_end; |
| 1831 | + bool seen_vma = false; | |
| 1832 | + | |
| 1825 | 1833 | VMA_ITERATOR(vmi, current->mm, start); |
| 1826 | 1834 | |
| 1827 | 1835 | /* |
| @@ -1834,9 +1842,7 @@ static unsigned long remap_move(struct vma_remap_struct *vrm) · 6 unmodified lines | ||
| 1834 | 1842 | unsigned long addr = max(vma->vm_start, start); |
| 1835 | 1843 | unsigned long len = min(end, vma->vm_end) - addr; |
| 1836 | 1844 | unsigned long offset, res_vma; |
| 1837 | − | |
| 1838 | − if (!allowed) | |
| 1839 | − return -EFAULT; | |
| 1845 | + bool multi_allowed; | |
| 1840 | 1846 | |
| 1841 | 1847 | /* No gap permitted at the start of the range. */ |
| 1842 | 1848 | if (!seen_vma && start < vma->vm_start) |
| @@ -1865,9 +1871,15 @@ static unsigned long remap_move(struct vma_remap_struct *vrm) · 22 unmodified lines | ||
| 1865 | 1871 | vrm->new_addr = target_addr + offset; |
| 1866 | 1872 | vrm->old_len = vrm->new_len = len; |
| 1867 | 1873 | |
| 1868 | − allowed = vma_multi_allowed(vma); | |
| 1869 | − if (seen_vma && !allowed) | |
| 1870 | − return -EFAULT; | |
| 1874 | + multi_allowed = vma_multi_allowed(vma); | |
| 1875 | + if (!multi_allowed) { | |
| 1876 | + /* This is not the first VMA, abort immediately. */ | |
| 1877 | + if (seen_vma) | |
| 1878 | + return -EFAULT; | |
| 1879 | + /* This is the first, but there are more, abort. */ | |
| 1880 | + if (vma->vm_end < end) | |
| 1881 | + return -EFAULT; | |
| 1882 | + } | |
| 1871 | 1883 | |
| 1872 | 1884 | res_vma = check_prep_vma(vrm); |
| 1873 | 1885 | if (!res_vma) |
| @@ -1876,7 +1888,7 @@ static unsigned long remap_move(struct vma_remap_struct *vrm) · 2 unmodified lines | ||
| 1876 | 1888 | return res_vma; |
| 1877 | 1889 | |
| 1878 | 1890 | if (!seen_vma) { |
| 1879 | − VM_WARN_ON_ONCE(allowed && res_vma != new_addr); | |
| 1891 | + VM_WARN_ON_ONCE(multi_allowed && res_vma != new_addr); | |
| 1880 | 1892 | res = res_vma; |
| 1881 | 1893 | } |
| 1882 | 1894 | |
| @@ -73,7 +73,7 @@ static int __init emu_setup_memblk(struct numa_meminfo *ei, · 72 unmodified lines | ||
| 73 | 73 | } |
| 74 | 74 | |
| 75 | 75 | printk(KERN_INFO "Faking node %d at [mem %#018Lx-%#018Lx] (%LuMB)\n", |
| 76 | − nid, eb->start, eb->end - 1, (eb->end - eb->start) >> 20); | |
| 76 | + nid, eb->start, eb->end - 1, (eb->end - eb->start) / SZ_1M); | |
| 77 | 77 | return 0; |
| 78 | 78 | } |
| 79 | 79 | |
| @@ -264,7 +264,7 @@ static int __init split_nodes_size_interleave_uniform(struct numa_meminfo *ei, · 184 unmodified lines | ||
| 264 | 264 | min_size = ALIGN(max(min_size, FAKE_NODE_MIN_SIZE), FAKE_NODE_MIN_SIZE); |
| 265 | 265 | if (size < min_size) { |
| 266 | 266 | pr_err("Fake node size %LuMB too small, increasing to %LuMB\n", |
| 267 | − size >> 20, min_size >> 20); | |
| 267 | + size / SZ_1M, min_size / SZ_1M); | |
| 268 | 268 | size = min_size; |
| 269 | 269 | } |
| 270 | 270 | size = ALIGN_DOWN(size, FAKE_NODE_MIN_SIZE); |
| @@ -76,7 +76,7 @@ static int __init numa_alloc_distance(void) · 75 unmodified lines | ||
| 76 | 76 | for (j = 0; j < cnt; j++) |
| 77 | 77 | numa_distance[i * cnt + j] = i == j ? |
| 78 | 78 | LOCAL_DISTANCE : REMOTE_DISTANCE; |
| 79 | − printk(KERN_DEBUG "NUMA: Initialized distance table, cnt=%d\n", cnt); | |
| 79 | + pr_debug("NUMA: Initialized distance table, cnt=%d\n", cnt); | |
| 80 | 80 | |
| 81 | 81 | return 0; |
| 82 | 82 | } |
| @@ -427,9 +427,9 @@ static int __init numa_register_meminfo(struct numa_meminfo *mi) · 344 unmodified lines | ||
| 427 | 427 | unsigned long pfn_align = node_map_pfn_alignment(); |
| 428 | 428 | |
| 429 | 429 | if (pfn_align && pfn_align < PAGES_PER_SECTION) { |
| 430 | − unsigned long node_align_mb = PFN_PHYS(pfn_align) >> 20; | |
| 430 | + unsigned long node_align_mb = PFN_PHYS(pfn_align) / SZ_1M; | |
| 431 | 431 | |
| 432 | − unsigned long sect_align_mb = PFN_PHYS(PAGES_PER_SECTION) >> 20; | |
| 432 | + unsigned long sect_align_mb = PFN_PHYS(PAGES_PER_SECTION) / SZ_1M; | |
| 433 | 433 | |
| 434 | 434 | pr_warn("Node alignment %luMB < min %luMB, rejecting NUMA config\n", |
| 435 | 435 | node_align_mb, sect_align_mb); |
| @@ -5772,9 +5772,9 @@ static int __init init_lru_gen(void) · 5771 unmodified lines | ||
| 5772 | 5772 | if (sysfs_create_group(mm_kobj, &lru_gen_attr_group)) |
| 5773 | 5773 | pr_err("lru_gen: failed to create sysfs group\n"); |
| 5774 | 5774 | |
| 5775 | − debugfs_create_file_aux_num("lru_gen", 0644, NULL, NULL, 1, | |
| 5775 | + debugfs_create_file_aux_num("lru_gen", 0644, NULL, NULL, false, | |
| 5776 | 5776 | &lru_gen_rw_fops); |
| 5777 | − debugfs_create_file_aux_num("lru_gen_full", 0444, NULL, NULL, 0, | |
| 5777 | + debugfs_create_file_aux_num("lru_gen_full", 0444, NULL, NULL, true, | |
| 5778 | 5778 | &lru_gen_ro_fops); |
| 5779 | 5779 | |
| 5780 | 5780 | return 0; |
| @@ -2246,8 +2246,15 @@ EXPORT_SYMBOL_GPL(zs_destroy_pool); · 2245 unmodified lines | ||
| 2246 | 2246 | |
| 2247 | 2247 | static int __init zs_init(void) |
| 2248 | 2248 | { |
| 2249 | + int rc __maybe_unused; | |
| 2250 | + | |
| 2249 | 2251 | #ifdef CONFIG_ZPOOL |
| 2250 | 2252 | zpool_register_driver(&zs_zpool_driver); |
| 2253 | +#endif | |
| 2254 | +#ifdef CONFIG_COMPACTION | |
| 2255 | + rc = set_movable_ops(&zsmalloc_mops, PGTY_zsmalloc); | |
| 2256 | + if (rc) | |
| 2257 | + return rc; | |
| 2251 | 2258 | #endif |
| 2252 | 2259 | zs_stat_init(); |
| 2253 | 2260 | return 0; |
| @@ -2257,6 +2264,9 @@ static void __exit zs_exit(void) · 3 unmodified lines | ||
| 2257 | 2264 | { |
| 2258 | 2265 | #ifdef CONFIG_ZPOOL |
| 2259 | 2266 | zpool_unregister_driver(&zs_zpool_driver); |
| 2267 | +#endif | |
| 2268 | +#ifdef CONFIG_COMPACTION | |
| 2269 | + set_movable_ops(NULL, PGTY_zsmalloc); | |
| 2260 | 2270 | #endif |
| 2261 | 2271 | zs_stat_exit(); |
| 2262 | 2272 | } |
| @@ -635,18 +635,27 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) · 634 unmodified lines | ||
| 635 | 635 | |
| 636 | 636 | skb->dev = NULL; /* for paths shared with net_device interfaces */ |
| 637 | 637 | if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { |
| 638 | − atm_return_tx(vcc, skb); | |
| 639 | − kfree_skb(skb); | |
| 640 | 638 | error = -EFAULT; |
| 641 | − goto out; | |
| 639 | + goto free_skb; | |
| 642 | 640 | } |
| 643 | 641 | if (eff != size) |
| 644 | 642 | memset(skb->data + size, 0, eff-size); |
| 643 | + | |
| 644 | + if (vcc->dev->ops->pre_send) { | |
| 645 | + error = vcc->dev->ops->pre_send(vcc, skb); | |
| 646 | + if (error) | |
| 647 | + goto free_skb; | |
| 648 | + } | |
| 649 | + | |
| 645 | 650 | error = vcc->dev->ops->send(vcc, skb); |
| 646 | 651 | error = error ? error : size; |
| 647 | 652 | out: |
| 648 | 653 | release_sock(sk); |
| 649 | 654 | return error; |
| 655 | +free_skb: | |
| 656 | + atm_return_tx(vcc, skb); | |
| 657 | + kfree_skb(skb); | |
| 658 | + goto out; | |
| 650 | 659 | } |
| 651 | 660 | |
| 652 | 661 | __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) |
| @@ -149,8 +149,6 @@ static void hci_conn_cleanup(struct hci_conn *conn) · 148 unmodified lines | ||
| 149 | 149 | |
| 150 | 150 | hci_chan_list_flush(conn); |
| 151 | 151 | |
| 152 | − hci_conn_hash_del(hdev, conn); | |
| 153 | − | |
| 154 | 152 | if (HCI_CONN_HANDLE_UNSET(conn->handle)) |
| 155 | 153 | ida_free(&hdev->unset_handle_ida, conn->handle); |
| 156 | 154 | |
| @@ -1152,28 +1150,54 @@ void hci_conn_del(struct hci_conn *conn) · 995 unmodified lines | ||
| 1152 | 1150 | disable_delayed_work_sync(&conn->auto_accept_work); |
| 1153 | 1151 | disable_delayed_work_sync(&conn->idle_work); |
| 1154 | 1152 | |
| 1155 | − if (conn->type == ACL_LINK) { | |
| 1156 | − /* Unacked frames */ | |
| 1157 | − hdev->acl_cnt += conn->sent; | |
| 1158 | − } else if (conn->type == LE_LINK) { | |
| 1159 | − cancel_delayed_work(&conn->le_conn_timeout); | |
| 1153 | + /* Remove the connection from the list so unacked logic can detect when | |
| 1154 | + * a certain pool is not being utilized. | |
| 1155 | + */ | |
| 1156 | + hci_conn_hash_del(hdev, conn); | |
| 1160 | 1157 | |
| 1161 | − if (hdev->le_pkts) | |
| 1162 | − hdev->le_cnt += conn->sent; | |
| 1158 | + /* Handle unacked frames: | |
| 1159 | + * | |
| 1160 | + * - In case there are no connection, or if restoring the buffers | |
| 1161 | + * considered in transist would overflow, restore all buffers to the | |
| 1162 | + * pool. | |
| 1163 | + * - Otherwise restore just the buffers considered in transit for the | |
| 1164 | + * hci_conn | |
| 1165 | + */ | |
| 1166 | + switch (conn->type) { | |
| 1167 | + case ACL_LINK: | |
| 1168 | + if (!hci_conn_num(hdev, ACL_LINK) || | |
| 1169 | + hdev->acl_cnt + conn->sent > hdev->acl_pkts) | |
| 1170 | + hdev->acl_cnt = hdev->acl_pkts; | |
| 1163 | 1171 | else |
| 1164 | 1172 | hdev->acl_cnt += conn->sent; |
| 1165 | − } else { | |
| 1166 | − /* Unacked ISO frames */ | |
| 1167 | − if (conn->type == CIS_LINK || | |
| 1168 | − conn->type == BIS_LINK || | |
| 1169 | − conn->type == PA_LINK) { | |
| 1170 | − if (hdev->iso_pkts) | |
| 1171 | − hdev->iso_cnt += conn->sent; | |
| 1172 | − else if (hdev->le_pkts) | |
| 1173 | + break; | |
| 1174 | + case LE_LINK: | |
| 1175 | + cancel_delayed_work(&conn->le_conn_timeout); | |
| 1176 | + | |
| 1177 | + if (hdev->le_pkts) { | |
| 1178 | + if (!hci_conn_num(hdev, LE_LINK) || | |
| 1179 | + hdev->le_cnt + conn->sent > hdev->le_pkts) | |
| 1180 | + hdev->le_cnt = hdev->le_pkts; | |
| 1181 | + else | |
| 1173 | 1182 | hdev->le_cnt += conn->sent; |
| 1183 | + } else { | |
| 1184 | + if ((!hci_conn_num(hdev, LE_LINK) && | |
| 1185 | + !hci_conn_num(hdev, ACL_LINK)) || | |
| 1186 | + hdev->acl_cnt + conn->sent > hdev->acl_pkts) | |
| 1187 | + hdev->acl_cnt = hdev->acl_pkts; | |
| 1174 | 1188 | else |
| 1175 | 1189 | hdev->acl_cnt += conn->sent; |
| 1176 | 1190 | } |
| 1191 | + break; | |
| 1192 | + case CIS_LINK: | |
| 1193 | + case BIS_LINK: | |
| 1194 | + case PA_LINK: | |
| 1195 | + if (!hci_iso_count(hdev) || | |
| 1196 | + hdev->iso_cnt + conn->sent > hdev->iso_pkts) | |
| 1197 | + hdev->iso_cnt = hdev->iso_pkts; | |
| 1198 | + else | |
| 1199 | + hdev->iso_cnt += conn->sent; | |
| 1200 | + break; | |
| 1177 | 1201 | } |
| 1178 | 1202 | |
| 1179 | 1203 | skb_queue_purge(&conn->data_q); |
| @@ -2703,7 +2703,7 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) · 2702 unmodified lines | ||
| 2703 | 2703 | if (!conn) |
| 2704 | 2704 | goto unlock; |
| 2705 | 2705 | |
| 2706 | − if (status) { | |
| 2706 | + if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) { | |
| 2707 | 2707 | mgmt_disconnect_failed(hdev, &conn->dst, conn->type, |
| 2708 | 2708 | conn->dst_type, status); |
| 2709 | 2709 | |
| @@ -2718,6 +2718,12 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) · 8 unmodified lines | ||
| 2718 | 2718 | goto done; |
| 2719 | 2719 | } |
| 2720 | 2720 | |
| 2721 | + /* During suspend, mark connection as closed immediately | |
| 2722 | + * since we might not receive HCI_EV_DISCONN_COMPLETE | |
| 2723 | + */ | |
| 2724 | + if (hdev->suspended) | |
| 2725 | + conn->state = BT_CLOSED; | |
| 2726 | + | |
| 2721 | 2727 | mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); |
| 2722 | 2728 | |
| 2723 | 2729 | if (conn->type == ACL_LINK) { |
| @@ -4398,7 +4404,17 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, · 1674 unmodified lines | ||
| 4398 | 4404 | if (!conn) |
| 4399 | 4405 | continue; |
| 4400 | 4406 | |
| 4401 | − conn->sent -= count; | |
| 4407 | + /* Check if there is really enough packets outstanding before | |
| 4408 | + * attempting to decrease the sent counter otherwise it could | |
| 4409 | + * underflow.. | |
| 4410 | + */ | |
| 4411 | + if (conn->sent >= count) { | |
| 4412 | + conn->sent -= count; | |
| 4413 | + } else { | |
| 4414 | + bt_dev_warn(hdev, "hcon %p sent %u < count %u", | |
| 4415 | + conn, conn->sent, count); | |
| 4416 | + conn->sent = 0; | |
| 4417 | + } | |
| 4402 | 4418 | |
| 4403 | 4419 | for (i = 0; i < count; ++i) |
| 4404 | 4420 | hci_conn_tx_dequeue(conn); |
| @@ -7008,6 +7024,7 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data, · 2603 unmodified lines | ||
| 7008 | 7024 | { |
| 7009 | 7025 | struct hci_evt_le_big_sync_lost *ev = data; |
| 7010 | 7026 | struct hci_conn *bis, *conn; |
| 7027 | + bool mgmt_conn; | |
| 7011 | 7028 | |
| 7012 | 7029 | bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle); |
| 7013 | 7030 | |
| @@ -7026,6 +7043,10 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data, · 12 unmodified lines | ||
| 7026 | 7043 | while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle, |
| 7027 | 7044 | BT_CONNECTED, |
| 7028 | 7045 | HCI_ROLE_SLAVE))) { |
| 7046 | + mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags); | |
| 7047 | + mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type, | |
| 7048 | + ev->reason, mgmt_conn); | |
| 7049 | + | |
| 7029 | 7050 | clear_bit(HCI_CONN_BIG_SYNC, &bis->flags); |
| 7030 | 7051 | hci_disconn_cfm(bis, ev->reason); |
| 7031 | 7052 | hci_conn_del(bis); |
| @@ -3481,13 +3481,13 @@ int hci_update_scan_sync(struct hci_dev *hdev) · 3480 unmodified lines | ||
| 3481 | 3481 | return hci_write_scan_enable_sync(hdev, scan); |
| 3482 | 3482 | } |
| 3483 | 3483 | |
| 3484 | −int hci_update_name_sync(struct hci_dev *hdev) | |
| 3484 | +int hci_update_name_sync(struct hci_dev *hdev, const u8 *name) | |
| 3485 | 3485 | { |
| 3486 | 3486 | struct hci_cp_write_local_name cp; |
| 3487 | 3487 | |
| 3488 | 3488 | memset(&cp, 0, sizeof(cp)); |
| 3489 | 3489 | |
| 3490 | − memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); | |
| 3490 | + memcpy(cp.name, name, sizeof(cp.name)); | |
| 3491 | 3491 | |
| 3492 | 3492 | return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME, |
| 3493 | 3493 | sizeof(cp), &cp, |
| @@ -3540,7 +3540,7 @@ int hci_powered_update_sync(struct hci_dev *hdev) · 46 unmodified lines | ||
| 3540 | 3540 | hci_write_fast_connectable_sync(hdev, false); |
| 3541 | 3541 | hci_update_scan_sync(hdev); |
| 3542 | 3542 | hci_update_class_sync(hdev); |
| 3543 | − hci_update_name_sync(hdev); | |
| 3543 | + hci_update_name_sync(hdev, hdev->dev_name); | |
| 3544 | 3544 | hci_update_eir_sync(hdev); |
| 3545 | 3545 | } |
| 3546 | 3546 | |
| @@ -3892,8 +3892,11 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err) · 3891 unmodified lines | ||
| 3892 | 3892 | |
| 3893 | 3893 | static int set_name_sync(struct hci_dev *hdev, void *data) |
| 3894 | 3894 | { |
| 3895 | + struct mgmt_pending_cmd *cmd = data; | |
| 3896 | + struct mgmt_cp_set_local_name *cp = cmd->param; | |
| 3897 | + | |
| 3895 | 3898 | if (lmp_bredr_capable(hdev)) { |
| 3896 | − hci_update_name_sync(hdev); | |
| 3899 | + hci_update_name_sync(hdev, cp->name); | |
| 3897 | 3900 | hci_update_eir_sync(hdev); |
| 3898 | 3901 | } |
| 3899 | 3902 | |
| @@ -9705,7 +9708,9 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, · 5805 unmodified lines | ||
| 9705 | 9708 | if (!mgmt_connected) |
| 9706 | 9709 | return; |
| 9707 | 9710 | |
| 9708 | − if (link_type != ACL_LINK && link_type != LE_LINK) | |
| 9711 | + if (link_type != ACL_LINK && | |
| 9712 | + link_type != LE_LINK && | |
| 9713 | + link_type != BIS_LINK) | |
| 9709 | 9714 | return; |
| 9710 | 9715 | |
| 9711 | 9716 | bacpy(&ev.addr.bdaddr, bdaddr); |
| @@ -618,6 +618,20 @@ fault: · 617 unmodified lines | ||
| 618 | 618 | } |
| 619 | 619 | EXPORT_SYMBOL(skb_copy_datagram_from_iter); |
| 620 | 620 | |
| 621 | +int skb_copy_datagram_from_iter_full(struct sk_buff *skb, int offset, | |
| 622 | + struct iov_iter *from, int len) | |
| 623 | +{ | |
| 624 | + struct iov_iter_state state; | |
| 625 | + int ret; | |
| 626 | + | |
| 627 | + iov_iter_save_state(from, &state); | |
| 628 | + ret = skb_copy_datagram_from_iter(skb, offset, from, len); | |
| 629 | + if (ret) | |
| 630 | + iov_iter_restore(from, &state); | |
| 631 | + return ret; | |
| 632 | +} | |
| 633 | +EXPORT_SYMBOL(skb_copy_datagram_from_iter_full); | |
| 634 | + | |
| 621 | 635 | int zerocopy_fill_skb_from_iter(struct sk_buff *skb, |
| 622 | 636 | struct iov_iter *from, size_t length) |
| 623 | 637 | { |
| @@ -287,8 +287,10 @@ static int page_pool_init(struct page_pool *pool, · 286 unmodified lines | ||
| 287 | 287 | } |
| 288 | 288 | |
| 289 | 289 | if (pool->mp_ops) { |
| 290 | − if (!pool->dma_map || !pool->dma_sync) | |
| 291 | − return -EOPNOTSUPP; | |
| 290 | + if (!pool->dma_map || !pool->dma_sync) { | |
| 291 | + err = -EOPNOTSUPP; | |
| 292 | + goto free_ptr_ring; | |
| 293 | + } | |
| 292 | 294 | |
| 293 | 295 | if (WARN_ON(!is_kernel_rodata((unsigned long)pool->mp_ops))) { |
| 294 | 296 | err = -EFAULT; |
| @@ -2576,12 +2576,16 @@ static struct rtable *__mkroute_output(const struct fib_result *res, · 2575 unmodified lines | ||
| 2576 | 2576 | !netif_is_l3_master(dev_out)) |
| 2577 | 2577 | return ERR_PTR(-EINVAL); |
| 2578 | 2578 | |
| 2579 | − if (ipv4_is_lbcast(fl4->daddr)) | |
| 2579 | + if (ipv4_is_lbcast(fl4->daddr)) { | |
| 2580 | 2580 | type = RTN_BROADCAST; |
| 2581 | − else if (ipv4_is_multicast(fl4->daddr)) | |
| 2581 | + | |
| 2582 | + /* reset fi to prevent gateway resolution */ | |
| 2583 | + fi = NULL; | |
| 2584 | + } else if (ipv4_is_multicast(fl4->daddr)) { | |
| 2582 | 2585 | type = RTN_MULTICAST; |
| 2583 | − else if (ipv4_is_zeronet(fl4->daddr)) | |
| 2586 | + } else if (ipv4_is_zeronet(fl4->daddr)) { | |
| 2584 | 2587 | return ERR_PTR(-EINVAL); |
| 2588 | + } | |
| 2585 | 2589 | |
| 2586 | 2590 | if (dev_out->flags & IFF_LOOPBACK) |
| 2587 | 2591 | flags |= RTCF_LOCAL; |
| @@ -129,22 +129,12 @@ static const struct ppp_channel_ops pppol2tp_chan_ops = { · 128 unmodified lines | ||
| 129 | 129 | |
| 130 | 130 | static const struct proto_ops pppol2tp_ops; |
| 131 | 131 | |
| 132 | −/* Retrieves the pppol2tp socket associated to a session. | |
| 133 | − * A reference is held on the returned socket, so this function must be paired | |
| 134 | − * with sock_put(). | |
| 135 | − */ | |
| 132 | +/* Retrieves the pppol2tp socket associated to a session. */ | |
| 136 | 133 | static struct sock *pppol2tp_session_get_sock(struct l2tp_session *session) |
| 137 | 134 | { |
| 138 | 135 | struct pppol2tp_session *ps = l2tp_session_priv(session); |
| 139 | − struct sock *sk; | |
| 140 | − | |
| 141 | − rcu_read_lock(); | |
| 142 | − sk = rcu_dereference(ps->sk); | |
| 143 | − if (sk) | |
| 144 | − sock_hold(sk); | |
| 145 | − rcu_read_unlock(); | |
| 146 | 136 | |
| 147 | − return sk; | |
| 137 | + return rcu_dereference(ps->sk); | |
| 148 | 138 | } |
| 149 | 139 | |
| 150 | 140 | /* Helpers to obtain tunnel/session contexts from sockets. |
| @@ -206,14 +196,13 @@ end: · 55 unmodified lines | ||
| 206 | 196 | |
| 207 | 197 | static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len) |
| 208 | 198 | { |
| 209 | − struct pppol2tp_session *ps = l2tp_session_priv(session); | |
| 210 | − struct sock *sk = NULL; | |
| 199 | + struct sock *sk; | |
| 211 | 200 | |
| 212 | 201 | /* If the socket is bound, send it in to PPP's input queue. Otherwise |
| 213 | 202 | * queue it on the session socket. |
| 214 | 203 | */ |
| 215 | 204 | rcu_read_lock(); |
| 216 | − sk = rcu_dereference(ps->sk); | |
| 205 | + sk = pppol2tp_session_get_sock(session); | |
| 217 | 206 | if (!sk) |
| 218 | 207 | goto no_sock; |
| 219 | 208 | |
| @@ -510,13 +499,14 @@ static void pppol2tp_show(struct seq_file *m, void *arg) · 290 unmodified lines | ||
| 510 | 499 | struct l2tp_session *session = arg; |
| 511 | 500 | struct sock *sk; |
| 512 | 501 | |
| 502 | + rcu_read_lock(); | |
| 513 | 503 | sk = pppol2tp_session_get_sock(session); |
| 514 | 504 | if (sk) { |
| 515 | 505 | struct pppox_sock *po = pppox_sk(sk); |
| 516 | 506 | |
| 517 | 507 | seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); |
| 518 | − sock_put(sk); | |
| 519 | 508 | } |
| 509 | + rcu_read_unlock(); | |
| 520 | 510 | } |
| 521 | 511 | |
| 522 | 512 | static void pppol2tp_session_init(struct l2tp_session *session) |
| @@ -1530,6 +1520,7 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v) · 1007 unmodified lines | ||
| 1530 | 1520 | port = ntohs(inet->inet_sport); |
| 1531 | 1521 | } |
| 1532 | 1522 | |
| 1523 | + rcu_read_lock(); | |
| 1533 | 1524 | sk = pppol2tp_session_get_sock(session); |
| 1534 | 1525 | if (sk) { |
| 1535 | 1526 | state = sk->sk_state; |
| @@ -1565,8 +1556,8 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v) · 29 unmodified lines | ||
| 1565 | 1556 | struct pppox_sock *po = pppox_sk(sk); |
| 1566 | 1557 | |
| 1567 | 1558 | seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); |
| 1568 | − sock_put(sk); | |
| 1569 | 1559 | } |
| 1560 | + rcu_read_unlock(); | |
| 1570 | 1561 | } |
| 1571 | 1562 | |
| 1572 | 1563 | static int pppol2tp_seq_show(struct seq_file *m, void *v) |
| @@ -170,7 +170,7 @@ void rose_kill_by_neigh(struct rose_neigh *neigh) · 169 unmodified lines | ||
| 170 | 170 | |
| 171 | 171 | if (rose->neighbour == neigh) { |
| 172 | 172 | rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); |
| 173 | − rose->neighbour->use--; | |
| 173 | + rose_neigh_put(rose->neighbour); | |
| 174 | 174 | rose->neighbour = NULL; |
| 175 | 175 | } |
| 176 | 176 | } |
| @@ -212,7 +212,7 @@ start: · 35 unmodified lines | ||
| 212 | 212 | if (rose->device == dev) { |
| 213 | 213 | rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); |
| 214 | 214 | if (rose->neighbour) |
| 215 | − rose->neighbour->use--; | |
| 215 | + rose_neigh_put(rose->neighbour); | |
| 216 | 216 | netdev_put(rose->device, &rose->dev_tracker); |
| 217 | 217 | rose->device = NULL; |
| 218 | 218 | } |
| @@ -655,7 +655,7 @@ static int rose_release(struct socket *sock) · 436 unmodified lines | ||
| 655 | 655 | break; |
| 656 | 656 | |
| 657 | 657 | case ROSE_STATE_2: |
| 658 | − rose->neighbour->use--; | |
| 658 | + rose_neigh_put(rose->neighbour); | |
| 659 | 659 | release_sock(sk); |
| 660 | 660 | rose_disconnect(sk, 0, -1, -1); |
| 661 | 661 | lock_sock(sk); |
| @@ -823,6 +823,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le · 161 unmodified lines | ||
| 823 | 823 | rose->lci = rose_new_lci(rose->neighbour); |
| 824 | 824 | if (!rose->lci) { |
| 825 | 825 | err = -ENETUNREACH; |
| 826 | + rose_neigh_put(rose->neighbour); | |
| 826 | 827 | goto out_release; |
| 827 | 828 | } |
| 828 | 829 | |
| @@ -834,12 +835,14 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le · 5 unmodified lines | ||
| 834 | 835 | dev = rose_dev_first(); |
| 835 | 836 | if (!dev) { |
| 836 | 837 | err = -ENETUNREACH; |
| 838 | + rose_neigh_put(rose->neighbour); | |
| 837 | 839 | goto out_release; |
| 838 | 840 | } |
| 839 | 841 | |
| 840 | 842 | user = ax25_findbyuid(current_euid()); |
| 841 | 843 | if (!user) { |
| 842 | 844 | err = -EINVAL; |
| 845 | + rose_neigh_put(rose->neighbour); | |
| 843 | 846 | dev_put(dev); |
| 844 | 847 | goto out_release; |
| 845 | 848 | } |
| @@ -874,8 +877,6 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le · 28 unmodified lines | ||
| 874 | 877 | |
| 875 | 878 | rose->state = ROSE_STATE_1; |
| 876 | 879 | |
| 877 | − rose->neighbour->use++; | |
| 878 | − | |
| 879 | 880 | rose_write_internal(sk, ROSE_CALL_REQUEST); |
| 880 | 881 | rose_start_heartbeat(sk); |
| 881 | 882 | rose_start_t1timer(sk); |
| @@ -1077,7 +1078,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros · 195 unmodified lines | ||
| 1077 | 1078 | GFP_ATOMIC); |
| 1078 | 1079 | make_rose->facilities = facilities; |
| 1079 | 1080 | |
| 1080 | − make_rose->neighbour->use++; | |
| 1081 | + rose_neigh_hold(make_rose->neighbour); | |
| 1081 | 1082 | |
| 1082 | 1083 | if (rose_sk(sk)->defer) { |
| 1083 | 1084 | make_rose->state = ROSE_STATE_5; |
| @@ -56,7 +56,7 @@ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int framety · 55 unmodified lines | ||
| 56 | 56 | case ROSE_CLEAR_REQUEST: |
| 57 | 57 | rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); |
| 58 | 58 | rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); |
| 59 | − rose->neighbour->use--; | |
| 59 | + rose_neigh_put(rose->neighbour); | |
| 60 | 60 | break; |
| 61 | 61 | |
| 62 | 62 | default: |
| @@ -79,12 +79,12 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety · 16 unmodified lines | ||
| 79 | 79 | case ROSE_CLEAR_REQUEST: |
| 80 | 80 | rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); |
| 81 | 81 | rose_disconnect(sk, 0, skb->data[3], skb->data[4]); |
| 82 | − rose->neighbour->use--; | |
| 82 | + rose_neigh_put(rose->neighbour); | |
| 83 | 83 | break; |
| 84 | 84 | |
| 85 | 85 | case ROSE_CLEAR_CONFIRMATION: |
| 86 | 86 | rose_disconnect(sk, 0, -1, -1); |
| 87 | − rose->neighbour->use--; | |
| 87 | + rose_neigh_put(rose->neighbour); | |
| 88 | 88 | break; |
| 89 | 89 | |
| 90 | 90 | default: |
| @@ -121,7 +121,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety · 30 unmodified lines | ||
| 121 | 121 | case ROSE_CLEAR_REQUEST: |
| 122 | 122 | rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); |
| 123 | 123 | rose_disconnect(sk, 0, skb->data[3], skb->data[4]); |
| 124 | − rose->neighbour->use--; | |
| 124 | + rose_neigh_put(rose->neighbour); | |
| 125 | 125 | break; |
| 126 | 126 | |
| 127 | 127 | case ROSE_RR: |
| @@ -234,7 +234,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety · 106 unmodified lines | ||
| 234 | 234 | case ROSE_CLEAR_REQUEST: |
| 235 | 235 | rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); |
| 236 | 236 | rose_disconnect(sk, 0, skb->data[3], skb->data[4]); |
| 237 | − rose->neighbour->use--; | |
| 237 | + rose_neigh_put(rose->neighbour); | |
| 238 | 238 | break; |
| 239 | 239 | |
| 240 | 240 | default: |
| @@ -254,7 +254,7 @@ static int rose_state5_machine(struct sock *sk, struct sk_buff *skb, int framety · 13 unmodified lines | ||
| 254 | 254 | if (frametype == ROSE_CLEAR_REQUEST) { |
| 255 | 255 | rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); |
| 256 | 256 | rose_disconnect(sk, 0, skb->data[3], skb->data[4]); |
| 257 | − rose_sk(sk)->neighbour->use--; | |
| 257 | + rose_neigh_put(rose_sk(sk)->neighbour); | |
| 258 | 258 | } |
| 259 | 259 | |
| 260 | 260 | return 0; |
| @@ -93,11 +93,11 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, · 92 unmodified lines | ||
| 93 | 93 | rose_neigh->ax25 = NULL; |
| 94 | 94 | rose_neigh->dev = dev; |
| 95 | 95 | rose_neigh->count = 0; |
| 96 | − rose_neigh->use = 0; | |
| 97 | 96 | rose_neigh->dce_mode = 0; |
| 98 | 97 | rose_neigh->loopback = 0; |
| 99 | 98 | rose_neigh->number = rose_neigh_no++; |
| 100 | 99 | rose_neigh->restarted = 0; |
| 100 | + refcount_set(&rose_neigh->use, 1); | |
| 101 | 101 | |
| 102 | 102 | skb_queue_head_init(&rose_neigh->queue); |
| 103 | 103 | |
| @@ -178,6 +178,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, · 74 unmodified lines | ||
| 178 | 178 | } |
| 179 | 179 | } |
| 180 | 180 | rose_neigh->count++; |
| 181 | + rose_neigh_hold(rose_neigh); | |
| 181 | 182 | |
| 182 | 183 | goto out; |
| 183 | 184 | } |
| @@ -187,6 +188,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route, · 3 unmodified lines | ||
| 187 | 188 | rose_node->neighbour[rose_node->count] = rose_neigh; |
| 188 | 189 | rose_node->count++; |
| 189 | 190 | rose_neigh->count++; |
| 191 | + rose_neigh_hold(rose_neigh); | |
| 190 | 192 | } |
| 191 | 193 | |
| 192 | 194 | out: |
| @@ -234,20 +236,12 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) · 41 unmodified lines | ||
| 234 | 236 | |
| 235 | 237 | if ((s = rose_neigh_list) == rose_neigh) { |
| 236 | 238 | rose_neigh_list = rose_neigh->next; |
| 237 | − if (rose_neigh->ax25) | |
| 238 | − ax25_cb_put(rose_neigh->ax25); | |
| 239 | − kfree(rose_neigh->digipeat); | |
| 240 | − kfree(rose_neigh); | |
| 241 | 239 | return; |
| 242 | 240 | } |
| 243 | 241 | |
| 244 | 242 | while (s != NULL && s->next != NULL) { |
| 245 | 243 | if (s->next == rose_neigh) { |
| 246 | 244 | s->next = rose_neigh->next; |
| 247 | − if (rose_neigh->ax25) | |
| 248 | − ax25_cb_put(rose_neigh->ax25); | |
| 249 | − kfree(rose_neigh->digipeat); | |
| 250 | − kfree(rose_neigh); | |
| 251 | 245 | return; |
| 252 | 246 | } |
| 253 | 247 | |
| @@ -263,10 +257,10 @@ static void rose_remove_route(struct rose_route *rose_route) · 9 unmodified lines | ||
| 263 | 257 | struct rose_route *s; |
| 264 | 258 | |
| 265 | 259 | if (rose_route->neigh1 != NULL) |
| 266 | − rose_route->neigh1->use--; | |
| 260 | + rose_neigh_put(rose_route->neigh1); | |
| 267 | 261 | |
| 268 | 262 | if (rose_route->neigh2 != NULL) |
| 269 | − rose_route->neigh2->use--; | |
| 263 | + rose_neigh_put(rose_route->neigh2); | |
| 270 | 264 | |
| 271 | 265 | if ((s = rose_route_list) == rose_route) { |
| 272 | 266 | rose_route_list = rose_route->next; |
| @@ -330,9 +324,12 @@ static int rose_del_node(struct rose_route_struct *rose_route, · 57 unmodified lines | ||
| 330 | 324 | for (i = 0; i < rose_node->count; i++) { |
| 331 | 325 | if (rose_node->neighbour[i] == rose_neigh) { |
| 332 | 326 | rose_neigh->count--; |
| 327 | + rose_neigh_put(rose_neigh); | |
| 333 | 328 | |
| 334 | − if (rose_neigh->count == 0 && rose_neigh->use == 0) | |
| 329 | + if (rose_neigh->count == 0) { | |
| 335 | 330 | rose_remove_neigh(rose_neigh); |
| 331 | + rose_neigh_put(rose_neigh); | |
| 332 | + } | |
| 336 | 333 | |
| 337 | 334 | rose_node->count--; |
| 338 | 335 | |
| @@ -381,11 +378,11 @@ void rose_add_loopback_neigh(void) · 42 unmodified lines | ||
| 381 | 378 | sn->ax25 = NULL; |
| 382 | 379 | sn->dev = NULL; |
| 383 | 380 | sn->count = 0; |
| 384 | − sn->use = 0; | |
| 385 | 381 | sn->dce_mode = 1; |
| 386 | 382 | sn->loopback = 1; |
| 387 | 383 | sn->number = rose_neigh_no++; |
| 388 | 384 | sn->restarted = 1; |
| 385 | + refcount_set(&sn->use, 1); | |
| 389 | 386 | |
| 390 | 387 | skb_queue_head_init(&sn->queue); |
| 391 | 388 | |
| @@ -436,6 +433,7 @@ int rose_add_loopback_node(const rose_address *address) · 44 unmodified lines | ||
| 436 | 433 | rose_node_list = rose_node; |
| 437 | 434 | |
| 438 | 435 | rose_loopback_neigh->count++; |
| 436 | + rose_neigh_hold(rose_loopback_neigh); | |
| 439 | 437 | |
| 440 | 438 | out: |
| 441 | 439 | spin_unlock_bh(&rose_node_list_lock); |
| @@ -467,6 +465,7 @@ void rose_del_loopback_node(const rose_address *address) · 25 unmodified lines | ||
| 467 | 465 | rose_remove_node(rose_node); |
| 468 | 466 | |
| 469 | 467 | rose_loopback_neigh->count--; |
| 468 | + rose_neigh_put(rose_loopback_neigh); | |
| 470 | 469 | |
| 471 | 470 | out: |
| 472 | 471 | spin_unlock_bh(&rose_node_list_lock); |
| @@ -506,6 +505,7 @@ void rose_rt_device_down(struct net_device *dev) · 33 unmodified lines | ||
| 506 | 505 | memmove(&t->neighbour[i], &t->neighbour[i + 1], |
| 507 | 506 | sizeof(t->neighbour[0]) * |
| 508 | 507 | (t->count - i)); |
| 508 | + rose_neigh_put(s); | |
| 509 | 509 | } |
| 510 | 510 | |
| 511 | 511 | if (t->count <= 0) |
| @@ -513,6 +513,7 @@ void rose_rt_device_down(struct net_device *dev) · 1 unmodified line | ||
| 513 | 513 | } |
| 514 | 514 | |
| 515 | 515 | rose_remove_neigh(s); |
| 516 | + rose_neigh_put(s); | |
| 516 | 517 | } |
| 517 | 518 | spin_unlock_bh(&rose_neigh_list_lock); |
| 518 | 519 | spin_unlock_bh(&rose_node_list_lock); |
| @@ -548,6 +549,7 @@ static int rose_clear_routes(void) · 29 unmodified lines | ||
| 548 | 549 | { |
| 549 | 550 | struct rose_neigh *s, *rose_neigh; |
| 550 | 551 | struct rose_node *t, *rose_node; |
| 552 | + int i; | |
| 551 | 553 | |
| 552 | 554 | spin_lock_bh(&rose_node_list_lock); |
| 553 | 555 | spin_lock_bh(&rose_neigh_list_lock); |
| @@ -558,17 +560,21 @@ static int rose_clear_routes(void) · 4 unmodified lines | ||
| 558 | 560 | while (rose_node != NULL) { |
| 559 | 561 | t = rose_node; |
| 560 | 562 | rose_node = rose_node->next; |
| 561 | − if (!t->loopback) | |
| 563 | + | |
| 564 | + if (!t->loopback) { | |
| 565 | + for (i = 0; i < t->count; i++) | |
| 566 | + rose_neigh_put(t->neighbour[i]); | |
| 562 | 567 | rose_remove_node(t); |
| 568 | + } | |
| 563 | 569 | } |
| 564 | 570 | |
| 565 | 571 | while (rose_neigh != NULL) { |
| 566 | 572 | s = rose_neigh; |
| 567 | 573 | rose_neigh = rose_neigh->next; |
| 568 | 574 | |
| 569 | − if (s->use == 0 && !s->loopback) { | |
| 570 | − s->count = 0; | |
| 575 | + if (!s->loopback) { | |
| 571 | 576 | rose_remove_neigh(s); |
| 577 | + rose_neigh_put(s); | |
| 572 | 578 | } |
| 573 | 579 | } |
| 574 | 580 | |
| @@ -684,6 +690,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, · 109 unmodified lines | ||
| 684 | 690 | for (i = 0; i < node->count; i++) { |
| 685 | 691 | if (node->neighbour[i]->restarted) { |
| 686 | 692 | res = node->neighbour[i]; |
| 693 | + rose_neigh_hold(node->neighbour[i]); | |
| 687 | 694 | goto out; |
| 688 | 695 | } |
| 689 | 696 | } |
| @@ -695,6 +702,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause, · 5 unmodified lines | ||
| 695 | 702 | for (i = 0; i < node->count; i++) { |
| 696 | 703 | if (!rose_ftimer_running(node->neighbour[i])) { |
| 697 | 704 | res = node->neighbour[i]; |
| 705 | + rose_neigh_hold(node->neighbour[i]); | |
| 698 | 706 | goto out; |
| 699 | 707 | } |
| 700 | 708 | failed = 1; |
| @@ -784,13 +792,13 @@ static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh) · 83 unmodified lines | ||
| 784 | 792 | } |
| 785 | 793 | |
| 786 | 794 | if (rose_route->neigh1 == rose_neigh) { |
| 787 | − rose_route->neigh1->use--; | |
| 795 | + rose_neigh_put(rose_route->neigh1); | |
| 788 | 796 | rose_route->neigh1 = NULL; |
| 789 | 797 | rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0); |
| 790 | 798 | } |
| 791 | 799 | |
| 792 | 800 | if (rose_route->neigh2 == rose_neigh) { |
| 793 | − rose_route->neigh2->use--; | |
| 801 | + rose_neigh_put(rose_route->neigh2); | |
| 794 | 802 | rose_route->neigh2 = NULL; |
| 795 | 803 | rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0); |
| 796 | 804 | } |
| @@ -919,7 +927,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) · 122 unmodified lines | ||
| 919 | 927 | rose_clear_queues(sk); |
| 920 | 928 | rose->cause = ROSE_NETWORK_CONGESTION; |
| 921 | 929 | rose->diagnostic = 0; |
| 922 | − rose->neighbour->use--; | |
| 930 | + rose_neigh_put(rose->neighbour); | |
| 923 | 931 | rose->neighbour = NULL; |
| 924 | 932 | rose->lci = 0; |
| 925 | 933 | rose->state = ROSE_STATE_0; |
| @@ -1044,12 +1052,12 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) · 118 unmodified lines | ||
| 1044 | 1052 | |
| 1045 | 1053 | if ((new_lci = rose_new_lci(new_neigh)) == 0) { |
| 1046 | 1054 | rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71); |
| 1047 | − goto out; | |
| 1055 | + goto put_neigh; | |
| 1048 | 1056 | } |
| 1049 | 1057 | |
| 1050 | 1058 | if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) { |
| 1051 | 1059 | rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120); |
| 1052 | − goto out; | |
| 1060 | + goto put_neigh; | |
| 1053 | 1061 | } |
| 1054 | 1062 | |
| 1055 | 1063 | rose_route->lci1 = lci; |
| @@ -1062,8 +1070,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) · 6 unmodified lines | ||
| 1062 | 1070 | rose_route->lci2 = new_lci; |
| 1063 | 1071 | rose_route->neigh2 = new_neigh; |
| 1064 | 1072 | |
| 1065 | − rose_route->neigh1->use++; | |
| 1066 | − rose_route->neigh2->use++; | |
| 1073 | + rose_neigh_hold(rose_route->neigh1); | |
| 1074 | + rose_neigh_hold(rose_route->neigh2); | |
| 1067 | 1075 | |
| 1068 | 1076 | rose_route->next = rose_route_list; |
| 1069 | 1077 | rose_route_list = rose_route; |
| @@ -1075,6 +1083,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) · 5 unmodified lines | ||
| 1075 | 1083 | rose_transmit_link(skb, rose_route->neigh2); |
| 1076 | 1084 | res = 1; |
| 1077 | 1085 | |
| 1086 | +put_neigh: | |
| 1087 | + rose_neigh_put(new_neigh); | |
| 1078 | 1088 | out: |
| 1079 | 1089 | spin_unlock_bh(&rose_route_list_lock); |
| 1080 | 1090 | spin_unlock_bh(&rose_neigh_list_lock); |
| @@ -1190,7 +1200,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v) · 109 unmodified lines | ||
| 1190 | 1200 | (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), |
| 1191 | 1201 | rose_neigh->dev ? rose_neigh->dev->name : "???", |
| 1192 | 1202 | rose_neigh->count, |
| 1193 | − rose_neigh->use, | |
| 1203 | + refcount_read(&rose_neigh->use) - rose_neigh->count - 1, | |
| 1194 | 1204 | (rose_neigh->dce_mode) ? "DCE" : "DTE", |
| 1195 | 1205 | (rose_neigh->restarted) ? "yes" : "no", |
| 1196 | 1206 | ax25_display_timer(&rose_neigh->t0timer) / HZ, |
| @@ -1295,18 +1305,22 @@ void __exit rose_rt_free(void) · 98 unmodified lines | ||
| 1295 | 1305 | struct rose_neigh *s, *rose_neigh = rose_neigh_list; |
| 1296 | 1306 | struct rose_node *t, *rose_node = rose_node_list; |
| 1297 | 1307 | struct rose_route *u, *rose_route = rose_route_list; |
| 1308 | + int i; | |
| 1298 | 1309 | |
| 1299 | 1310 | while (rose_neigh != NULL) { |
| 1300 | 1311 | s = rose_neigh; |
| 1301 | 1312 | rose_neigh = rose_neigh->next; |
| 1302 | 1313 | |
| 1303 | 1314 | rose_remove_neigh(s); |
| 1315 | + rose_neigh_put(s); | |
| 1304 | 1316 | } |
| 1305 | 1317 | |
| 1306 | 1318 | while (rose_node != NULL) { |
| 1307 | 1319 | t = rose_node; |
| 1308 | 1320 | rose_node = rose_node->next; |
| 1309 | 1321 | |
| 1322 | + for (i = 0; i < t->count; i++) | |
| 1323 | + rose_neigh_put(t->neighbour[i]); | |
| 1310 | 1324 | rose_remove_node(t); |
| 1311 | 1325 | } |
| 1312 | 1326 | |
| @@ -180,7 +180,7 @@ static void rose_timer_expiry(struct timer_list *t) · 179 unmodified lines | ||
| 180 | 180 | break; |
| 181 | 181 | |
| 182 | 182 | case ROSE_STATE_2: /* T3 */ |
| 183 | − rose->neighbour->use--; | |
| 183 | + rose_neigh_put(rose->neighbour); | |
| 184 | 184 | rose_disconnect(sk, ETIMEDOUT, -1, -1); |
| 185 | 185 | break; |
| 186 | 186 | |
| @@ -547,7 +547,9 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) · 546 unmodified lines | ||
| 547 | 547 | { |
| 548 | 548 | addr->v6.sin6_family = AF_INET6; |
| 549 | 549 | addr->v6.sin6_port = 0; |
| 550 | + addr->v6.sin6_flowinfo = 0; | |
| 550 | 551 | addr->v6.sin6_addr = sk->sk_v6_rcv_saddr; |
| 552 | + addr->v6.sin6_scope_id = 0; | |
| 551 | 553 | } |
| 552 | 554 | |
| 553 | 555 | /* Initialize sk->sk_rcv_saddr from sctp_addr. */ |
| @@ -105,12 +105,14 @@ static int virtio_transport_fill_skb(struct sk_buff *skb, · 104 unmodified lines | ||
| 105 | 105 | size_t len, |
| 106 | 106 | bool zcopy) |
| 107 | 107 | { |
| 108 | + struct msghdr *msg = info->msg; | |
| 109 | + | |
| 108 | 110 | if (zcopy) |
| 109 | − return __zerocopy_sg_from_iter(info->msg, NULL, skb, | |
| 110 | − &info->msg->msg_iter, len, NULL); | |
| 111 | + return __zerocopy_sg_from_iter(msg, NULL, skb, | |
| 112 | + &msg->msg_iter, len, NULL); | |
| 111 | 113 | |
| 112 | 114 | virtio_vsock_skb_put(skb, len); |
| 113 | − return skb_copy_datagram_from_iter(skb, 0, &info->msg->msg_iter, len); | |
| 115 | + return skb_copy_datagram_from_iter_full(skb, 0, &msg->msg_iter, len); | |
| 114 | 116 | } |
| 115 | 117 | |
| 116 | 118 | static void virtio_transport_init_hdr(struct sk_buff *skb, |
| @@ -43,17 +43,6 @@ pub struct Vmalloc; · 42 unmodified lines | ||
| 43 | 43 | /// For more details see [self]. |
| 44 | 44 | pub struct KVmalloc; |
| 45 | 45 | |
| 46 | −/// Returns a proper size to alloc a new object aligned to `new_layout`'s alignment. | |
| 47 | −fn aligned_size(new_layout: Layout) -> usize { | |
| 48 | − // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first. | |
| 49 | − let layout = new_layout.pad_to_align(); | |
| 50 | − | |
| 51 | − // Note that `layout.size()` (after padding) is guaranteed to be a multiple of `layout.align()` | |
| 52 | − // which together with the slab guarantees means the `krealloc` will return a properly aligned | |
| 53 | − // object (see comments in `kmalloc()` for more information). | |
| 54 | − layout.size() | |
| 55 | −} | |
| 56 | − | |
| 57 | 46 | /// # Invariants |
| 58 | 47 | /// |
| 59 | 48 | /// One of the following: `krealloc`, `vrealloc`, `kvrealloc`. |
| @@ -88,7 +77,7 @@ impl ReallocFunc { · 28 unmodified lines | ||
| 88 | 77 | old_layout: Layout, |
| 89 | 78 | flags: Flags, |
| 90 | 79 | ) -> Result<NonNull<[u8]>, AllocError> { |
| 91 | − let size = aligned_size(layout); | |
| 80 | + let size = layout.size(); | |
| 92 | 81 | let ptr = match ptr { |
| 93 | 82 | Some(ptr) => { |
| 94 | 83 | if old_layout.size() == 0 { |
| @@ -123,6 +112,17 @@ impl ReallocFunc { · 28 unmodified lines | ||
| 123 | 112 | } |
| 124 | 113 | } |
| 125 | 114 | |
| 115 | +impl Kmalloc { | |
| 116 | + /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of | |
| 117 | + /// `layout`. | |
| 118 | + pub fn aligned_layout(layout: Layout) -> Layout { | |
| 119 | + // Note that `layout.size()` (after padding) is guaranteed to be a multiple of | |
| 120 | + // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return | |
| 121 | + // a properly aligned object (see comments in `kmalloc()` for more information). | |
| 122 | + layout.pad_to_align() | |
| 123 | + } | |
| 124 | +} | |
| 125 | + | |
| 126 | 126 | // SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees that |
| 127 | 127 | // - memory remains valid until it is explicitly freed, |
| 128 | 128 | // - passing a pointer to a valid memory allocation is OK, |
| @@ -135,6 +135,8 @@ unsafe impl Allocator for Kmalloc { · 6 unmodified lines | ||
| 135 | 135 | old_layout: Layout, |
| 136 | 136 | flags: Flags, |
| 137 | 137 | ) -> Result<NonNull<[u8]>, AllocError> { |
| 138 | + let layout = Kmalloc::aligned_layout(layout); | |
| 139 | + | |
| 138 | 140 | // SAFETY: `ReallocFunc::call` has the same safety requirements as `Allocator::realloc`. |
| 139 | 141 | unsafe { ReallocFunc::KREALLOC.call(ptr, layout, old_layout, flags) } |
| 140 | 142 | } |
| @@ -176,6 +178,10 @@ unsafe impl Allocator for KVmalloc { · 35 unmodified lines | ||
| 176 | 178 | old_layout: Layout, |
| 177 | 179 | flags: Flags, |
| 178 | 180 | ) -> Result<NonNull<[u8]>, AllocError> { |
| 181 | + // `KVmalloc` may use the `Kmalloc` backend, hence we have to enforce a `Kmalloc` | |
| 182 | + // compatible layout. | |
| 183 | + let layout = Kmalloc::aligned_layout(layout); | |
| 184 | + | |
| 179 | 185 | // TODO: Support alignments larger than PAGE_SIZE. |
| 180 | 186 | if layout.align() > bindings::PAGE_SIZE { |
| 181 | 187 | pr_warn!("KVmalloc does not support alignments larger than PAGE_SIZE yet.\n"); |
| @@ -22,6 +22,17 @@ pub type Kmalloc = Cmalloc; · 21 unmodified lines | ||
| 22 | 22 | pub type Vmalloc = Kmalloc; |
| 23 | 23 | pub type KVmalloc = Kmalloc; |
| 24 | 24 | |
| 25 | +impl Cmalloc { | |
| 26 | + /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of | |
| 27 | + /// `layout`. | |
| 28 | + pub fn aligned_layout(layout: Layout) -> Layout { | |
| 29 | + // Note that `layout.size()` (after padding) is guaranteed to be a multiple of | |
| 30 | + // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return | |
| 31 | + // a properly aligned object (see comments in `kmalloc()` for more information). | |
| 32 | + layout.pad_to_align() | |
| 33 | + } | |
| 34 | +} | |
| 35 | + | |
| 25 | 36 | extern "C" { |
| 26 | 37 | #[link_name = "aligned_alloc"] |
| 27 | 38 | fn libc_aligned_alloc(align: usize, size: usize) -> *mut crate::ffi::c_void; |
| @@ -15,23 +15,130 @@ use crate::c_str; · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | pub mod property; |
| 17 | 17 | |
| 18 | −/// A reference-counted device. | |
| 18 | +/// The core representation of a device in the kernel's driver model. | |
| 19 | 19 | /// |
| 20 | −/// This structure represents the Rust abstraction for a C `struct device`. This implementation | |
| 21 | −/// abstracts the usage of an already existing C `struct device` within Rust code that we get | |
| 22 | −/// passed from the C side. | |
| 20 | +/// This structure represents the Rust abstraction for a C `struct device`. A [`Device`] can either | |
| 21 | +/// exist as temporary reference (see also [`Device::from_raw`]), which is only valid within a | |
| 22 | +/// certain scope or as [`ARef<Device>`], owning a dedicated reference count. | |
| 23 | 23 | /// |
| 24 | −/// An instance of this abstraction can be obtained temporarily or permanent. | |
| 24 | +/// # Device Types | |
| 25 | 25 | /// |
| 26 | −/// A temporary one is bound to the lifetime of the C `struct device` pointer used for creation. | |
| 27 | −/// A permanent instance is always reference-counted and hence not restricted by any lifetime | |
| 28 | −/// boundaries. | |
| 26 | +/// A [`Device`] can represent either a bus device or a class device. | |
| 29 | 27 | /// |
| 30 | −/// For subsystems it is recommended to create a permanent instance to wrap into a subsystem | |
| 31 | −/// specific device structure (e.g. `pci::Device`). This is useful for passing it to drivers in | |
| 32 | −/// `T::probe()`, such that a driver can store the `ARef<Device>` (equivalent to storing a | |
| 33 | −/// `struct device` pointer in a C driver) for arbitrary purposes, e.g. allocating DMA coherent | |
| 34 | −/// memory. | |
| 28 | +/// ## Bus Devices | |
| 29 | +/// | |
| 30 | +/// A bus device is a [`Device`] that is associated with a physical or virtual bus. Examples of | |
| 31 | +/// buses include PCI, USB, I2C, and SPI. Devices attached to a bus are registered with a specific | |
| 32 | +/// bus type, which facilitates matching devices with appropriate drivers based on IDs or other | |
| 33 | +/// identifying information. Bus devices are visible in sysfs under `/sys/bus/<bus-name>/devices/`. | |
| 34 | +/// | |
| 35 | +/// ## Class Devices | |
| 36 | +/// | |
| 37 | +/// A class device is a [`Device`] that is associated with a logical category of functionality | |
| 38 | +/// rather than a physical bus. Examples of classes include block devices, network interfaces, sound | |
| 39 | +/// cards, and input devices. Class devices are grouped under a common class and exposed to | |
| 40 | +/// userspace via entries in `/sys/class/<class-name>/`. | |
| 41 | +/// | |
| 42 | +/// # Device Context | |
| 43 | +/// | |
| 44 | +/// [`Device`] references are generic over a [`DeviceContext`], which represents the type state of | |
| 45 | +/// a [`Device`]. | |
| 46 | +/// | |
| 47 | +/// As the name indicates, this type state represents the context of the scope the [`Device`] | |
| 48 | +/// reference is valid in. For instance, the [`Bound`] context guarantees that the [`Device`] is | |
| 49 | +/// bound to a driver for the entire duration of the existence of a [`Device<Bound>`] reference. | |
| 50 | +/// | |
| 51 | +/// Other [`DeviceContext`] types besides [`Bound`] are [`Normal`], [`Core`] and [`CoreInternal`]. | |
| 52 | +/// | |
| 53 | +/// Unless selected otherwise [`Device`] defaults to the [`Normal`] [`DeviceContext`], which by | |
| 54 | +/// itself has no additional requirements. | |
| 55 | +/// | |
| 56 | +/// It is always up to the caller of [`Device::from_raw`] to select the correct [`DeviceContext`] | |
| 57 | +/// type for the corresponding scope the [`Device`] reference is created in. | |
| 58 | +/// | |
| 59 | +/// All [`DeviceContext`] types other than [`Normal`] are intended to be used with | |
| 60 | +/// [bus devices](#bus-devices) only. | |
| 61 | +/// | |
| 62 | +/// # Implementing Bus Devices | |
| 63 | +/// | |
| 64 | +/// This section provides a guideline to implement bus specific devices, such as [`pci::Device`] or | |
| 65 | +/// [`platform::Device`]. | |
| 66 | +/// | |
| 67 | +/// A bus specific device should be defined as follows. | |
| 68 | +/// | |
| 69 | +/// ```ignore | |
| 70 | +/// #[repr(transparent)] | |
| 71 | +/// pub struct Device<Ctx: device::DeviceContext = device::Normal>( | |
| 72 | +/// Opaque<bindings::bus_device_type>, | |
| 73 | +/// PhantomData<Ctx>, | |
| 74 | +/// ); | |
| 75 | +/// ``` | |
| 76 | +/// | |
| 77 | +/// Since devices are reference counted, [`AlwaysRefCounted`] should be implemented for `Device` | |
| 78 | +/// (i.e. `Device<Normal>`). Note that [`AlwaysRefCounted`] must not be implemented for any other | |
| 79 | +/// [`DeviceContext`], since all other device context types are only valid within a certain scope. | |
| 80 | +/// | |
| 81 | +/// In order to be able to implement the [`DeviceContext`] dereference hierarchy, bus device | |
| 82 | +/// implementations should call the [`impl_device_context_deref`] macro as shown below. | |
| 83 | +/// | |
| 84 | +/// ```ignore | |
| 85 | +/// // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s | |
| 86 | +/// // generic argument. | |
| 87 | +/// kernel::impl_device_context_deref!(unsafe { Device }); | |
| 88 | +/// ``` | |
| 89 | +/// | |
| 90 | +/// In order to convert from a any [`Device<Ctx>`] to [`ARef<Device>`], bus devices can implement | |
| 91 | +/// the following macro call. | |
| 92 | +/// | |
| 93 | +/// ```ignore | |
| 94 | +/// kernel::impl_device_context_into_aref!(Device); | |
| 95 | +/// ``` | |
| 96 | +/// | |
| 97 | +/// Bus devices should also implement the following [`AsRef`] implementation, such that users can | |
| 98 | +/// easily derive a generic [`Device`] reference. | |
| 99 | +/// | |
| 100 | +/// ```ignore | |
| 101 | +/// impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> { | |
| 102 | +/// fn as_ref(&self) -> &device::Device<Ctx> { | |
| 103 | +/// ... | |
| 104 | +/// } | |
| 105 | +/// } | |
| 106 | +/// ``` | |
| 107 | +/// | |
| 108 | +/// # Implementing Class Devices | |
| 109 | +/// | |
| 110 | +/// Class device implementations require less infrastructure and depend slightly more on the | |
| 111 | +/// specific subsystem. | |
| 112 | +/// | |
| 113 | +/// An example implementation for a class device could look like this. | |
| 114 | +/// | |
| 115 | +/// ```ignore | |
| 116 | +/// #[repr(C)] | |
| 117 | +/// pub struct Device<T: class::Driver> { | |
| 118 | +/// dev: Opaque<bindings::class_device_type>, | |
| 119 | +/// data: T::Data, | |
| 120 | +/// } | |
| 121 | +/// ``` | |
| 122 | +/// | |
| 123 | +/// This class device uses the sub-classing pattern to embed the driver's private data within the | |
| 124 | +/// allocation of the class device. For this to be possible the class device is generic over the | |
| 125 | +/// class specific `Driver` trait implementation. | |
| 126 | +/// | |
| 127 | +/// Just like any device, class devices are reference counted and should hence implement | |
| 128 | +/// [`AlwaysRefCounted`] for `Device`. | |
| 129 | +/// | |
| 130 | +/// Class devices should also implement the following [`AsRef`] implementation, such that users can | |
| 131 | +/// easily derive a generic [`Device`] reference. | |
| 132 | +/// | |
| 133 | +/// ```ignore | |
| 134 | +/// impl<T: class::Driver> AsRef<device::Device> for Device<T> { | |
| 135 | +/// fn as_ref(&self) -> &device::Device { | |
| 136 | +/// ... | |
| 137 | +/// } | |
| 138 | +/// } | |
| 139 | +/// ``` | |
| 140 | +/// | |
| 141 | +/// An example for a class device implementation is [`drm::Device`]. | |
| 35 | 142 | /// |
| 36 | 143 | /// # Invariants |
| 37 | 144 | /// |
| @@ -42,6 +149,12 @@ pub mod property; · 4 unmodified lines | ||
| 42 | 149 | /// |
| 43 | 150 | /// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be |
| 44 | 151 | /// dropped from any thread. |
| 152 | +/// | |
| 153 | +/// [`AlwaysRefCounted`]: kernel::types::AlwaysRefCounted | |
| 154 | +/// [`drm::Device`]: kernel::drm::Device | |
| 155 | +/// [`impl_device_context_deref`]: kernel::impl_device_context_deref | |
| 156 | +/// [`pci::Device`]: kernel::pci::Device | |
| 157 | +/// [`platform::Device`]: kernel::platform::Device | |
| 45 | 158 | #[repr(transparent)] |
| 46 | 159 | pub struct Device<Ctx: DeviceContext = Normal>(Opaque<bindings::device>, PhantomData<Ctx>); |
| 47 | 160 | |
| @@ -311,28 +424,75 @@ unsafe impl Send for Device {} · 263 unmodified lines | ||
| 311 | 424 | // synchronization in `struct device`. |
| 312 | 425 | unsafe impl Sync for Device {} |
| 313 | 426 | |
| 314 | −/// Marker trait for the context of a bus specific device. | |
| 427 | +/// Marker trait for the context or scope of a bus specific device. | |
| 428 | +/// | |
| 429 | +/// [`DeviceContext`] is a marker trait for types representing the context of a bus specific | |
| 430 | +/// [`Device`]. | |
| 431 | +/// | |
| 432 | +/// The specific device context types are: [`CoreInternal`], [`Core`], [`Bound`] and [`Normal`]. | |
| 315 | 433 | /// |
| 316 | −/// Some functions of a bus specific device should only be called from a certain context, i.e. bus | |
| 317 | −/// callbacks, such as `probe()`. | |
| 434 | +/// [`DeviceContext`] types are hierarchical, which means that there is a strict hierarchy that | |
| 435 | +/// defines which [`DeviceContext`] type can be derived from another. For instance, any | |
| 436 | +/// [`Device<Core>`] can dereference to a [`Device<Bound>`]. | |
| 318 | 437 | /// |
| 319 | −/// This is the marker trait for structures representing the context of a bus specific device. | |
| 438 | +/// The following enumeration illustrates the dereference hierarchy of [`DeviceContext`] types. | |
| 439 | +/// | |
| 440 | +/// - [`CoreInternal`] => [`Core`] => [`Bound`] => [`Normal`] | |
| 441 | +/// | |
| 442 | +/// Bus devices can automatically implement the dereference hierarchy by using | |
| 443 | +/// [`impl_device_context_deref`]. | |
| 444 | +/// | |
| 445 | +/// Note that the guarantee for a [`Device`] reference to have a certain [`DeviceContext`] comes | |
| 446 | +/// from the specific scope the [`Device`] reference is valid in. | |
| 447 | +/// | |
| 448 | +/// [`impl_device_context_deref`]: kernel::impl_device_context_deref | |
| 320 | 449 | pub trait DeviceContext: private::Sealed {} |
| 321 | 450 | |
| 322 | −/// The [`Normal`] context is the context of a bus specific device when it is not an argument of | |
| 323 | −/// any bus callback. | |
| 451 | +/// The [`Normal`] context is the default [`DeviceContext`] of any [`Device`]. | |
| 452 | +/// | |
| 453 | +/// The normal context does not indicate any specific context. Any `Device<Ctx>` is also a valid | |
| 454 | +/// [`Device<Normal>`]. It is the only [`DeviceContext`] for which it is valid to implement | |
| 455 | +/// [`AlwaysRefCounted`] for. | |
| 456 | +/// | |
| 457 | +/// [`AlwaysRefCounted`]: kernel::types::AlwaysRefCounted | |
| 324 | 458 | pub struct Normal; |
| 325 | 459 | |
| 326 | −/// The [`Core`] context is the context of a bus specific device when it is supplied as argument of | |
| 327 | −/// any of the bus callbacks, such as `probe()`. | |
| 460 | +/// The [`Core`] context is the context of a bus specific device when it appears as argument of | |
| 461 | +/// any bus specific callback, such as `probe()`. | |
| 462 | +/// | |
| 463 | +/// The core context indicates that the [`Device<Core>`] reference's scope is limited to the bus | |
| 464 | +/// callback it appears in. It is intended to be used for synchronization purposes. Bus device | |
| 465 | +/// implementations can implement methods for [`Device<Core>`], such that they can only be called | |
| 466 | +/// from bus callbacks. | |
| 328 | 467 | pub struct Core; |
| 329 | 468 | |
| 330 | −/// Semantically the same as [`Core`] but reserved for internal usage of the corresponding bus | |
| 469 | +/// Semantically the same as [`Core`], but reserved for internal usage of the corresponding bus | |
| 331 | 470 | /// abstraction. |
| 471 | +/// | |
| 472 | +/// The internal core context is intended to be used in exactly the same way as the [`Core`] | |
| 473 | +/// context, with the difference that this [`DeviceContext`] is internal to the corresponding bus | |
| 474 | +/// abstraction. | |
| 475 | +/// | |
| 476 | +/// This context mainly exists to share generic [`Device`] infrastructure that should only be called | |
| 477 | +/// from bus callbacks with bus abstractions, but without making them accessible for drivers. | |
| 332 | 478 | pub struct CoreInternal; |
| 333 | 479 | |
| 334 | −/// The [`Bound`] context is the context of a bus specific device reference when it is guaranteed to | |
| 335 | −/// be bound for the duration of its lifetime. | |
| 480 | +/// The [`Bound`] context is the [`DeviceContext`] of a bus specific device when it is guaranteed to | |
| 481 | +/// be bound to a driver. | |
| 482 | +/// | |
| 483 | +/// The bound context indicates that for the entire duration of the lifetime of a [`Device<Bound>`] | |
| 484 | +/// reference, the [`Device`] is guaranteed to be bound to a driver. | |
| 485 | +/// | |
| 486 | +/// Some APIs, such as [`dma::CoherentAllocation`] or [`Devres`] rely on the [`Device`] to be bound, | |
| 487 | +/// which can be proven with the [`Bound`] device context. | |
| 488 | +/// | |
| 489 | +/// Any abstraction that can guarantee a scope where the corresponding bus device is bound, should | |
| 490 | +/// provide a [`Device<Bound>`] reference to its users for this scope. This allows users to benefit | |
| 491 | +/// from optimizations for accessing device resources, see also [`Devres::access`]. | |
| 492 | +/// | |
| 493 | +/// [`Devres`]: kernel::devres::Devres | |
| 494 | +/// [`Devres::access`]: kernel::devres::Devres::access | |
| 495 | +/// [`dma::CoherentAllocation`]: kernel::dma::CoherentAllocation | |
| 336 | 496 | pub struct Bound; |
| 337 | 497 | |
| 338 | 498 | mod private { |
| @@ -115,10 +115,11 @@ pub struct Devres<T: Send> { · 114 unmodified lines | ||
| 115 | 115 | /// Contains all the fields shared with [`Self::callback`]. |
| 116 | 116 | // TODO: Replace with `UnsafePinned`, once available. |
| 117 | 117 | // |
| 118 | − // Subsequently, the `drop_in_place()` in `Devres::drop` and the explicit `Send` and `Sync' | |
| 119 | − // impls can be removed. | |
| 118 | + // Subsequently, the `drop_in_place()` in `Devres::drop` and `Devres::new` as well as the | |
| 119 | + // explicit `Send` and `Sync' impls can be removed. | |
| 120 | 120 | #[pin] |
| 121 | 121 | inner: Opaque<Inner<T>>, |
| 122 | + _add_action: (), | |
| 122 | 123 | } |
| 123 | 124 | |
| 124 | 125 | impl<T: Send> Devres<T> { |
| @@ -140,7 +141,15 @@ impl<T: Send> Devres<T> { · 15 unmodified lines | ||
| 140 | 141 | dev: dev.into(), |
| 141 | 142 | callback, |
| 142 | 143 | // INVARIANT: `inner` is properly initialized. |
| 143 | − inner <- { | |
| 144 | + inner <- Opaque::pin_init(try_pin_init!(Inner { | |
| 145 | + devm <- Completion::new(), | |
| 146 | + revoke <- Completion::new(), | |
| 147 | + data <- Revocable::new(data), | |
| 148 | + })), | |
| 149 | + // TODO: Replace with "initializer code blocks" [1] once available. | |
| 150 | + // | |
| 151 | + // [1] https://github.com/Rust-for-Linux/pin-init/pull/69 | |
| 152 | + _add_action: { | |
| 144 | 153 | // SAFETY: `this` is a valid pointer to uninitialized memory. |
| 145 | 154 | let inner = unsafe { &raw mut (*this.as_ptr()).inner }; |
| 146 | 155 | |
| @@ -152,13 +161,13 @@ impl<T: Send> Devres<T> { · 5 unmodified lines | ||
| 152 | 161 | // live at least as long as the returned `impl PinInit<Self, Error>`. |
| 153 | 162 | to_result(unsafe { |
| 154 | 163 | bindings::devm_add_action(dev.as_raw(), Some(callback), inner.cast()) |
| 155 | − })?; | |
| 164 | + }).inspect_err(|_| { | |
| 165 | + let inner = Opaque::cast_into(inner); | |
| 156 | 166 | |
| 157 | − Opaque::pin_init(try_pin_init!(Inner { | |
| 158 | − devm <- Completion::new(), | |
| 159 | − revoke <- Completion::new(), | |
| 160 | − data <- Revocable::new(data), | |
| 161 | − })) | |
| 167 | + // SAFETY: `inner` is a valid pointer to an `Inner<T>` and valid for both reads | |
| 168 | + // and writes. | |
| 169 | + unsafe { core::ptr::drop_in_place(inner) }; | |
| 170 | + })?; | |
| 162 | 171 | }, |
| 163 | 172 | }) |
| 164 | 173 | } |
| @@ -2,8 +2,93 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | //! Generic support for drivers of different buses (e.g., PCI, Platform, Amba, etc.). |
| 4 | 4 | //! |
| 5 | −//! Each bus / subsystem is expected to implement [`RegistrationOps`], which allows drivers to | |
| 6 | −//! register using the [`Registration`] class. | |
| 5 | +//! This documentation describes how to implement a bus specific driver API and how to align it with | |
| 6 | +//! the design of (bus specific) devices. | |
| 7 | +//! | |
| 8 | +//! Note: Readers are expected to know the content of the documentation of [`Device`] and | |
| 9 | +//! [`DeviceContext`]. | |
| 10 | +//! | |
| 11 | +//! # Driver Trait | |
| 12 | +//! | |
| 13 | +//! The main driver interface is defined by a bus specific driver trait. For instance: | |
| 14 | +//! | |
| 15 | +//! ```ignore | |
| 16 | +//! pub trait Driver: Send { | |
| 17 | +//! /// The type holding information about each device ID supported by the driver. | |
| 18 | +//! type IdInfo: 'static; | |
| 19 | +//! | |
| 20 | +//! /// The table of OF device ids supported by the driver. | |
| 21 | +//! const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None; | |
| 22 | +//! | |
| 23 | +//! /// The table of ACPI device ids supported by the driver. | |
| 24 | +//! const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None; | |
| 25 | +//! | |
| 26 | +//! /// Driver probe. | |
| 27 | +//! fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; | |
| 28 | +//! | |
| 29 | +//! /// Driver unbind (optional). | |
| 30 | +//! fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) { | |
| 31 | +//! let _ = (dev, this); | |
| 32 | +//! } | |
| 33 | +//! } | |
| 34 | +//! ``` | |
| 35 | +//! | |
| 36 | +//! For specific examples see [`auxiliary::Driver`], [`pci::Driver`] and [`platform::Driver`]. | |
| 37 | +//! | |
| 38 | +//! The `probe()` callback should return a `Result<Pin<KBox<Self>>>`, i.e. the driver's private | |
| 39 | +//! data. The bus abstraction should store the pointer in the corresponding bus device. The generic | |
| 40 | +//! [`Device`] infrastructure provides common helpers for this purpose on its | |
| 41 | +//! [`Device<CoreInternal>`] implementation. | |
| 42 | +//! | |
| 43 | +//! All driver callbacks should provide a reference to the driver's private data. Once the driver | |
| 44 | +//! is unbound from the device, the bus abstraction should take back the ownership of the driver's | |
| 45 | +//! private data from the corresponding [`Device`] and [`drop`] it. | |
| 46 | +//! | |
| 47 | +//! All driver callbacks should provide a [`Device<Core>`] reference (see also [`device::Core`]). | |
| 48 | +//! | |
| 49 | +//! # Adapter | |
| 50 | +//! | |
| 51 | +//! The adapter implementation of a bus represents the abstraction layer between the C bus | |
| 52 | +//! callbacks and the Rust bus callbacks. It therefore has to be generic over an implementation of | |
| 53 | +//! the [driver trait](#driver-trait). | |
| 54 | +//! | |
| 55 | +//! ```ignore | |
| 56 | +//! pub struct Adapter<T: Driver>; | |
| 57 | +//! ``` | |
| 58 | +//! | |
| 59 | +//! There's a common [`Adapter`] trait that can be implemented to inherit common driver | |
| 60 | +//! infrastructure, such as finding the ID info from an [`of::IdTable`] or [`acpi::IdTable`]. | |
| 61 | +//! | |
| 62 | +//! # Driver Registration | |
| 63 | +//! | |
| 64 | +//! In order to register C driver types (such as `struct platform_driver`) the [adapter](#adapter) | |
| 65 | +//! should implement the [`RegistrationOps`] trait. | |
| 66 | +//! | |
| 67 | +//! This trait implementation can be used to create the actual registration with the common | |
| 68 | +//! [`Registration`] type. | |
| 69 | +//! | |
| 70 | +//! Typically, bus abstractions want to provide a bus specific `module_bus_driver!` macro, which | |
| 71 | +//! creates a kernel module with exactly one [`Registration`] for the bus specific adapter. | |
| 72 | +//! | |
| 73 | +//! The generic driver infrastructure provides a helper for this with the [`module_driver`] macro. | |
| 74 | +//! | |
| 75 | +//! # Device IDs | |
| 76 | +//! | |
| 77 | +//! Besides the common device ID types, such as [`of::DeviceId`] and [`acpi::DeviceId`], most buses | |
| 78 | +//! may need to implement their own device ID types. | |
| 79 | +//! | |
| 80 | +//! For this purpose the generic infrastructure in [`device_id`] should be used. | |
| 81 | +//! | |
| 82 | +//! [`auxiliary::Driver`]: kernel::auxiliary::Driver | |
| 83 | +//! [`Core`]: device::Core | |
| 84 | +//! [`Device`]: device::Device | |
| 85 | +//! [`Device<Core>`]: device::Device<device::Core> | |
| 86 | +//! [`Device<CoreInternal>`]: device::Device<device::CoreInternal> | |
| 87 | +//! [`DeviceContext`]: device::DeviceContext | |
| 88 | +//! [`device_id`]: kernel::device_id | |
| 89 | +//! [`module_driver`]: kernel::module_driver | |
| 90 | +//! [`pci::Driver`]: kernel::pci::Driver | |
| 91 | +//! [`platform::Driver`]: kernel::platform::Driver | |
| 7 | 92 | |
| 8 | 93 | use crate::error::{Error, Result}; |
| 9 | 94 | use crate::{acpi, device, of, str::CStr, try_pin_init, types::Opaque, ThisModule}; |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | //! C header: [`include/linux/drm/drm_device.h`](srctree/include/linux/drm/drm_device.h) |
| 6 | 6 | |
| 7 | 7 | use crate::{ |
| 8 | + alloc::allocator::Kmalloc, | |
| 8 | 9 | bindings, device, drm, |
| 9 | 10 | drm::driver::AllocImpl, |
| 10 | 11 | error::from_err_ptr, |
| @@ -12,7 +13,7 @@ use crate::{ · 1 unmodified line | ||
| 12 | 13 | prelude::*, |
| 13 | 14 | types::{ARef, AlwaysRefCounted, Opaque}, |
| 14 | 15 | }; |
| 15 | −use core::{mem, ops::Deref, ptr, ptr::NonNull}; | |
| 16 | +use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull}; | |
| 16 | 17 | |
| 17 | 18 | #[cfg(CONFIG_DRM_LEGACY)] |
| 18 | 19 | macro_rules! drm_legacy_fields { |
| @@ -53,10 +54,8 @@ macro_rules! drm_legacy_fields { · 34 unmodified lines | ||
| 53 | 54 | /// |
| 54 | 55 | /// `self.dev` is a valid instance of a `struct device`. |
| 55 | 56 | #[repr(C)] |
| 56 | −#[pin_data] | |
| 57 | 57 | pub struct Device<T: drm::Driver> { |
| 58 | 58 | dev: Opaque<bindings::drm_device>, |
| 59 | − #[pin] | |
| 60 | 59 | data: T::Data, |
| 61 | 60 | } |
| 62 | 61 | |
| @@ -96,6 +95,10 @@ impl<T: drm::Driver> Device<T> { · 33 unmodified lines | ||
| 96 | 95 | |
| 97 | 96 | /// Create a new `drm::Device` for a `drm::Driver`. |
| 98 | 97 | pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<ARef<Self>> { |
| 98 | + // `__drm_dev_alloc` uses `kmalloc()` to allocate memory, hence ensure a `kmalloc()` | |
| 99 | + // compatible `Layout`. | |
| 100 | + let layout = Kmalloc::aligned_layout(Layout::new::<Self>()); | |
| 101 | + | |
| 99 | 102 | // SAFETY: |
| 100 | 103 | // - `VTABLE`, as a `const` is pinned to the read-only section of the compilation, |
| 101 | 104 | // - `dev` is valid by its type invarants, |
| @@ -103,7 +106,7 @@ impl<T: drm::Driver> Device<T> { · 1 unmodified line | ||
| 103 | 106 | bindings::__drm_dev_alloc( |
| 104 | 107 | dev.as_raw(), |
| 105 | 108 | &Self::VTABLE, |
| 106 | − mem::size_of::<Self>(), | |
| 109 | + layout.size(), | |
| 107 | 110 | mem::offset_of!(Self, dev), |
| 108 | 111 | ) |
| 109 | 112 | } |
| @@ -117,9 +120,13 @@ impl<T: drm::Driver> Device<T> { · 7 unmodified lines | ||
| 117 | 120 | // - `raw_data` is a valid pointer to uninitialized memory. |
| 118 | 121 | // - `raw_data` will not move until it is dropped. |
| 119 | 122 | unsafe { data.__pinned_init(raw_data) }.inspect_err(|_| { |
| 120 | − // SAFETY: `__drm_dev_alloc()` was successful, hence `raw_drm` must be valid and the | |
| 123 | + // SAFETY: `raw_drm` is a valid pointer to `Self`, given that `__drm_dev_alloc` was | |
| 124 | + // successful. | |
| 125 | + let drm_dev = unsafe { Self::into_drm_device(raw_drm) }; | |
| 126 | + | |
| 127 | + // SAFETY: `__drm_dev_alloc()` was successful, hence `drm_dev` must be valid and the | |
| 121 | 128 | // refcount must be non-zero. |
| 122 | − unsafe { bindings::drm_dev_put(ptr::addr_of_mut!((*raw_drm.as_ptr()).dev).cast()) }; | |
| 129 | + unsafe { bindings::drm_dev_put(drm_dev) }; | |
| 123 | 130 | })?; |
| 124 | 131 | |
| 125 | 132 | // SAFETY: The reference count is one, and now we take ownership of that reference as a |
| @@ -140,6 +147,14 @@ impl<T: drm::Driver> Device<T> { · 14 unmodified lines | ||
| 140 | 147 | unsafe { crate::container_of!(Opaque::cast_from(ptr), Self, dev) }.cast_mut() |
| 141 | 148 | } |
| 142 | 149 | |
| 150 | + /// # Safety | |
| 151 | + /// | |
| 152 | + /// `ptr` must be a valid pointer to `Self`. | |
| 153 | + unsafe fn into_drm_device(ptr: NonNull<Self>) -> *mut bindings::drm_device { | |
| 154 | + // SAFETY: By the safety requirements of this function, `ptr` is a valid pointer to `Self`. | |
| 155 | + unsafe { &raw mut (*ptr.as_ptr()).dev }.cast() | |
| 156 | + } | |
| 157 | + | |
| 143 | 158 | /// Not intended to be called externally, except via declare_drm_ioctls!() |
| 144 | 159 | /// |
| 145 | 160 | /// # Safety |
| @@ -189,8 +204,11 @@ unsafe impl<T: drm::Driver> AlwaysRefCounted for Device<T> { · 43 unmodified lines | ||
| 189 | 204 | } |
| 190 | 205 | |
| 191 | 206 | unsafe fn dec_ref(obj: NonNull<Self>) { |
| 207 | + // SAFETY: `obj` is a valid pointer to `Self`. | |
| 208 | + let drm_dev = unsafe { Self::into_drm_device(obj) }; | |
| 209 | + | |
| 192 | 210 | // SAFETY: The safety requirements guarantee that the refcount is non-zero. |
| 193 | − unsafe { bindings::drm_dev_put(obj.cast().as_ptr()) }; | |
| 211 | + unsafe { bindings::drm_dev_put(drm_dev) }; | |
| 194 | 212 | } |
| 195 | 213 | } |
| 196 | 214 | |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | //! |
| 5 | 5 | //! This module provides bindings for working with faux devices in kernel modules. |
| 6 | 6 | //! |
| 7 | −//! C header: [`include/linux/device/faux.h`] | |
| 7 | +//! C header: [`include/linux/device/faux.h`](srctree/include/linux/device/faux.h) | |
| 8 | 8 | |
| 9 | 9 | use crate::{bindings, device, error::code::*, prelude::*}; |
| 10 | 10 | use core::ptr::{addr_of_mut, null, null_mut, NonNull}; |
| @@ -2139,14 +2139,14 @@ static int snd_utimer_create(struct snd_timer_uinfo *utimer_info, · 2138 unmodified lines | ||
| 2139 | 2139 | goto err_take_id; |
| 2140 | 2140 | } |
| 2141 | 2141 | |
| 2142 | + utimer->id = utimer_id; | |
| 2143 | + | |
| 2142 | 2144 | utimer->name = kasprintf(GFP_KERNEL, "snd-utimer%d", utimer_id); |
| 2143 | 2145 | if (!utimer->name) { |
| 2144 | 2146 | err = -ENOMEM; |
| 2145 | 2147 | goto err_get_name; |
| 2146 | 2148 | } |
| 2147 | 2149 | |
| 2148 | − utimer->id = utimer_id; | |
| 2149 | − | |
| 2150 | 2150 | tid.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; |
| 2151 | 2151 | tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL; |
| 2152 | 2152 | tid.card = -1; |
| @@ -510,6 +510,15 @@ static void alc256_shutup(struct hda_codec *codec) · 509 unmodified lines | ||
| 510 | 510 | hp_pin = 0x21; |
| 511 | 511 | |
| 512 | 512 | alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ |
| 513 | + | |
| 514 | + /* 3k pull low control for Headset jack. */ | |
| 515 | + /* NOTE: call this before clearing the pin, otherwise codec stalls */ | |
| 516 | + /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly | |
| 517 | + * when booting with headset plugged. So skip setting it for the codec alc257 | |
| 518 | + */ | |
| 519 | + if (spec->en_3kpull_low) | |
| 520 | + alc_update_coef_idx(codec, 0x46, 0, 3 << 12); | |
| 521 | + | |
| 513 | 522 | hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); |
| 514 | 523 | |
| 515 | 524 | if (hp_pin_sense) { |
| @@ -520,14 +529,6 @@ static void alc256_shutup(struct hda_codec *codec) · 4 unmodified lines | ||
| 520 | 529 | |
| 521 | 530 | msleep(75); |
| 522 | 531 | |
| 523 | − /* 3k pull low control for Headset jack. */ | |
| 524 | − /* NOTE: call this before clearing the pin, otherwise codec stalls */ | |
| 525 | − /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly | |
| 526 | − * when booting with headset plugged. So skip setting it for the codec alc257 | |
| 527 | − */ | |
| 528 | − if (spec->en_3kpull_low) | |
| 529 | − alc_update_coef_idx(codec, 0x46, 0, 3 << 12); | |
| 530 | − | |
| 531 | 532 | if (!spec->no_shutup_pins) |
| 532 | 533 | snd_hda_codec_write(codec, hp_pin, 0, |
| 533 | 534 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); |
| @@ -3579,6 +3580,7 @@ enum { · 3045 unmodified lines | ||
| 3579 | 3580 | ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE, |
| 3580 | 3581 | ALC294_FIXUP_ASUS_MIC, |
| 3581 | 3582 | ALC294_FIXUP_ASUS_HEADSET_MIC, |
| 3583 | + ALC294_FIXUP_ASUS_I2C_HEADSET_MIC, | |
| 3582 | 3584 | ALC294_FIXUP_ASUS_SPK, |
| 3583 | 3585 | ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE, |
| 3584 | 3586 | ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE, |
| @@ -4889,6 +4891,15 @@ static const struct hda_fixup alc269_fixups[] = { · 1304 unmodified lines | ||
| 4889 | 4891 | .chained = true, |
| 4890 | 4892 | .chain_id = ALC269_FIXUP_HEADSET_MIC |
| 4891 | 4893 | }, |
| 4894 | + [ALC294_FIXUP_ASUS_I2C_HEADSET_MIC] = { | |
| 4895 | + .type = HDA_FIXUP_PINS, | |
| 4896 | + .v.pins = (const struct hda_pintbl[]) { | |
| 4897 | + { 0x19, 0x03a19020 }, /* use as headset mic */ | |
| 4898 | + { } | |
| 4899 | + }, | |
| 4900 | + .chained = true, | |
| 4901 | + .chain_id = ALC287_FIXUP_CS35L41_I2C_2 | |
| 4902 | + }, | |
| 4892 | 4903 | [ALC294_FIXUP_ASUS_SPK] = { |
| 4893 | 4904 | .type = HDA_FIXUP_VERBS, |
| 4894 | 4905 | .v.verbs = (const struct hda_verb[]) { |
| @@ -6368,6 +6379,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = { · 1473 unmodified lines | ||
| 6368 | 6379 | SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), |
| 6369 | 6380 | SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360), |
| 6370 | 6381 | SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), |
| 6382 | + SND_PCI_QUIRK(0x103c, 0x8548, "HP EliteBook x360 830 G6", ALC285_FIXUP_HP_GPIO_LED), | |
| 6383 | + SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED), | |
| 6371 | 6384 | SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11), |
| 6372 | 6385 | SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360), |
| 6373 | 6386 | SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT), |
| @@ -6728,7 +6741,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { · 354 unmodified lines | ||
| 6728 | 6741 | SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC), |
| 6729 | 6742 | SND_PCI_QUIRK(0x1043, 0x1b93, "ASUS G614JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2), |
| 6730 | 6743 | SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), |
| 6731 | − SND_PCI_QUIRK(0x1043, 0x1c03, "ASUS UM3406HA", ALC287_FIXUP_CS35L41_I2C_2), | |
| 6744 | + SND_PCI_QUIRK(0x1043, 0x1c03, "ASUS UM3406HA", ALC294_FIXUP_ASUS_I2C_HEADSET_MIC), | |
| 6732 | 6745 | SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
| 6733 | 6746 | SND_PCI_QUIRK(0x1043, 0x1c33, "ASUS UX5304MA", ALC245_FIXUP_CS35L41_SPI_2), |
| 6734 | 6747 | SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2), |
| @@ -267,7 +267,7 @@ static const struct snd_kcontrol_new tas2770_snd_controls[] = { · 266 unmodified lines | ||
| 267 | 267 | static const struct snd_kcontrol_new tas2781_snd_controls[] = { |
| 268 | 268 | ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2781_AMP_LEVEL, |
| 269 | 269 | 1, 0, 20, 0, tas2781_amp_getvol, |
| 270 | − tas2781_amp_putvol, amp_vol_tlv), | |
| 270 | + tas2781_amp_putvol, tas2781_amp_tlv), | |
| 271 | 271 | ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, |
| 272 | 272 | tas2781_force_fwload_get, tas2781_force_fwload_put), |
| 273 | 273 | }; |
| @@ -305,7 +305,7 @@ static int tas2563_save_calibration(struct tas2781_hda *h) · 31 unmodified lines | ||
| 305 | 305 | efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX]; |
| 306 | 306 | unsigned long max_size = TAS2563_CAL_DATA_SIZE; |
| 307 | 307 | unsigned char var8[TAS2563_CAL_VAR_NAME_MAX]; |
| 308 | − struct tasdevice_priv *p = h->hda_priv; | |
| 308 | + struct tasdevice_priv *p = h->priv; | |
| 309 | 309 | struct calidata *cd = &p->cali_data; |
| 310 | 310 | struct cali_reg *r = &cd->cali_reg_array; |
| 311 | 311 | unsigned int offset = 0; |
| @@ -494,9 +494,11 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol, · 493 unmodified lines | ||
| 494 | 494 | |
| 495 | 495 | static struct snd_kcontrol_new tas2781_snd_ctls[] = { |
| 496 | 496 | ACARD_SINGLE_RANGE_EXT_TLV(NULL, TAS2781_AMP_LEVEL, 1, 0, 20, 0, |
| 497 | − tas2781_amp_getvol, tas2781_amp_putvol, amp_vol_tlv), | |
| 497 | + tas2781_amp_getvol, tas2781_amp_putvol, | |
| 498 | + tas2781_amp_tlv), | |
| 498 | 499 | ACARD_SINGLE_RANGE_EXT_TLV(NULL, TAS2781_DVC_LVL, 0, 0, 200, 1, |
| 499 | − tas2781_digital_getvol, tas2781_digital_putvol, dvc_tlv), | |
| 500 | + tas2781_digital_getvol, tas2781_digital_putvol, | |
| 501 | + tas2781_dvc_tlv), | |
| 500 | 502 | ACARD_SINGLE_BOOL_EXT(NULL, 0, tas2781_force_fwload_get, |
| 501 | 503 | tas2781_force_fwload_put), |
| 502 | 504 | }; |
| @@ -393,74 +393,6 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, · 392 unmodified lines | ||
| 393 | 393 | return 0; |
| 394 | 394 | } |
| 395 | 395 | |
| 396 | −static int cs35l63_sdw_kick_divider(struct cs35l56_private *cs35l56, | |
| 397 | − struct sdw_slave *peripheral) | |
| 398 | −{ | |
| 399 | − unsigned int curr_scale_reg, next_scale_reg; | |
| 400 | − int curr_scale, next_scale, ret; | |
| 401 | − | |
| 402 | − if (!cs35l56->base.init_done) | |
| 403 | − return 0; | |
| 404 | − | |
| 405 | − if (peripheral->bus->params.curr_bank) { | |
| 406 | − curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; | |
| 407 | − next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; | |
| 408 | − } else { | |
| 409 | − curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; | |
| 410 | − next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; | |
| 411 | − } | |
| 412 | − | |
| 413 | − /* | |
| 414 | − * Current clock scale value must be different to new value. | |
| 415 | − * Modify current to guarantee this. If next still has the dummy | |
| 416 | − * value we wrote when it was current, the core code has not set | |
| 417 | − * a new scale so restore its original good value | |
| 418 | − */ | |
| 419 | − curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); | |
| 420 | − if (curr_scale < 0) { | |
| 421 | − dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale); | |
| 422 | − return curr_scale; | |
| 423 | − } | |
| 424 | − | |
| 425 | − next_scale = sdw_read_no_pm(peripheral, next_scale_reg); | |
| 426 | − if (next_scale < 0) { | |
| 427 | − dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale); | |
| 428 | − return next_scale; | |
| 429 | − } | |
| 430 | − | |
| 431 | − if (next_scale == CS35L56_SDW_INVALID_BUS_SCALE) { | |
| 432 | − next_scale = cs35l56->old_sdw_clock_scale; | |
| 433 | − ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); | |
| 434 | − if (ret < 0) { | |
| 435 | − dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", | |
| 436 | − ret); | |
| 437 | − return ret; | |
| 438 | − } | |
| 439 | − } | |
| 440 | − | |
| 441 | − cs35l56->old_sdw_clock_scale = curr_scale; | |
| 442 | − ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); | |
| 443 | − if (ret < 0) { | |
| 444 | − dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret); | |
| 445 | − return ret; | |
| 446 | − } | |
| 447 | − | |
| 448 | − dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale); | |
| 449 | − | |
| 450 | − return 0; | |
| 451 | −} | |
| 452 | − | |
| 453 | −static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, | |
| 454 | − struct sdw_bus_params *params) | |
| 455 | −{ | |
| 456 | − struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); | |
| 457 | − | |
| 458 | − if ((cs35l56->base.type == 0x63) && (cs35l56->base.rev < 0xa1)) | |
| 459 | − return cs35l63_sdw_kick_divider(cs35l56, peripheral); | |
| 460 | − | |
| 461 | − return 0; | |
| 462 | −} | |
| 463 | − | |
| 464 | 396 | static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, |
| 465 | 397 | enum sdw_clk_stop_mode mode, |
| 466 | 398 | enum sdw_clk_stop_type type) |
| @@ -476,7 +408,6 @@ static const struct sdw_slave_ops cs35l56_sdw_ops = { · 9 unmodified lines | ||
| 476 | 408 | .read_prop = cs35l56_sdw_read_prop, |
| 477 | 409 | .interrupt_callback = cs35l56_sdw_interrupt, |
| 478 | 410 | .update_status = cs35l56_sdw_update_status, |
| 479 | − .bus_config = cs35l56_sdw_bus_config, | |
| 480 | 411 | #ifdef DEBUG |
| 481 | 412 | .clk_stop = cs35l56_sdw_clk_stop, |
| 482 | 413 | #endif |
| @@ -838,6 +838,15 @@ const struct cirrus_amp_cal_controls cs35l56_calibration_controls = { · 837 unmodified lines | ||
| 838 | 838 | }; |
| 839 | 839 | EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, "SND_SOC_CS35L56_SHARED"); |
| 840 | 840 | |
| 841 | +static const struct cirrus_amp_cal_controls cs35l63_calibration_controls = { | |
| 842 | + .alg_id = 0xbf210, | |
| 843 | + .mem_region = WMFW_ADSP2_YM, | |
| 844 | + .ambient = "CAL_AMBIENT", | |
| 845 | + .calr = "CAL_R", | |
| 846 | + .status = "CAL_STATUS", | |
| 847 | + .checksum = "CAL_CHECKSUM", | |
| 848 | +}; | |
| 849 | + | |
| 841 | 850 | int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base) |
| 842 | 851 | { |
| 843 | 852 | u64 silicon_uid = 0; |
| @@ -912,19 +921,31 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_read_prot_status, "SND_SOC_CS35L56_SHARED"); · 68 unmodified lines | ||
| 912 | 921 | void cs35l56_log_tuning(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp) |
| 913 | 922 | { |
| 914 | 923 | __be32 pid, sid, tid; |
| 924 | + unsigned int alg_id; | |
| 915 | 925 | int ret; |
| 916 | 926 | |
| 927 | + switch (cs35l56_base->type) { | |
| 928 | + case 0x54: | |
| 929 | + case 0x56: | |
| 930 | + case 0x57: | |
| 931 | + alg_id = 0x9f212; | |
| 932 | + break; | |
| 933 | + default: | |
| 934 | + alg_id = 0xbf212; | |
| 935 | + break; | |
| 936 | + } | |
| 937 | + | |
| 917 | 938 | scoped_guard(mutex, &cs_dsp->pwr_lock) { |
| 918 | 939 | ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_PRJCT_ID", |
| 919 | − WMFW_ADSP2_XM, 0x9f212), | |
| 940 | + WMFW_ADSP2_XM, alg_id), | |
| 920 | 941 | 0, &pid, sizeof(pid)); |
| 921 | 942 | if (!ret) |
| 922 | 943 | ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_CHNNL_ID", |
| 923 | − WMFW_ADSP2_XM, 0x9f212), | |
| 944 | + WMFW_ADSP2_XM, alg_id), | |
| 924 | 945 | 0, &sid, sizeof(sid)); |
| 925 | 946 | if (!ret) |
| 926 | 947 | ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_SNPSHT_ID", |
| 927 | − WMFW_ADSP2_XM, 0x9f212), | |
| 948 | + WMFW_ADSP2_XM, alg_id), | |
| 928 | 949 | 0, &tid, sizeof(tid)); |
| 929 | 950 | } |
| 930 | 951 | |
| @@ -974,8 +995,10 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) · 43 unmodified lines | ||
| 974 | 995 | case 0x35A54: |
| 975 | 996 | case 0x35A56: |
| 976 | 997 | case 0x35A57: |
| 998 | + cs35l56_base->calibration_controls = &cs35l56_calibration_controls; | |
| 977 | 999 | break; |
| 978 | 1000 | case 0x35A630: |
| 1001 | + cs35l56_base->calibration_controls = &cs35l63_calibration_controls; | |
| 979 | 1002 | devid = devid >> 4; |
| 980 | 1003 | break; |
| 981 | 1004 | default: |
| @@ -695,7 +695,7 @@ static int cs35l56_write_cal(struct cs35l56_private *cs35l56) · 694 unmodified lines | ||
| 695 | 695 | return ret; |
| 696 | 696 | |
| 697 | 697 | ret = cs_amp_write_cal_coeffs(&cs35l56->dsp.cs_dsp, |
| 698 | − &cs35l56_calibration_controls, | |
| 698 | + cs35l56->base.calibration_controls, | |
| 699 | 699 | &cs35l56->base.cal_data); |
| 700 | 700 | |
| 701 | 701 | wm_adsp_stop(&cs35l56->dsp); |
| @@ -20,8 +20,6 @@ · 19 unmodified lines | ||
| 20 | 20 | #define CS35L56_SDW_GEN_INT_MASK_1 0xc1 |
| 21 | 21 | #define CS35L56_SDW_INT_MASK_CODEC_IRQ BIT(0) |
| 22 | 22 | |
| 23 | −#define CS35L56_SDW_INVALID_BUS_SCALE 0xf | |
| 24 | − | |
| 25 | 23 | #define CS35L56_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) |
| 26 | 24 | #define CS35L56_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE \ |
| 27 | 25 | | SNDRV_PCM_FMTBIT_S32_LE) |
| @@ -52,7 +50,6 @@ struct cs35l56_private { · 24 unmodified lines | ||
| 52 | 50 | u8 asp_slot_count; |
| 53 | 51 | bool tdm_mode; |
| 54 | 52 | bool sysclk_set; |
| 55 | − u8 old_sdw_clock_scale; | |
| 56 | 53 | u8 sdw_link_num; |
| 57 | 54 | u8 sdw_unique_id; |
| 58 | 55 | }; |
| @@ -636,7 +636,7 @@ static int es8389_set_bias_level(struct snd_soc_component *component, · 635 unmodified lines | ||
| 636 | 636 | regmap_write(es8389->regmap, ES8389_ANA_CTL1, 0x59); |
| 637 | 637 | regmap_write(es8389->regmap, ES8389_ADC_EN, 0x00); |
| 638 | 638 | regmap_write(es8389->regmap, ES8389_CLK_OFF1, 0x00); |
| 639 | − regmap_write(es8389->regmap, ES8389_RESET, 0x7E); | |
| 639 | + regmap_write(es8389->regmap, ES8389_RESET, 0x3E); | |
| 640 | 640 | regmap_update_bits(es8389->regmap, ES8389_DAC_INV, 0x80, 0x80); |
| 641 | 641 | usleep_range(8000, 8500); |
| 642 | 642 | regmap_update_bits(es8389->regmap, ES8389_DAC_INV, 0x80, 0x00); |
| @@ -910,10 +910,10 @@ static const struct snd_kcontrol_new tasdevice_cali_controls[] = { · 909 unmodified lines | ||
| 910 | 910 | static const struct snd_kcontrol_new tas2781_snd_controls[] = { |
| 911 | 911 | SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2781_AMP_LEVEL, |
| 912 | 912 | 1, 0, 20, 0, tas2781_amp_getvol, |
| 913 | − tas2781_amp_putvol, amp_vol_tlv), | |
| 913 | + tas2781_amp_putvol, tas2781_amp_tlv), | |
| 914 | 914 | SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2781_DVC_LVL, |
| 915 | 915 | 0, 0, 200, 1, tas2781_digital_getvol, |
| 916 | − tas2781_digital_putvol, dvc_tlv), | |
| 916 | + tas2781_digital_putvol, tas2781_dvc_tlv), | |
| 917 | 917 | }; |
| 918 | 918 | |
| 919 | 919 | static const struct snd_kcontrol_new tas2781_cali_controls[] = { |
| @@ -349,7 +349,7 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor · 348 unmodified lines | ||
| 349 | 349 | u16 cs_len; |
| 350 | 350 | u8 cs_type; |
| 351 | 351 | |
| 352 | − if (len < sizeof(*p)) | |
| 352 | + if (len < sizeof(*cs_desc)) | |
| 353 | 353 | break; |
| 354 | 354 | cs_len = le16_to_cpu(cs_desc->wLength); |
| 355 | 355 | if (len < cs_len) |
| @@ -285,7 +285,7 @@ static const struct usb_desc_validator audio_validators[] = { · 284 unmodified lines | ||
| 285 | 285 | /* UAC_VERSION_3, UAC3_EXTENDED_TERMINAL: not implemented yet */ |
| 286 | 286 | FUNC(UAC_VERSION_3, UAC3_MIXER_UNIT, validate_mixer_unit), |
| 287 | 287 | FUNC(UAC_VERSION_3, UAC3_SELECTOR_UNIT, validate_selector_unit), |
| 288 | − FUNC(UAC_VERSION_3, UAC_FEATURE_UNIT, validate_uac3_feature_unit), | |
| 288 | + FUNC(UAC_VERSION_3, UAC3_FEATURE_UNIT, validate_uac3_feature_unit), | |
| 289 | 289 | /* UAC_VERSION_3, UAC3_EFFECT_UNIT: not implemented yet */ |
| 290 | 290 | FUNC(UAC_VERSION_3, UAC3_PROCESSING_UNIT, validate_processing_unit), |
| 291 | 291 | FUNC(UAC_VERSION_3, UAC3_EXTENSION_UNIT, validate_processing_unit), |
| @@ -75,11 +75,13 @@ · 74 unmodified lines | ||
| 75 | 75 | #define ARM_CPU_PART_CORTEX_A76 0xD0B |
| 76 | 76 | #define ARM_CPU_PART_NEOVERSE_N1 0xD0C |
| 77 | 77 | #define ARM_CPU_PART_CORTEX_A77 0xD0D |
| 78 | +#define ARM_CPU_PART_CORTEX_A76AE 0xD0E | |
| 78 | 79 | #define ARM_CPU_PART_NEOVERSE_V1 0xD40 |
| 79 | 80 | #define ARM_CPU_PART_CORTEX_A78 0xD41 |
| 80 | 81 | #define ARM_CPU_PART_CORTEX_A78AE 0xD42 |
| 81 | 82 | #define ARM_CPU_PART_CORTEX_X1 0xD44 |
| 82 | 83 | #define ARM_CPU_PART_CORTEX_A510 0xD46 |
| 84 | +#define ARM_CPU_PART_CORTEX_X1C 0xD4C | |
| 83 | 85 | #define ARM_CPU_PART_CORTEX_A520 0xD80 |
| 84 | 86 | #define ARM_CPU_PART_CORTEX_A710 0xD47 |
| 85 | 87 | #define ARM_CPU_PART_CORTEX_A715 0xD4D |
| @@ -119,9 +121,11 @@ · 33 unmodified lines | ||
| 119 | 121 | #define QCOM_CPU_PART_KRYO 0x200 |
| 120 | 122 | #define QCOM_CPU_PART_KRYO_2XX_GOLD 0x800 |
| 121 | 123 | #define QCOM_CPU_PART_KRYO_2XX_SILVER 0x801 |
| 124 | +#define QCOM_CPU_PART_KRYO_3XX_GOLD 0x802 | |
| 122 | 125 | #define QCOM_CPU_PART_KRYO_3XX_SILVER 0x803 |
| 123 | 126 | #define QCOM_CPU_PART_KRYO_4XX_GOLD 0x804 |
| 124 | 127 | #define QCOM_CPU_PART_KRYO_4XX_SILVER 0x805 |
| 128 | +#define QCOM_CPU_PART_ORYON_X1 0x001 | |
| 125 | 129 | |
| 126 | 130 | #define NVIDIA_CPU_PART_DENVER 0x003 |
| 127 | 131 | #define NVIDIA_CPU_PART_CARMEL 0x004 |
| @@ -129,6 +133,7 @@ · 1 unmodified line | ||
| 129 | 133 | #define FUJITSU_CPU_PART_A64FX 0x001 |
| 130 | 134 | |
| 131 | 135 | #define HISI_CPU_PART_TSV110 0xD01 |
| 136 | +#define HISI_CPU_PART_HIP09 0xD02 | |
| 132 | 137 | #define HISI_CPU_PART_HIP12 0xD06 |
| 133 | 138 | |
| 134 | 139 | #define APPLE_CPU_PART_M1_ICESTORM 0x022 |
| @@ -159,11 +164,13 @@ · 24 unmodified lines | ||
| 159 | 164 | #define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76) |
| 160 | 165 | #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1) |
| 161 | 166 | #define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77) |
| 167 | +#define MIDR_CORTEX_A76AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76AE) | |
| 162 | 168 | #define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1) |
| 163 | 169 | #define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78) |
| 164 | 170 | #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) |
| 165 | 171 | #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) |
| 166 | 172 | #define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510) |
| 173 | +#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C) | |
| 167 | 174 | #define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520) |
| 168 | 175 | #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) |
| 169 | 176 | #define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715) |
| @@ -196,13 +203,26 @@ · 26 unmodified lines | ||
| 196 | 203 | #define MIDR_QCOM_KRYO MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO) |
| 197 | 204 | #define MIDR_QCOM_KRYO_2XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_GOLD) |
| 198 | 205 | #define MIDR_QCOM_KRYO_2XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_SILVER) |
| 206 | +#define MIDR_QCOM_KRYO_3XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_3XX_GOLD) | |
| 199 | 207 | #define MIDR_QCOM_KRYO_3XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_3XX_SILVER) |
| 200 | 208 | #define MIDR_QCOM_KRYO_4XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_GOLD) |
| 201 | 209 | #define MIDR_QCOM_KRYO_4XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_SILVER) |
| 210 | +#define MIDR_QCOM_ORYON_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_ORYON_X1) | |
| 211 | + | |
| 212 | +/* | |
| 213 | + * NOTES: | |
| 214 | + * - Qualcomm Kryo 5XX Prime / Gold ID themselves as MIDR_CORTEX_A77 | |
| 215 | + * - Qualcomm Kryo 5XX Silver IDs itself as MIDR_QCOM_KRYO_4XX_SILVER | |
| 216 | + * - Qualcomm Kryo 6XX Prime IDs itself as MIDR_CORTEX_X1 | |
| 217 | + * - Qualcomm Kryo 6XX Gold IDs itself as ARM_CPU_PART_CORTEX_A78 | |
| 218 | + * - Qualcomm Kryo 6XX Silver IDs itself as MIDR_CORTEX_A55 | |
| 219 | + */ | |
| 220 | + | |
| 202 | 221 | #define MIDR_NVIDIA_DENVER MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_DENVER) |
| 203 | 222 | #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL) |
| 204 | 223 | #define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX) |
| 205 | 224 | #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110) |
| 225 | +#define MIDR_HISI_HIP09 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP09) | |
| 206 | 226 | #define MIDR_HISI_HIP12 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP12) |
| 207 | 227 | #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) |
| 208 | 228 | #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) |
| @@ -291,6 +311,14 @@ static inline u32 __attribute_const__ read_cpuid_id(void) · 82 unmodified lines | ||
| 291 | 311 | return read_cpuid(MIDR_EL1); |
| 292 | 312 | } |
| 293 | 313 | |
| 314 | +struct target_impl_cpu { | |
| 315 | + u64 midr; | |
| 316 | + u64 revidr; | |
| 317 | + u64 aidr; | |
| 318 | +}; | |
| 319 | + | |
| 320 | +bool cpu_errata_set_target_impl(u64 num, void *impl_cpus); | |
| 321 | + | |
| 294 | 322 | static inline u64 __attribute_const__ read_cpuid_mpidr(void) |
| 295 | 323 | { |
| 296 | 324 | return read_cpuid(MPIDR_EL1); |
| @@ -1,18 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ |
| 2 | 2 | /* |
| 3 | − * This program is free software; you can redistribute it and/or modify | |
| 4 | − * it under the terms of the GNU General Public License, version 2, as | |
| 5 | − * published by the Free Software Foundation. | |
| 6 | − * | |
| 7 | − * This program is distributed in the hope that it will be useful, | |
| 8 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 9 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 10 | − * GNU General Public License for more details. | |
| 11 | − * | |
| 12 | − * You should have received a copy of the GNU General Public License | |
| 13 | − * along with this program; if not, write to the Free Software | |
| 14 | − * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| 15 | − * | |
| 16 | 3 | * Copyright IBM Corp. 2007 |
| 17 | 4 | * |
| 18 | 5 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> |
| @@ -218,6 +218,7 @@ · 217 unmodified lines | ||
| 218 | 218 | #define X86_FEATURE_FLEXPRIORITY ( 8*32+ 1) /* "flexpriority" Intel FlexPriority */ |
| 219 | 219 | #define X86_FEATURE_EPT ( 8*32+ 2) /* "ept" Intel Extended Page Table */ |
| 220 | 220 | #define X86_FEATURE_VPID ( 8*32+ 3) /* "vpid" Intel Virtual Processor ID */ |
| 221 | +#define X86_FEATURE_COHERENCY_SFW_NO ( 8*32+ 4) /* SNP cache coherency software work around not needed */ | |
| 221 | 222 | |
| 222 | 223 | #define X86_FEATURE_VMMCALL ( 8*32+15) /* "vmmcall" Prefer VMMCALL to VMCALL */ |
| 223 | 224 | #define X86_FEATURE_XENPV ( 8*32+16) /* Xen paravirtual guest */ |
| @@ -456,10 +457,14 @@ · 232 unmodified lines | ||
| 456 | 457 | #define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* No Nested Data Breakpoints */ |
| 457 | 458 | #define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */ |
| 458 | 459 | #define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* LFENCE always serializing / synchronizes RDTSC */ |
| 460 | +#define X86_FEATURE_VERW_CLEAR (20*32+ 5) /* The memory form of VERW mitigates TSA */ | |
| 459 | 461 | #define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* Null Selector Clears Base */ |
| 462 | + | |
| 460 | 463 | #define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */ |
| 461 | 464 | #define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */ |
| 462 | 465 | |
| 466 | +#define X86_FEATURE_GP_ON_USER_CPUID (20*32+17) /* User CPUID faulting */ | |
| 467 | + | |
| 463 | 468 | #define X86_FEATURE_PREFETCHI (20*32+20) /* Prefetch Data/Instruction to Cache Level */ |
| 464 | 469 | #define X86_FEATURE_SBPB (20*32+27) /* Selective Branch Prediction Barrier */ |
| 465 | 470 | #define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* MSR_PRED_CMD[IBPB] flushes all branch type predictions */ |
| @@ -487,6 +492,9 @@ · 21 unmodified lines | ||
| 487 | 492 | #define X86_FEATURE_PREFER_YMM (21*32+ 8) /* Avoid ZMM registers due to downclocking */ |
| 488 | 493 | #define X86_FEATURE_APX (21*32+ 9) /* Advanced Performance Extensions */ |
| 489 | 494 | #define X86_FEATURE_INDIRECT_THUNK_ITS (21*32+10) /* Use thunk for indirect branches in lower half of cacheline */ |
| 495 | +#define X86_FEATURE_TSA_SQ_NO (21*32+11) /* AMD CPU not vulnerable to TSA-SQ */ | |
| 496 | +#define X86_FEATURE_TSA_L1_NO (21*32+12) /* AMD CPU not vulnerable to TSA-L1 */ | |
| 497 | +#define X86_FEATURE_CLEAR_CPU_BUF_VM (21*32+13) /* Clear CPU buffers using VERW before VMRUN */ | |
| 490 | 498 | |
| 491 | 499 | /* |
| 492 | 500 | * BUG word(s) |
| @@ -542,5 +550,5 @@ · 49 unmodified lines | ||
| 542 | 550 | #define X86_BUG_OLD_MICROCODE X86_BUG( 1*32+ 6) /* "old_microcode" CPU has old microcode, it is surely vulnerable to something */ |
| 543 | 551 | #define X86_BUG_ITS X86_BUG( 1*32+ 7) /* "its" CPU is affected by Indirect Target Selection */ |
| 544 | 552 | #define X86_BUG_ITS_NATIVE_ONLY X86_BUG( 1*32+ 8) /* "its_native_only" CPU is affected by ITS, VMX is not affected */ |
| 545 | − | |
| 553 | +#define X86_BUG_TSA X86_BUG( 1*32+ 9) /* "tsa" CPU is affected by Transient Scheduler Attacks */ | |
| 546 | 554 | #endif /* _ASM_X86_CPUFEATURES_H */ |
| @@ -419,6 +419,7 @@ · 418 unmodified lines | ||
| 419 | 419 | #define DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI (1UL << 12) |
| 420 | 420 | #define DEBUGCTLMSR_FREEZE_IN_SMM_BIT 14 |
| 421 | 421 | #define DEBUGCTLMSR_FREEZE_IN_SMM (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT) |
| 422 | +#define DEBUGCTLMSR_RTM_DEBUG BIT(15) | |
| 422 | 423 | |
| 423 | 424 | #define MSR_PEBS_FRONTEND 0x000003f7 |
| 424 | 425 | |
| @@ -733,6 +734,11 @@ · 308 unmodified lines | ||
| 733 | 734 | #define MSR_AMD64_PERF_CNTR_GLOBAL_CTL 0xc0000301 |
| 734 | 735 | #define MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR 0xc0000302 |
| 735 | 736 | |
| 737 | +/* AMD Hardware Feedback Support MSRs */ | |
| 738 | +#define MSR_AMD_WORKLOAD_CLASS_CONFIG 0xc0000500 | |
| 739 | +#define MSR_AMD_WORKLOAD_CLASS_ID 0xc0000501 | |
| 740 | +#define MSR_AMD_WORKLOAD_HRST 0xc0000502 | |
| 741 | + | |
| 736 | 742 | /* AMD Last Branch Record MSRs */ |
| 737 | 743 | #define MSR_AMD64_LBR_SELECT 0xc000010e |
| 738 | 744 | |
| @@ -831,6 +837,7 @@ · 92 unmodified lines | ||
| 831 | 837 | #define MSR_K7_HWCR_SMMLOCK BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT) |
| 832 | 838 | #define MSR_K7_HWCR_IRPERF_EN_BIT 30 |
| 833 | 839 | #define MSR_K7_HWCR_IRPERF_EN BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT) |
| 840 | +#define MSR_K7_HWCR_CPUID_USER_DIS_BIT 35 | |
| 834 | 841 | #define MSR_K7_FID_VID_CTL 0xc0010041 |
| 835 | 842 | #define MSR_K7_FID_VID_STATUS 0xc0010042 |
| 836 | 843 | #define MSR_K7_HWCR_CPB_DIS_BIT 25 |
| @@ -965,7 +965,13 @@ struct kvm_tdx_cmd { · 964 unmodified lines | ||
| 965 | 965 | struct kvm_tdx_capabilities { |
| 966 | 966 | __u64 supported_attrs; |
| 967 | 967 | __u64 supported_xfam; |
| 968 | − __u64 reserved[254]; | |
| 968 | + | |
| 969 | + __u64 kernel_tdvmcallinfo_1_r11; | |
| 970 | + __u64 user_tdvmcallinfo_1_r11; | |
| 971 | + __u64 kernel_tdvmcallinfo_1_r12; | |
| 972 | + __u64 user_tdvmcallinfo_1_r12; | |
| 973 | + | |
| 974 | + __u64 reserved[250]; | |
| 969 | 975 | |
| 970 | 976 | /* Configurable CPUID bits for userspace */ |
| 971 | 977 | struct kvm_cpuid2 cpuid; |
| @@ -0,0 +1,28 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | + | |
| 3 | +#ifndef _LINUX_ARGS_H | |
| 4 | +#define _LINUX_ARGS_H | |
| 5 | + | |
| 6 | +/* | |
| 7 | + * How do these macros work? | |
| 8 | + * | |
| 9 | + * In __COUNT_ARGS() _0 to _12 are just placeholders from the start | |
| 10 | + * in order to make sure _n is positioned over the correct number | |
| 11 | + * from 12 to 0 (depending on X, which is a variadic argument list). | |
| 12 | + * They serve no purpose other than occupying a position. Since each | |
| 13 | + * macro parameter must have a distinct identifier, those identifiers | |
| 14 | + * are as good as any. | |
| 15 | + * | |
| 16 | + * In COUNT_ARGS() we use actual integers, so __COUNT_ARGS() returns | |
| 17 | + * that as _n. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +/* This counts to 15. Any more, it will return 16th argument. */ | |
| 21 | +#define __COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _n, X...) _n | |
| 22 | +#define COUNT_ARGS(X...) __COUNT_ARGS(, ##X, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) | |
| 23 | + | |
| 24 | +/* Concatenate two parameters, but allow them to be expanded beforehand. */ | |
| 25 | +#define __CONCAT(a, b) a ## b | |
| 26 | +#define CONCATENATE(a, b) __CONCAT(a, b) | |
| 27 | + | |
| 28 | +#endif /* _LINUX_ARGS_H */ | |
| @@ -2,10 +2,8 @@ · 1 unmodified line | ||
| 2 | 2 | #ifndef __LINUX_BITS_H |
| 3 | 3 | #define __LINUX_BITS_H |
| 4 | 4 | |
| 5 | −#include <linux/const.h> | |
| 6 | 5 | #include <vdso/bits.h> |
| 7 | 6 | #include <uapi/linux/bits.h> |
| 8 | −#include <asm/bitsperlong.h> | |
| 9 | 7 | |
| 10 | 8 | #define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG)) |
| 11 | 9 | #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) |
| @@ -50,10 +48,14 @@ · 38 unmodified lines | ||
| 50 | 48 | (type_max(t) << (l) & \ |
| 51 | 49 | type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h))))) |
| 52 | 50 | |
| 51 | +#define GENMASK(h, l) GENMASK_TYPE(unsigned long, h, l) | |
| 52 | +#define GENMASK_ULL(h, l) GENMASK_TYPE(unsigned long long, h, l) | |
| 53 | + | |
| 53 | 54 | #define GENMASK_U8(h, l) GENMASK_TYPE(u8, h, l) |
| 54 | 55 | #define GENMASK_U16(h, l) GENMASK_TYPE(u16, h, l) |
| 55 | 56 | #define GENMASK_U32(h, l) GENMASK_TYPE(u32, h, l) |
| 56 | 57 | #define GENMASK_U64(h, l) GENMASK_TYPE(u64, h, l) |
| 58 | +#define GENMASK_U128(h, l) GENMASK_TYPE(u128, h, l) | |
| 57 | 59 | |
| 58 | 60 | /* |
| 59 | 61 | * Fixed-type variants of BIT(), with additional checks like GENMASK_TYPE(). The |
| @@ -79,28 +81,9 @@ · 19 unmodified lines | ||
| 79 | 81 | * BUILD_BUG_ON_ZERO is not available in h files included from asm files, |
| 80 | 82 | * disable the input check if that is the case. |
| 81 | 83 | */ |
| 82 | −#define GENMASK_INPUT_CHECK(h, l) 0 | |
| 84 | +#define GENMASK(h, l) __GENMASK(h, l) | |
| 85 | +#define GENMASK_ULL(h, l) __GENMASK_ULL(h, l) | |
| 83 | 86 | |
| 84 | 87 | #endif /* !defined(__ASSEMBLY__) */ |
| 85 | 88 | |
| 86 | −#define GENMASK(h, l) \ | |
| 87 | − (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l)) | |
| 88 | −#define GENMASK_ULL(h, l) \ | |
| 89 | − (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l)) | |
| 90 | − | |
| 91 | −#if !defined(__ASSEMBLY__) | |
| 92 | −/* | |
| 93 | − * Missing asm support | |
| 94 | − * | |
| 95 | − * __GENMASK_U128() depends on _BIT128() which would not work | |
| 96 | − * in the asm code, as it shifts an 'unsigned __int128' data | |
| 97 | − * type instead of direct representation of 128 bit constants | |
| 98 | − * such as long and unsigned long. The fundamental problem is | |
| 99 | − * that a 128 bit constant will get silently truncated by the | |
| 100 | − * gcc compiler. | |
| 101 | − */ | |
| 102 | −#define GENMASK_U128(h, l) \ | |
| 103 | − (GENMASK_INPUT_CHECK(h, l) + __GENMASK_U128(h, l)) | |
| 104 | −#endif | |
| 105 | − | |
| 106 | 89 | #endif /* __LINUX_BITS_H */ |
| @@ -41,5 +41,28 @@ · 40 unmodified lines | ||
| 41 | 41 | SYM_TYPED_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) |
| 42 | 42 | #endif |
| 43 | 43 | |
| 44 | +#else /* __ASSEMBLY__ */ | |
| 45 | + | |
| 46 | +#ifdef CONFIG_CFI_CLANG | |
| 47 | +#define DEFINE_CFI_TYPE(name, func) \ | |
| 48 | + /* \ | |
| 49 | + * Force a reference to the function so the compiler generates \ | |
| 50 | + * __kcfi_typeid_<func>. \ | |
| 51 | + */ \ | |
| 52 | + __ADDRESSABLE(func); \ | |
| 53 | + /* u32 name __ro_after_init = __kcfi_typeid_<func> */ \ | |
| 54 | + extern u32 name; \ | |
| 55 | + asm ( \ | |
| 56 | + " .pushsection .data..ro_after_init,\"aw\",\%progbits \n" \ | |
| 57 | + " .type " #name ",\%object \n" \ | |
| 58 | + " .globl " #name " \n" \ | |
| 59 | + " .p2align 2, 0x0 \n" \ | |
| 60 | + #name ": \n" \ | |
| 61 | + " .4byte __kcfi_typeid_" #func " \n" \ | |
| 62 | + " .size " #name ", 4 \n" \ | |
| 63 | + " .popsection \n" \ | |
| 64 | + ); | |
| 65 | +#endif | |
| 66 | + | |
| 44 | 67 | #endif /* __ASSEMBLY__ */ |
| 45 | 68 | #endif /* _LINUX_CFI_TYPES_H */ |
| @@ -852,8 +852,14 @@ __SYSCALL(__NR_removexattrat, sys_removexattrat) · 851 unmodified lines | ||
| 852 | 852 | #define __NR_open_tree_attr 467 |
| 853 | 853 | __SYSCALL(__NR_open_tree_attr, sys_open_tree_attr) |
| 854 | 854 | |
| 855 | +/* fs/inode.c */ | |
| 856 | +#define __NR_file_getattr 468 | |
| 857 | +__SYSCALL(__NR_file_getattr, sys_file_getattr) | |
| 858 | +#define __NR_file_setattr 469 | |
| 859 | +__SYSCALL(__NR_file_setattr, sys_file_setattr) | |
| 860 | + | |
| 855 | 861 | #undef __NR_syscalls |
| 856 | −#define __NR_syscalls 468 | |
| 862 | +#define __NR_syscalls 470 | |
| 857 | 863 | |
| 858 | 864 | /* |
| 859 | 865 | * 32 bit systems traditionally used different |
| @@ -178,6 +178,7 @@ struct kvm_xen_exit { · 177 unmodified lines | ||
| 178 | 178 | #define KVM_EXIT_NOTIFY 37 |
| 179 | 179 | #define KVM_EXIT_LOONGARCH_IOCSR 38 |
| 180 | 180 | #define KVM_EXIT_MEMORY_FAULT 39 |
| 181 | +#define KVM_EXIT_TDX 40 | |
| 181 | 182 | |
| 182 | 183 | /* For KVM_EXIT_INTERNAL_ERROR */ |
| 183 | 184 | /* Emulate instruction failed. */ |
| @@ -447,6 +448,31 @@ struct kvm_run { · 263 unmodified lines | ||
| 447 | 448 | __u64 gpa; |
| 448 | 449 | __u64 size; |
| 449 | 450 | } memory_fault; |
| 451 | + /* KVM_EXIT_TDX */ | |
| 452 | + struct { | |
| 453 | + __u64 flags; | |
| 454 | + __u64 nr; | |
| 455 | + union { | |
| 456 | + struct { | |
| 457 | + __u64 ret; | |
| 458 | + __u64 data[5]; | |
| 459 | + } unknown; | |
| 460 | + struct { | |
| 461 | + __u64 ret; | |
| 462 | + __u64 gpa; | |
| 463 | + __u64 size; | |
| 464 | + } get_quote; | |
| 465 | + struct { | |
| 466 | + __u64 ret; | |
| 467 | + __u64 leaf; | |
| 468 | + __u64 r11, r12, r13, r14; | |
| 469 | + } get_tdvmcall_info; | |
| 470 | + struct { | |
| 471 | + __u64 ret; | |
| 472 | + __u64 vector; | |
| 473 | + } setup_event_notify; | |
| 474 | + }; | |
| 475 | + } tdx; | |
| 450 | 476 | /* Fix the size of the union. */ |
| 451 | 477 | char padding[256]; |
| 452 | 478 | }; |
| @@ -935,6 +961,7 @@ struct kvm_enable_cap { · 482 unmodified lines | ||
| 935 | 961 | #define KVM_CAP_ARM_EL2 240 |
| 936 | 962 | #define KVM_CAP_ARM_EL2_E2H0 241 |
| 937 | 963 | #define KVM_CAP_RISCV_MP_STATE_RESET 242 |
| 964 | +#define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243 | |
| 938 | 965 | |
| 939 | 966 | struct kvm_irq_routing_irqchip { |
| 940 | 967 | __u32 irqchip; |
| @@ -482,3 +482,5 @@ · 481 unmodified lines | ||
| 482 | 482 | 465 common listxattrat sys_listxattrat |
| 483 | 483 | 466 common removexattrat sys_removexattrat |
| 484 | 484 | 467 common open_tree_attr sys_open_tree_attr |
| 485 | +468 common file_getattr sys_file_getattr | |
| 486 | +469 common file_setattr sys_file_setattr | |
| @@ -382,3 +382,5 @@ · 381 unmodified lines | ||
| 382 | 382 | 465 n64 listxattrat sys_listxattrat |
| 383 | 383 | 466 n64 removexattrat sys_removexattrat |
| 384 | 384 | 467 n64 open_tree_attr sys_open_tree_attr |
| 385 | +468 n64 file_getattr sys_file_getattr | |
| 386 | +469 n64 file_setattr sys_file_setattr | |
| @@ -558,3 +558,5 @@ · 557 unmodified lines | ||
| 558 | 558 | 465 common listxattrat sys_listxattrat |
| 559 | 559 | 466 common removexattrat sys_removexattrat |
| 560 | 560 | 467 common open_tree_attr sys_open_tree_attr |
| 561 | +468 common file_getattr sys_file_getattr | |
| 562 | +469 common file_setattr sys_file_setattr | |
| @@ -470,3 +470,5 @@ · 469 unmodified lines | ||
| 470 | 470 | 465 common listxattrat sys_listxattrat sys_listxattrat |
| 471 | 471 | 466 common removexattrat sys_removexattrat sys_removexattrat |
| 472 | 472 | 467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr |
| 473 | +468 common file_getattr sys_file_getattr sys_file_getattr | |
| 474 | +469 common file_setattr sys_file_setattr sys_file_setattr | |
| @@ -471,3 +471,5 @@ · 470 unmodified lines | ||
| 471 | 471 | 465 common listxattrat sys_listxattrat |
| 472 | 472 | 466 common removexattrat sys_removexattrat |
| 473 | 473 | 467 common open_tree_attr sys_open_tree_attr |
| 474 | +468 common file_getattr sys_file_getattr | |
| 475 | +469 common file_setattr sys_file_setattr | |
| @@ -513,3 +513,5 @@ · 512 unmodified lines | ||
| 513 | 513 | 465 common listxattrat sys_listxattrat |
| 514 | 514 | 466 common removexattrat sys_removexattrat |
| 515 | 515 | 467 common open_tree_attr sys_open_tree_attr |
| 516 | +468 common file_getattr sys_file_getattr | |
| 517 | +469 common file_setattr sys_file_setattr | |
| @@ -473,3 +473,5 @@ · 472 unmodified lines | ||
| 473 | 473 | 465 i386 listxattrat sys_listxattrat |
| 474 | 474 | 466 i386 removexattrat sys_removexattrat |
| 475 | 475 | 467 i386 open_tree_attr sys_open_tree_attr |
| 476 | +468 i386 file_getattr sys_file_getattr | |
| 477 | +469 i386 file_setattr sys_file_setattr | |
| @@ -391,6 +391,8 @@ · 390 unmodified lines | ||
| 391 | 391 | 465 common listxattrat sys_listxattrat |
| 392 | 392 | 466 common removexattrat sys_removexattrat |
| 393 | 393 | 467 common open_tree_attr sys_open_tree_attr |
| 394 | +468 common file_getattr sys_file_getattr | |
| 395 | +469 common file_setattr sys_file_setattr | |
| 394 | 396 | |
| 395 | 397 | # |
| 396 | 398 | # Due to a historical design error, certain syscalls are numbered differently |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | #include "arch-tests.h" |
| 3 | 3 | #include "../util/topdown.h" |
| 4 | +#include "debug.h" | |
| 4 | 5 | #include "evlist.h" |
| 5 | 6 | #include "parse-events.h" |
| 6 | 7 | #include "pmu.h" |
| @@ -438,3 +438,5 @@ · 437 unmodified lines | ||
| 438 | 438 | 465 common listxattrat sys_listxattrat |
| 439 | 439 | 466 common removexattrat sys_removexattrat |
| 440 | 440 | 467 common open_tree_attr sys_open_tree_attr |
| 441 | +468 common file_getattr sys_file_getattr | |
| 442 | +469 common file_setattr sys_file_setattr | |
| @@ -85,7 +85,7 @@ static int add_dso(const char *fpath, const struct stat *sb __maybe_unused, · 84 unmodified lines | ||
| 85 | 85 | if (typeflag == FTW_D || typeflag == FTW_SL) |
| 86 | 86 | return 0; |
| 87 | 87 | |
| 88 | − if (filename__read_build_id(fpath, &bid) < 0) | |
| 88 | + if (filename__read_build_id(fpath, &bid, /*block=*/true) < 0) | |
| 89 | 89 | return 0; |
| 90 | 90 | |
| 91 | 91 | dso->name = realpath(fpath, NULL); |
| @@ -180,7 +180,7 @@ static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi) · 179 unmodified lines | ||
| 180 | 180 | struct nscookie nsc; |
| 181 | 181 | |
| 182 | 182 | nsinfo__mountns_enter(nsi, &nsc); |
| 183 | − err = filename__read_build_id(filename, &bid); | |
| 183 | + err = filename__read_build_id(filename, &bid, /*block=*/true); | |
| 184 | 184 | nsinfo__mountns_exit(&nsc); |
| 185 | 185 | if (err < 0) { |
| 186 | 186 | pr_debug("Couldn't read a build-id in %s\n", filename); |
| @@ -204,7 +204,7 @@ static int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi) · 17 unmodified lines | ||
| 204 | 204 | int err; |
| 205 | 205 | |
| 206 | 206 | nsinfo__mountns_enter(nsi, &nsc); |
| 207 | − err = filename__read_build_id(filename, &bid); | |
| 207 | + err = filename__read_build_id(filename, &bid, /*block=*/true); | |
| 208 | 208 | nsinfo__mountns_exit(&nsc); |
| 209 | 209 | if (err < 0) { |
| 210 | 210 | pr_debug("Couldn't read a build-id in %s\n", filename); |
| @@ -280,7 +280,7 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) · 69 unmodified lines | ||
| 280 | 280 | if (!dso__build_id_filename(dso, filename, sizeof(filename), false)) |
| 281 | 281 | return true; |
| 282 | 282 | |
| 283 | − if (filename__read_build_id(filename, &bid) == -1) { | |
| 283 | + if (filename__read_build_id(filename, &bid, /*block=*/true) == -1) { | |
| 284 | 284 | if (errno == ENOENT) |
| 285 | 285 | return false; |
| 286 | 286 | |
| @@ -309,7 +309,7 @@ static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi) · 22 unmodified lines | ||
| 309 | 309 | int err; |
| 310 | 310 | |
| 311 | 311 | nsinfo__mountns_enter(nsi, &nsc); |
| 312 | − err = filename__read_build_id(filename, &bid); | |
| 312 | + err = filename__read_build_id(filename, &bid, /*block=*/true); | |
| 313 | 313 | nsinfo__mountns_exit(&nsc); |
| 314 | 314 | if (err < 0) { |
| 315 | 315 | pr_debug("Couldn't read a build-id in %s\n", filename); |
| @@ -680,12 +680,12 @@ static int dso__read_build_id(struct dso *dso) · 679 unmodified lines | ||
| 680 | 680 | |
| 681 | 681 | mutex_lock(dso__lock(dso)); |
| 682 | 682 | nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); |
| 683 | − if (filename__read_build_id(dso__long_name(dso), &bid) > 0) | |
| 683 | + if (filename__read_build_id(dso__long_name(dso), &bid, /*block=*/true) > 0) | |
| 684 | 684 | dso__set_build_id(dso, &bid); |
| 685 | 685 | else if (dso__nsinfo(dso)) { |
| 686 | 686 | char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso)); |
| 687 | 687 | |
| 688 | − if (new_name && filename__read_build_id(new_name, &bid) > 0) | |
| 688 | + if (new_name && filename__read_build_id(new_name, &bid, /*block=*/true) > 0) | |
| 689 | 689 | dso__set_build_id(dso, &bid); |
| 690 | 690 | free(new_name); |
| 691 | 691 | } |
| @@ -31,7 +31,7 @@ static int build_id_cache__add_file(const char *filename) · 30 unmodified lines | ||
| 31 | 31 | struct build_id bid = { .size = 0, }; |
| 32 | 32 | int err; |
| 33 | 33 | |
| 34 | − err = filename__read_build_id(filename, &bid); | |
| 34 | + err = filename__read_build_id(filename, &bid, /*block=*/true); | |
| 35 | 35 | if (err < 0) { |
| 36 | 36 | pr_debug("Failed to read build id of %s\n", filename); |
| 37 | 37 | return err; |
| @@ -90,10 +90,28 @@ · 89 unmodified lines | ||
| 90 | 90 | #define DN_ATTRIB 0x00000020 /* File changed attibutes */ |
| 91 | 91 | #define DN_MULTISHOT 0x80000000 /* Don't remove notifier */ |
| 92 | 92 | |
| 93 | +/* Reserved kernel ranges [-100], [-10000, -40000]. */ | |
| 93 | 94 | #define AT_FDCWD -100 /* Special value for dirfd used to |
| 94 | 95 | indicate openat should use the |
| 95 | 96 | current working directory. */ |
| 96 | 97 | |
| 98 | +/* | |
| 99 | + * The concept of process and threads in userland and the kernel is a confusing | |
| 100 | + * one - within the kernel every thread is a 'task' with its own individual PID, | |
| 101 | + * however from userland's point of view threads are grouped by a single PID, | |
| 102 | + * which is that of the 'thread group leader', typically the first thread | |
| 103 | + * spawned. | |
| 104 | + * | |
| 105 | + * To cut the Gideon knot, for internal kernel usage, we refer to | |
| 106 | + * PIDFD_SELF_THREAD to refer to the current thread (or task from a kernel | |
| 107 | + * perspective), and PIDFD_SELF_THREAD_GROUP to refer to the current thread | |
| 108 | + * group leader... | |
| 109 | + */ | |
| 110 | +#define PIDFD_SELF_THREAD -10000 /* Current thread. */ | |
| 111 | +#define PIDFD_SELF_THREAD_GROUP -10001 /* Current thread group leader. */ | |
| 112 | + | |
| 113 | +#define FD_PIDFS_ROOT -10002 /* Root of the pidfs filesystem */ | |
| 114 | +#define FD_INVALID -10009 /* Invalid file descriptor: -10000 - EBADF = -10009 */ | |
| 97 | 115 | |
| 98 | 116 | /* Generic flags for the *at(2) family of syscalls. */ |
| 99 | 117 | |
| @@ -60,6 +60,17 @@ · 59 unmodified lines | ||
| 60 | 60 | #define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */ |
| 61 | 61 | #define RENAME_WHITEOUT (1 << 2) /* Whiteout source */ |
| 62 | 62 | |
| 63 | +/* | |
| 64 | + * The root inode of procfs is guaranteed to always have the same inode number. | |
| 65 | + * For programs that make heavy use of procfs, verifying that the root is a | |
| 66 | + * real procfs root and using openat2(RESOLVE_{NO_{XDEV,MAGICLINKS},BENEATH}) | |
| 67 | + * will allow you to make sure you are never tricked into operating on the | |
| 68 | + * wrong procfs file. | |
| 69 | + */ | |
| 70 | +enum procfs_ino { | |
| 71 | + PROCFS_ROOT_INO = 1, | |
| 72 | +}; | |
| 73 | + | |
| 63 | 74 | struct file_clone_range { |
| 64 | 75 | __s64 src_fd; |
| 65 | 76 | __u64 src_offset; |
| @@ -91,6 +102,63 @@ struct fs_sysfs_path { · 25 unmodified lines | ||
| 91 | 102 | __u8 name[128]; |
| 92 | 103 | }; |
| 93 | 104 | |
| 105 | +/* Protection info capability flags */ | |
| 106 | +#define LBMD_PI_CAP_INTEGRITY (1 << 0) | |
| 107 | +#define LBMD_PI_CAP_REFTAG (1 << 1) | |
| 108 | + | |
| 109 | +/* Checksum types for Protection Information */ | |
| 110 | +#define LBMD_PI_CSUM_NONE 0 | |
| 111 | +#define LBMD_PI_CSUM_IP 1 | |
| 112 | +#define LBMD_PI_CSUM_CRC16_T10DIF 2 | |
| 113 | +#define LBMD_PI_CSUM_CRC64_NVME 4 | |
| 114 | + | |
| 115 | +/* sizeof first published struct */ | |
| 116 | +#define LBMD_SIZE_VER0 16 | |
| 117 | + | |
| 118 | +/* | |
| 119 | + * Logical block metadata capability descriptor | |
| 120 | + * If the device does not support metadata, all the fields will be zero. | |
| 121 | + * Applications must check lbmd_flags to determine whether metadata is | |
| 122 | + * supported or not. | |
| 123 | + */ | |
| 124 | +struct logical_block_metadata_cap { | |
| 125 | + /* Bitmask of logical block metadata capability flags */ | |
| 126 | + __u32 lbmd_flags; | |
| 127 | + /* | |
| 128 | + * The amount of data described by each unit of logical block | |
| 129 | + * metadata | |
| 130 | + */ | |
| 131 | + __u16 lbmd_interval; | |
| 132 | + /* | |
| 133 | + * Size in bytes of the logical block metadata associated with each | |
| 134 | + * interval | |
| 135 | + */ | |
| 136 | + __u8 lbmd_size; | |
| 137 | + /* | |
| 138 | + * Size in bytes of the opaque block tag associated with each | |
| 139 | + * interval | |
| 140 | + */ | |
| 141 | + __u8 lbmd_opaque_size; | |
| 142 | + /* | |
| 143 | + * Offset in bytes of the opaque block tag within the logical block | |
| 144 | + * metadata | |
| 145 | + */ | |
| 146 | + __u8 lbmd_opaque_offset; | |
| 147 | + /* Size in bytes of the T10 PI tuple associated with each interval */ | |
| 148 | + __u8 lbmd_pi_size; | |
| 149 | + /* Offset in bytes of T10 PI tuple within the logical block metadata */ | |
| 150 | + __u8 lbmd_pi_offset; | |
| 151 | + /* T10 PI guard tag type */ | |
| 152 | + __u8 lbmd_guard_tag_type; | |
| 153 | + /* Size in bytes of the T10 PI application tag */ | |
| 154 | + __u8 lbmd_app_tag_size; | |
| 155 | + /* Size in bytes of the T10 PI reference tag */ | |
| 156 | + __u8 lbmd_ref_tag_size; | |
| 157 | + /* Size in bytes of the T10 PI storage tag */ | |
| 158 | + __u8 lbmd_storage_tag_size; | |
| 159 | + __u8 pad; | |
| 160 | +}; | |
| 161 | + | |
| 94 | 162 | /* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */ |
| 95 | 163 | #define FILE_DEDUPE_RANGE_SAME 0 |
| 96 | 164 | #define FILE_DEDUPE_RANGE_DIFFERS 1 |
| @@ -148,6 +216,24 @@ struct fsxattr { · 51 unmodified lines | ||
| 148 | 216 | unsigned char fsx_pad[8]; |
| 149 | 217 | }; |
| 150 | 218 | |
| 219 | +/* | |
| 220 | + * Variable size structure for file_[sg]et_attr(). | |
| 221 | + * | |
| 222 | + * Note. This is alternative to the structure 'struct file_kattr'/'struct fsxattr'. | |
| 223 | + * As this structure is passed to/from userspace with its size, this can | |
| 224 | + * be versioned based on the size. | |
| 225 | + */ | |
| 226 | +struct file_attr { | |
| 227 | + __u64 fa_xflags; /* xflags field value (get/set) */ | |
| 228 | + __u32 fa_extsize; /* extsize field value (get/set)*/ | |
| 229 | + __u32 fa_nextents; /* nextents field value (get) */ | |
| 230 | + __u32 fa_projid; /* project identifier (get/set) */ | |
| 231 | + __u32 fa_cowextsize; /* CoW extsize field value (get/set) */ | |
| 232 | +}; | |
| 233 | + | |
| 234 | +#define FILE_ATTR_SIZE_VER0 24 | |
| 235 | +#define FILE_ATTR_SIZE_LATEST FILE_ATTR_SIZE_VER0 | |
| 236 | + | |
| 151 | 237 | /* |
| 152 | 238 | * Flags for the fsx_xflags field |
| 153 | 239 | */ |
| @@ -247,6 +333,8 @@ struct fsxattr { · 93 unmodified lines | ||
| 247 | 333 | * also /sys/kernel/debug/ for filesystems with debugfs exports |
| 248 | 334 | */ |
| 249 | 335 | #define FS_IOC_GETFSSYSFSPATH _IOR(0x15, 1, struct fs_sysfs_path) |
| 336 | +/* Get logical block metadata capability details */ | |
| 337 | +#define FS_IOC_GETLBMD_CAP _IOWR(0x15, 2, struct logical_block_metadata_cap) | |
| 250 | 338 | |
| 251 | 339 | /* |
| 252 | 340 | * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS) |
| @@ -244,6 +244,8 @@ struct prctl_mm_map { · 243 unmodified lines | ||
| 244 | 244 | # define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT) |
| 245 | 245 | /* Unused; kept only for source compatibility */ |
| 246 | 246 | # define PR_MTE_TCF_SHIFT 1 |
| 247 | +/* MTE tag check store only */ | |
| 248 | +# define PR_MTE_STORE_ONLY (1UL << 19) | |
| 247 | 249 | /* RISC-V pointer masking tag length */ |
| 248 | 250 | # define PR_PMLEN_SHIFT 24 |
| 249 | 251 | # define PR_PMLEN_MASK (0x7fUL << PR_PMLEN_SHIFT) |
| @@ -255,7 +257,12 @@ struct prctl_mm_map { · 5 unmodified lines | ||
| 255 | 257 | /* Dispatch syscalls to a userspace handler */ |
| 256 | 258 | #define PR_SET_SYSCALL_USER_DISPATCH 59 |
| 257 | 259 | # define PR_SYS_DISPATCH_OFF 0 |
| 258 | −# define PR_SYS_DISPATCH_ON 1 | |
| 260 | +/* Enable dispatch except for the specified range */ | |
| 261 | +# define PR_SYS_DISPATCH_EXCLUSIVE_ON 1 | |
| 262 | +/* Enable dispatch for the specified range */ | |
| 263 | +# define PR_SYS_DISPATCH_INCLUSIVE_ON 2 | |
| 264 | +/* Legacy name for backwards compatibility */ | |
| 265 | +# define PR_SYS_DISPATCH_ON PR_SYS_DISPATCH_EXCLUSIVE_ON | |
| 259 | 266 | /* The control values for the user space selector when dispatch is enabled */ |
| 260 | 267 | # define SYSCALL_DISPATCH_FILTER_ALLOW 0 |
| 261 | 268 | # define SYSCALL_DISPATCH_FILTER_BLOCK 1 |
| @@ -235,4 +235,39 @@ · 234 unmodified lines | ||
| 235 | 235 | */ |
| 236 | 236 | #define VHOST_VDPA_GET_VRING_SIZE _IOWR(VHOST_VIRTIO, 0x82, \ |
| 237 | 237 | struct vhost_vring_state) |
| 238 | + | |
| 239 | +/* Extended features manipulation */ | |
| 240 | +#define VHOST_GET_FEATURES_ARRAY _IOR(VHOST_VIRTIO, 0x83, \ | |
| 241 | + struct vhost_features_array) | |
| 242 | +#define VHOST_SET_FEATURES_ARRAY _IOW(VHOST_VIRTIO, 0x83, \ | |
| 243 | + struct vhost_features_array) | |
| 244 | + | |
| 245 | +/* fork_owner values for vhost */ | |
| 246 | +#define VHOST_FORK_OWNER_KTHREAD 0 | |
| 247 | +#define VHOST_FORK_OWNER_TASK 1 | |
| 248 | + | |
| 249 | +/** | |
| 250 | + * VHOST_SET_FORK_FROM_OWNER - Set the fork_owner flag for the vhost device, | |
| 251 | + * This ioctl must called before VHOST_SET_OWNER. | |
| 252 | + * Only available when CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL=y | |
| 253 | + * | |
| 254 | + * @param fork_owner: An 8-bit value that determines the vhost thread mode | |
| 255 | + * | |
| 256 | + * When fork_owner is set to VHOST_FORK_OWNER_TASK(default value): | |
| 257 | + * - Vhost will create vhost worker as tasks forked from the owner, | |
| 258 | + * inheriting all of the owner's attributes. | |
| 259 | + * | |
| 260 | + * When fork_owner is set to VHOST_FORK_OWNER_KTHREAD: | |
| 261 | + * - Vhost will create vhost workers as kernel threads. | |
| 262 | + */ | |
| 263 | +#define VHOST_SET_FORK_FROM_OWNER _IOW(VHOST_VIRTIO, 0x84, __u8) | |
| 264 | + | |
| 265 | +/** | |
| 266 | + * VHOST_GET_FORK_OWNER - Get the current fork_owner flag for the vhost device. | |
| 267 | + * Only available when CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL=y | |
| 268 | + * | |
| 269 | + * @return: An 8-bit value indicating the current thread mode. | |
| 270 | + */ | |
| 271 | +#define VHOST_GET_FORK_FROM_OWNER _IOR(VHOST_VIRTIO, 0x85, __u8) | |
| 272 | + | |
| 238 | 273 | #endif |
| @@ -115,7 +115,7 @@ int filename__snprintf_build_id(const char *pathname, char *sbuild_id, size_t sb · 114 unmodified lines | ||
| 115 | 115 | struct build_id bid = { .size = 0, }; |
| 116 | 116 | int ret; |
| 117 | 117 | |
| 118 | − ret = filename__read_build_id(pathname, &bid); | |
| 118 | + ret = filename__read_build_id(pathname, &bid, /*block=*/true); | |
| 119 | 119 | if (ret < 0) |
| 120 | 120 | return ret; |
| 121 | 121 | |
| @@ -841,7 +841,7 @@ static int filename__read_build_id_ns(const char *filename, · 719 unmodified lines | ||
| 841 | 841 | int ret; |
| 842 | 842 | |
| 843 | 843 | nsinfo__mountns_enter(nsi, &nsc); |
| 844 | − ret = filename__read_build_id(filename, bid); | |
| 844 | + ret = filename__read_build_id(filename, bid, /*block=*/true); | |
| 845 | 845 | nsinfo__mountns_exit(&nsc); |
| 846 | 846 | |
| 847 | 847 | return ret; |
| @@ -110,8 +110,12 @@ struct debuginfo *debuginfo__new(const char *path) · 109 unmodified lines | ||
| 110 | 110 | if (!dso) |
| 111 | 111 | goto out; |
| 112 | 112 | |
| 113 | − /* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */ | |
| 114 | − if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0) | |
| 113 | + /* | |
| 114 | + * Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO. Don't block | |
| 115 | + * incase the path isn't for a regular file. | |
| 116 | + */ | |
| 117 | + assert(!dso__has_build_id(dso)); | |
| 118 | + if (filename__read_build_id(path, &bid, /*block=*/false) > 0) | |
| 115 | 119 | dso__set_build_id(dso, &bid); |
| 116 | 120 | |
| 117 | 121 | for (type = distro_dwarf_types; |
| @@ -81,13 +81,13 @@ static int dsos__read_build_ids_cb(struct dso *dso, void *data) · 80 unmodified lines | ||
| 81 | 81 | return 0; |
| 82 | 82 | } |
| 83 | 83 | nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); |
| 84 | − if (filename__read_build_id(dso__long_name(dso), &bid) > 0) { | |
| 84 | + if (filename__read_build_id(dso__long_name(dso), &bid, /*block=*/true) > 0) { | |
| 85 | 85 | dso__set_build_id(dso, &bid); |
| 86 | 86 | args->have_build_id = true; |
| 87 | 87 | } else if (errno == ENOENT && dso__nsinfo(dso)) { |
| 88 | 88 | char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso)); |
| 89 | 89 | |
| 90 | − if (new_name && filename__read_build_id(new_name, &bid) > 0) { | |
| 90 | + if (new_name && filename__read_build_id(new_name, &bid, /*block=*/true) > 0) { | |
| 91 | 91 | dso__set_build_id(dso, &bid); |
| 92 | 92 | args->have_build_id = true; |
| 93 | 93 | } |
| @@ -902,7 +902,7 @@ out_close: · 901 unmodified lines | ||
| 902 | 902 | |
| 903 | 903 | #else // HAVE_LIBBFD_BUILDID_SUPPORT |
| 904 | 904 | |
| 905 | −static int read_build_id(const char *filename, struct build_id *bid) | |
| 905 | +static int read_build_id(const char *filename, struct build_id *bid, bool block) | |
| 906 | 906 | { |
| 907 | 907 | size_t size = sizeof(bid->data); |
| 908 | 908 | int fd, err = -1; |
| @@ -911,7 +911,7 @@ static int read_build_id(const char *filename, struct build_id *bid) · 2 unmodified lines | ||
| 911 | 911 | if (size < BUILD_ID_SIZE) |
| 912 | 912 | goto out; |
| 913 | 913 | |
| 914 | − fd = open(filename, O_RDONLY); | |
| 914 | + fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); | |
| 915 | 915 | if (fd < 0) |
| 916 | 916 | goto out; |
| 917 | 917 | |
| @@ -934,7 +934,7 @@ out: · 16 unmodified lines | ||
| 934 | 934 | |
| 935 | 935 | #endif // HAVE_LIBBFD_BUILDID_SUPPORT |
| 936 | 936 | |
| 937 | −int filename__read_build_id(const char *filename, struct build_id *bid) | |
| 937 | +int filename__read_build_id(const char *filename, struct build_id *bid, bool block) | |
| 938 | 938 | { |
| 939 | 939 | struct kmod_path m = { .name = NULL, }; |
| 940 | 940 | char path[PATH_MAX]; |
| @@ -958,9 +958,10 @@ int filename__read_build_id(const char *filename, struct build_id *bid) · 17 unmodified lines | ||
| 958 | 958 | } |
| 959 | 959 | close(fd); |
| 960 | 960 | filename = path; |
| 961 | + block = true; | |
| 961 | 962 | } |
| 962 | 963 | |
| 963 | − err = read_build_id(filename, bid); | |
| 964 | + err = read_build_id(filename, bid, block); | |
| 964 | 965 | |
| 965 | 966 | if (m.comp) |
| 966 | 967 | unlink(filename); |
| @@ -4,7 +4,6 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #include <errno.h> |
| 6 | 6 | #include <unistd.h> |
| 7 | −#include <stdio.h> | |
| 8 | 7 | #include <fcntl.h> |
| 9 | 8 | #include <string.h> |
| 10 | 9 | #include <stdlib.h> |
| @@ -86,13 +85,10 @@ int filename__read_debuglink(const char *filename __maybe_unused, · 75 unmodified lines | ||
| 86 | 85 | /* |
| 87 | 86 | * Just try PT_NOTE header otherwise fails |
| 88 | 87 | */ |
| 89 | −int filename__read_build_id(const char *filename, struct build_id *bid) | |
| 88 | +int filename__read_build_id(const char *filename, struct build_id *bid, bool block) | |
| 90 | 89 | { |
| 91 | − FILE *fp; | |
| 92 | − int ret = -1; | |
| 90 | + int fd, ret = -1; | |
| 93 | 91 | bool need_swap = false, elf32; |
| 94 | − u8 e_ident[EI_NIDENT]; | |
| 95 | − int i; | |
| 96 | 92 | union { |
| 97 | 93 | struct { |
| 98 | 94 | Elf32_Ehdr ehdr32; |
| @@ -103,28 +99,27 @@ int filename__read_build_id(const char *filename, struct build_id *bid) · 4 unmodified lines | ||
| 103 | 99 | Elf64_Phdr *phdr64; |
| 104 | 100 | }; |
| 105 | 101 | } hdrs; |
| 106 | − void *phdr; | |
| 107 | − size_t phdr_size; | |
| 108 | − void *buf = NULL; | |
| 109 | − size_t buf_size = 0; | |
| 102 | + void *phdr, *buf = NULL; | |
| 103 | + ssize_t phdr_size, ehdr_size, buf_size = 0; | |
| 110 | 104 | |
| 111 | − fp = fopen(filename, "r"); | |
| 112 | − if (fp == NULL) | |
| 105 | + fd = open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); | |
| 106 | + if (fd < 0) | |
| 113 | 107 | return -1; |
| 114 | 108 | |
| 115 | − if (fread(e_ident, sizeof(e_ident), 1, fp) != 1) | |
| 109 | + if (read(fd, hdrs.ehdr32.e_ident, EI_NIDENT) != EI_NIDENT) | |
| 116 | 110 | goto out; |
| 117 | 111 | |
| 118 | − if (memcmp(e_ident, ELFMAG, SELFMAG) || | |
| 119 | − e_ident[EI_VERSION] != EV_CURRENT) | |
| 112 | + if (memcmp(hdrs.ehdr32.e_ident, ELFMAG, SELFMAG) || | |
| 113 | + hdrs.ehdr32.e_ident[EI_VERSION] != EV_CURRENT) | |
| 120 | 114 | goto out; |
| 121 | 115 | |
| 122 | − need_swap = check_need_swap(e_ident[EI_DATA]); | |
| 123 | − elf32 = e_ident[EI_CLASS] == ELFCLASS32; | |
| 116 | + need_swap = check_need_swap(hdrs.ehdr32.e_ident[EI_DATA]); | |
| 117 | + elf32 = hdrs.ehdr32.e_ident[EI_CLASS] == ELFCLASS32; | |
| 118 | + ehdr_size = (elf32 ? sizeof(hdrs.ehdr32) : sizeof(hdrs.ehdr64)) - EI_NIDENT; | |
| 124 | 119 | |
| 125 | − if (fread(elf32 ? (void *)&hdrs.ehdr32 : (void *)&hdrs.ehdr64, | |
| 126 | − elf32 ? sizeof(hdrs.ehdr32) : sizeof(hdrs.ehdr64), | |
| 127 | − 1, fp) != 1) | |
| 120 | + if (read(fd, | |
| 121 | + (elf32 ? (void *)&hdrs.ehdr32 : (void *)&hdrs.ehdr64) + EI_NIDENT, | |
| 122 | + ehdr_size) != ehdr_size) | |
| 128 | 123 | goto out; |
| 129 | 124 | |
| 130 | 125 | if (need_swap) { |
| @@ -138,14 +133,18 @@ int filename__read_build_id(const char *filename, struct build_id *bid) · 7 unmodified lines | ||
| 138 | 133 | hdrs.ehdr64.e_phnum = bswap_16(hdrs.ehdr64.e_phnum); |
| 139 | 134 | } |
| 140 | 135 | } |
| 141 | − phdr_size = elf32 ? hdrs.ehdr32.e_phentsize * hdrs.ehdr32.e_phnum | |
| 142 | − : hdrs.ehdr64.e_phentsize * hdrs.ehdr64.e_phnum; | |
| 136 | + if ((elf32 && hdrs.ehdr32.e_phentsize != sizeof(Elf32_Phdr)) || | |
| 137 | + (!elf32 && hdrs.ehdr64.e_phentsize != sizeof(Elf64_Phdr))) | |
| 138 | + goto out; | |
| 139 | + | |
| 140 | + phdr_size = elf32 ? sizeof(Elf32_Phdr) * hdrs.ehdr32.e_phnum | |
| 141 | + : sizeof(Elf64_Phdr) * hdrs.ehdr64.e_phnum; | |
| 143 | 142 | phdr = malloc(phdr_size); |
| 144 | 143 | if (phdr == NULL) |
| 145 | 144 | goto out; |
| 146 | 145 | |
| 147 | − fseek(fp, elf32 ? hdrs.ehdr32.e_phoff : hdrs.ehdr64.e_phoff, SEEK_SET); | |
| 148 | − if (fread(phdr, phdr_size, 1, fp) != 1) | |
| 146 | + lseek(fd, elf32 ? hdrs.ehdr32.e_phoff : hdrs.ehdr64.e_phoff, SEEK_SET); | |
| 147 | + if (read(fd, phdr, phdr_size) != phdr_size) | |
| 149 | 148 | goto out_free; |
| 150 | 149 | |
| 151 | 150 | if (elf32) |
| @@ -153,8 +152,8 @@ int filename__read_build_id(const char *filename, struct build_id *bid) · 1 unmodified line | ||
| 153 | 152 | else |
| 154 | 153 | hdrs.phdr64 = phdr; |
| 155 | 154 | |
| 156 | − for (i = 0; i < elf32 ? hdrs.ehdr32.e_phnum : hdrs.ehdr64.e_phnum; i++) { | |
| 157 | − size_t p_filesz; | |
| 155 | + for (int i = 0; i < (elf32 ? hdrs.ehdr32.e_phnum : hdrs.ehdr64.e_phnum); i++) { | |
| 156 | + ssize_t p_filesz; | |
| 158 | 157 | |
| 159 | 158 | if (need_swap) { |
| 160 | 159 | if (elf32) { |
| @@ -180,8 +179,8 @@ int filename__read_build_id(const char *filename, struct build_id *bid) · 19 unmodified lines | ||
| 180 | 179 | goto out_free; |
| 181 | 180 | buf = tmp; |
| 182 | 181 | } |
| 183 | − fseek(fp, elf32 ? hdrs.phdr32[i].p_offset : hdrs.phdr64[i].p_offset, SEEK_SET); | |
| 184 | − if (fread(buf, p_filesz, 1, fp) != 1) | |
| 182 | + lseek(fd, elf32 ? hdrs.phdr32[i].p_offset : hdrs.phdr64[i].p_offset, SEEK_SET); | |
| 183 | + if (read(fd, buf, p_filesz) != p_filesz) | |
| 185 | 184 | goto out_free; |
| 186 | 185 | |
| 187 | 186 | ret = read_build_id(buf, p_filesz, bid, need_swap); |
| @@ -194,7 +193,7 @@ out_free: · 6 unmodified lines | ||
| 194 | 193 | free(buf); |
| 195 | 194 | free(phdr); |
| 196 | 195 | out: |
| 197 | − fclose(fp); | |
| 196 | + close(fd); | |
| 198 | 197 | return ret; |
| 199 | 198 | } |
| 200 | 199 | |
| @@ -324,7 +323,7 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, · 123 unmodified lines | ||
| 324 | 323 | if (ret >= 0) |
| 325 | 324 | RC_CHK_ACCESS(dso)->is_64_bit = ret; |
| 326 | 325 | |
| 327 | − if (filename__read_build_id(ss->name, &bid) > 0) | |
| 326 | + if (filename__read_build_id(ss->name, &bid, /*block=*/true) > 0) | |
| 328 | 327 | dso__set_build_id(dso, &bid); |
| 329 | 328 | return 0; |
| 330 | 329 | } |
| @@ -1869,14 +1869,14 @@ int dso__load(struct dso *dso, struct map *map) · 1868 unmodified lines | ||
| 1869 | 1869 | |
| 1870 | 1870 | /* |
| 1871 | 1871 | * Read the build id if possible. This is required for |
| 1872 | − * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work | |
| 1872 | + * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work. Don't block in case path | |
| 1873 | + * isn't for a regular file. | |
| 1873 | 1874 | */ |
| 1874 | − if (!dso__has_build_id(dso) && | |
| 1875 | − is_regular_file(dso__long_name(dso))) { | |
| 1875 | + if (!dso__has_build_id(dso)) { | |
| 1876 | 1876 | struct build_id bid = { .size = 0, }; |
| 1877 | 1877 | |
| 1878 | 1878 | __symbol__join_symfs(name, PATH_MAX, dso__long_name(dso)); |
| 1879 | − if (filename__read_build_id(name, &bid) > 0) | |
| 1879 | + if (filename__read_build_id(name, &bid, /*block=*/false) > 0) | |
| 1880 | 1880 | dso__set_build_id(dso, &bid); |
| 1881 | 1881 | } |
| 1882 | 1882 | |
| @@ -140,7 +140,7 @@ struct symbol *dso__next_symbol(struct symbol *sym); · 139 unmodified lines | ||
| 140 | 140 | |
| 141 | 141 | enum dso_type dso__type_fd(int fd); |
| 142 | 142 | |
| 143 | −int filename__read_build_id(const char *filename, struct build_id *id); | |
| 143 | +int filename__read_build_id(const char *filename, struct build_id *id, bool block); | |
| 144 | 144 | int sysfs__read_build_id(const char *filename, struct build_id *bid); |
| 145 | 145 | int modules__parse(const char *filename, void *arg, |
| 146 | 146 | int (*process_module)(void *arg, const char *name, |
| @@ -401,7 +401,7 @@ static void perf_record_mmap2__read_build_id(struct perf_record_mmap2 *event, · 400 unmodified lines | ||
| 401 | 401 | nsi = nsinfo__new(event->pid); |
| 402 | 402 | nsinfo__mountns_enter(nsi, &nc); |
| 403 | 403 | |
| 404 | − rc = filename__read_build_id(event->filename, &bid) > 0 ? 0 : -1; | |
| 404 | + rc = filename__read_build_id(event->filename, &bid, /*block=*/false) > 0 ? 0 : -1; | |
| 405 | 405 | |
| 406 | 406 | nsinfo__mountns_exit(&nc); |
| 407 | 407 | nsinfo__put(nsi); |
| @@ -81,10 +81,11 @@ Refer to the AMD P-State kernel documentation for further information. · 80 unmodified lines | ||
| 81 | 81 | .RE |
| 82 | 82 | |
| 83 | 83 | .PP |
| 84 | −\-\-turbo\-boost, \-t | |
| 84 | +\-\-turbo\-boost, \-\-boost, \-t | |
| 85 | 85 | .RS 4 |
| 86 | −This option is used to enable or disable the turbo boost feature on | |
| 87 | −supported Intel and AMD processors. | |
| 86 | +This option is used to enable or disable the boost feature on | |
| 87 | +supported Intel and AMD processors, and other boost supported systems. | |
| 88 | +(The --boost option is an alias for the --turbo-boost option) | |
| 88 | 89 | |
| 89 | 90 | This option takes as parameter either \fB1\fP to enable, or \fB0\fP to disable the feature. |
| 90 | 91 | |
| @@ -128,7 +128,7 @@ static int get_boost_mode_x86(unsigned int cpu) · 127 unmodified lines | ||
| 128 | 128 | /* ToDo: Make this more global */ |
| 129 | 129 | unsigned long pstates[MAX_HW_PSTATES] = {0,}; |
| 130 | 130 | |
| 131 | − ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states); | |
| 131 | + ret = cpufreq_has_x86_boost_support(cpu, &support, &active, &b_states); | |
| 132 | 132 | if (ret) { |
| 133 | 133 | printf(_("Error while evaluating Boost Capabilities" |
| 134 | 134 | " on CPU %d -- are you root?\n"), cpu); |
| @@ -204,6 +204,18 @@ static int get_boost_mode_x86(unsigned int cpu) · 69 unmodified lines | ||
| 204 | 204 | return 0; |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | +static int get_boost_mode_generic(unsigned int cpu) | |
| 208 | +{ | |
| 209 | + bool active; | |
| 210 | + | |
| 211 | + if (!cpufreq_has_generic_boost_support(&active)) { | |
| 212 | + printf(_(" boost state support:\n")); | |
| 213 | + printf(_(" Active: %s\n"), active ? _("yes") : _("no")); | |
| 214 | + } | |
| 215 | + | |
| 216 | + return 0; | |
| 217 | +} | |
| 218 | + | |
| 207 | 219 | /* --boost / -b */ |
| 208 | 220 | |
| 209 | 221 | static int get_boost_mode(unsigned int cpu) |
| @@ -214,6 +226,8 @@ static int get_boost_mode(unsigned int cpu) · 4 unmodified lines | ||
| 214 | 226 | cpupower_cpu_info.vendor == X86_VENDOR_HYGON || |
| 215 | 227 | cpupower_cpu_info.vendor == X86_VENDOR_INTEL) |
| 216 | 228 | return get_boost_mode_x86(cpu); |
| 229 | + else | |
| 230 | + get_boost_mode_generic(cpu); | |
| 217 | 231 | |
| 218 | 232 | freqs = cpufreq_get_boost_frequencies(cpu); |
| 219 | 233 | if (freqs) { |
| @@ -21,6 +21,7 @@ static struct option set_opts[] = { · 20 unmodified lines | ||
| 21 | 21 | {"epp", required_argument, NULL, 'e'}, |
| 22 | 22 | {"amd-pstate-mode", required_argument, NULL, 'm'}, |
| 23 | 23 | {"turbo-boost", required_argument, NULL, 't'}, |
| 24 | + {"boost", required_argument, NULL, 't'}, | |
| 24 | 25 | { }, |
| 25 | 26 | }; |
| 26 | 27 | |
| @@ -62,8 +63,8 @@ int cmd_set(int argc, char **argv) · 35 unmodified lines | ||
| 62 | 63 | |
| 63 | 64 | params.params = 0; |
| 64 | 65 | /* parameter parsing */ |
| 65 | − while ((ret = getopt_long(argc, argv, "b:e:m:", | |
| 66 | − set_opts, NULL)) != -1) { | |
| 66 | + while ((ret = getopt_long(argc, argv, "b:e:m:t:", | |
| 67 | + set_opts, NULL)) != -1) { | |
| 67 | 68 | switch (ret) { |
| 68 | 69 | case 'b': |
| 69 | 70 | if (params.perf_bias) |
| @@ -103,6 +103,9 @@ extern struct cpupower_cpu_info cpupower_cpu_info; · 102 unmodified lines | ||
| 103 | 103 | |
| 104 | 104 | /* cpuid and cpuinfo helpers **************************/ |
| 105 | 105 | |
| 106 | +int cpufreq_has_generic_boost_support(bool *active); | |
| 107 | +int cpupower_set_turbo_boost(int turbo_boost); | |
| 108 | + | |
| 106 | 109 | /* X86 ONLY ****************************************/ |
| 107 | 110 | #if defined(__i386__) || defined(__x86_64__) |
| 108 | 111 | |
| @@ -118,7 +121,6 @@ extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu); · 9 unmodified lines | ||
| 118 | 121 | |
| 119 | 122 | extern int cpupower_set_epp(unsigned int cpu, char *epp); |
| 120 | 123 | extern int cpupower_set_amd_pstate_mode(char *mode); |
| 121 | −extern int cpupower_set_turbo_boost(int turbo_boost); | |
| 122 | 124 | |
| 123 | 125 | /* Read/Write msr ****************************/ |
| 124 | 126 | |
| @@ -139,8 +141,8 @@ extern int decode_pstates(unsigned int cpu, int boost_states, · 14 unmodified lines | ||
| 139 | 141 | |
| 140 | 142 | /* AMD HW pstate decoding **************************/ |
| 141 | 143 | |
| 142 | −extern int cpufreq_has_boost_support(unsigned int cpu, int *support, | |
| 143 | − int *active, int * states); | |
| 144 | +int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, | |
| 145 | + int *active, int *states); | |
| 144 | 146 | |
| 145 | 147 | /* AMD P-State stuff **************************/ |
| 146 | 148 | bool cpupower_amd_pstate_enabled(void); |
| @@ -181,13 +183,11 @@ static inline int cpupower_set_epp(unsigned int cpu, char *epp) · 34 unmodified lines | ||
| 181 | 183 | { return -1; }; |
| 182 | 184 | static inline int cpupower_set_amd_pstate_mode(char *mode) |
| 183 | 185 | { return -1; }; |
| 184 | −static inline int cpupower_set_turbo_boost(int turbo_boost) | |
| 185 | −{ return -1; }; | |
| 186 | 186 | |
| 187 | 187 | /* Read/Write msr ****************************/ |
| 188 | 188 | |
| 189 | −static inline int cpufreq_has_boost_support(unsigned int cpu, int *support, | |
| 190 | − int *active, int * states) | |
| 189 | +static inline int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, | |
| 190 | + int *active, int *states) | |
| 191 | 191 | { return -1; } |
| 192 | 192 | |
| 193 | 193 | static inline bool cpupower_amd_pstate_enabled(void) |
| @@ -8,15 +8,14 @@ · 7 unmodified lines | ||
| 8 | 8 | #include "helpers/helpers.h" |
| 9 | 9 | #include "helpers/sysfs.h" |
| 10 | 10 | #include "cpufreq.h" |
| 11 | +#include "cpupower_intern.h" | |
| 11 | 12 | |
| 12 | 13 | #if defined(__i386__) || defined(__x86_64__) |
| 13 | 14 | |
| 14 | −#include "cpupower_intern.h" | |
| 15 | − | |
| 16 | 15 | #define MSR_AMD_HWCR 0xc0010015 |
| 17 | 16 | |
| 18 | −int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, | |
| 19 | − int *states) | |
| 17 | +int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, int *active, | |
| 18 | + int *states) | |
| 20 | 19 | { |
| 21 | 20 | int ret; |
| 22 | 21 | unsigned long long val; |
| @@ -124,24 +123,6 @@ int cpupower_set_amd_pstate_mode(char *mode) · 101 unmodified lines | ||
| 124 | 123 | return 0; |
| 125 | 124 | } |
| 126 | 125 | |
| 127 | −int cpupower_set_turbo_boost(int turbo_boost) | |
| 128 | −{ | |
| 129 | − char path[SYSFS_PATH_MAX]; | |
| 130 | − char linebuf[2] = {}; | |
| 131 | − | |
| 132 | − snprintf(path, sizeof(path), PATH_TO_CPU "cpufreq/boost"); | |
| 133 | − | |
| 134 | − if (!is_valid_path(path)) | |
| 135 | − return -1; | |
| 136 | − | |
| 137 | − snprintf(linebuf, sizeof(linebuf), "%d", turbo_boost); | |
| 138 | − | |
| 139 | − if (cpupower_write_sysfs(path, linebuf, 2) <= 0) | |
| 140 | − return -1; | |
| 141 | − | |
| 142 | − return 0; | |
| 143 | −} | |
| 144 | − | |
| 145 | 126 | bool cpupower_amd_pstate_enabled(void) |
| 146 | 127 | { |
| 147 | 128 | char *driver = cpufreq_get_driver(0); |
| @@ -160,6 +141,39 @@ bool cpupower_amd_pstate_enabled(void) · 12 unmodified lines | ||
| 160 | 141 | |
| 161 | 142 | #endif /* #if defined(__i386__) || defined(__x86_64__) */ |
| 162 | 143 | |
| 144 | +int cpufreq_has_generic_boost_support(bool *active) | |
| 145 | +{ | |
| 146 | + char path[SYSFS_PATH_MAX]; | |
| 147 | + char linebuf[2] = {}; | |
| 148 | + unsigned long val; | |
| 149 | + char *endp; | |
| 150 | + | |
| 151 | + snprintf(path, sizeof(path), PATH_TO_CPU "cpufreq/boost"); | |
| 152 | + | |
| 153 | + if (!is_valid_path(path)) | |
| 154 | + return -EACCES; | |
| 155 | + | |
| 156 | + if (cpupower_read_sysfs(path, linebuf, 2) <= 0) | |
| 157 | + return -EINVAL; | |
| 158 | + | |
| 159 | + val = strtoul(linebuf, &endp, 0); | |
| 160 | + if (endp == linebuf || errno == ERANGE) | |
| 161 | + return -EINVAL; | |
| 162 | + | |
| 163 | + switch (val) { | |
| 164 | + case 0: | |
| 165 | + *active = false; | |
| 166 | + break; | |
| 167 | + case 1: | |
| 168 | + *active = true; | |
| 169 | + break; | |
| 170 | + default: | |
| 171 | + return -EINVAL; | |
| 172 | + } | |
| 173 | + | |
| 174 | + return 0; | |
| 175 | +} | |
| 176 | + | |
| 163 | 177 | /* get_cpustate |
| 164 | 178 | * |
| 165 | 179 | * Gather the information of all online CPUs into bitmask struct |
| @@ -259,3 +273,21 @@ void print_speed(unsigned long speed, int no_rounding) · 93 unmodified lines | ||
| 259 | 273 | } |
| 260 | 274 | } |
| 261 | 275 | } |
| 276 | + | |
| 277 | +int cpupower_set_turbo_boost(int turbo_boost) | |
| 278 | +{ | |
| 279 | + char path[SYSFS_PATH_MAX]; | |
| 280 | + char linebuf[2] = {}; | |
| 281 | + | |
| 282 | + snprintf(path, sizeof(path), PATH_TO_CPU "cpufreq/boost"); | |
| 283 | + | |
| 284 | + if (!is_valid_path(path)) | |
| 285 | + return -1; | |
| 286 | + | |
| 287 | + snprintf(linebuf, sizeof(linebuf), "%d", turbo_boost); | |
| 288 | + | |
| 289 | + if (cpupower_write_sysfs(path, linebuf, 2) <= 0) | |
| 290 | + return -1; | |
| 291 | + | |
| 292 | + return 0; | |
| 293 | +} | |
| @@ -408,3 +408,5 @@ · 407 unmodified lines | ||
| 408 | 408 | 465 common listxattrat sys_listxattrat |
| 409 | 409 | 466 common removexattrat sys_removexattrat |
| 410 | 410 | 467 common open_tree_attr sys_open_tree_attr |
| 411 | +468 common file_getattr sys_file_getattr | |
| 412 | +469 common file_setattr sys_file_setattr | |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | TEST_GEN_FILES += access_memory access_memory_even |
| 5 | 5 | |
| 6 | 6 | TEST_FILES = _damon_sysfs.py |
| 7 | +TEST_FILES += drgn_dump_damon_status.py | |
| 7 | 8 | |
| 8 | 9 | # functionality tests |
| 9 | 10 | TEST_PROGS += sysfs.sh |
| @@ -5,10 +5,14 @@ · 4 unmodified lines | ||
| 5 | 5 | #define _GNU_SOURCE |
| 6 | 6 | |
| 7 | 7 | #include <errno.h> |
| 8 | +#include <fcntl.h> | |
| 9 | +#include <linux/userfaultfd.h> | |
| 8 | 10 | #include <stdlib.h> |
| 9 | 11 | #include <stdio.h> |
| 10 | 12 | #include <string.h> |
| 13 | +#include <sys/ioctl.h> | |
| 11 | 14 | #include <sys/mman.h> |
| 15 | +#include <syscall.h> | |
| 12 | 16 | #include <time.h> |
| 13 | 17 | #include <stdbool.h> |
| 14 | 18 | |
| @@ -168,6 +172,7 @@ static bool is_range_mapped(FILE *maps_fp, unsigned long start, · 153 unmodified lines | ||
| 168 | 172 | |
| 169 | 173 | if (first_val <= start && second_val >= end) { |
| 170 | 174 | success = true; |
| 175 | + fflush(maps_fp); | |
| 171 | 176 | break; |
| 172 | 177 | } |
| 173 | 178 | } |
| @@ -175,6 +180,15 @@ static bool is_range_mapped(FILE *maps_fp, unsigned long start, · 1 unmodified line | ||
| 175 | 180 | return success; |
| 176 | 181 | } |
| 177 | 182 | |
| 183 | +/* Check if [ptr, ptr + size) mapped in /proc/self/maps. */ | |
| 184 | +static bool is_ptr_mapped(FILE *maps_fp, void *ptr, unsigned long size) | |
| 185 | +{ | |
| 186 | + unsigned long start = (unsigned long)ptr; | |
| 187 | + unsigned long end = start + size; | |
| 188 | + | |
| 189 | + return is_range_mapped(maps_fp, start, end); | |
| 190 | +} | |
| 191 | + | |
| 178 | 192 | /* |
| 179 | 193 | * Returns the start address of the mapping on success, else returns |
| 180 | 194 | * NULL on failure. |
| @@ -733,6 +747,249 @@ out: · 552 unmodified lines | ||
| 733 | 747 | dont_unmap ? " [dontunnmap]" : ""); |
| 734 | 748 | } |
| 735 | 749 | |
| 750 | +#ifdef __NR_userfaultfd | |
| 751 | +static void mremap_move_multi_invalid_vmas(FILE *maps_fp, | |
| 752 | + unsigned long page_size) | |
| 753 | +{ | |
| 754 | + char *test_name = "mremap move multiple invalid vmas"; | |
| 755 | + const size_t size = 10 * page_size; | |
| 756 | + bool success = true; | |
| 757 | + char *ptr, *tgt_ptr; | |
| 758 | + int uffd, err, i; | |
| 759 | + void *res; | |
| 760 | + struct uffdio_api api = { | |
| 761 | + .api = UFFD_API, | |
| 762 | + .features = UFFD_EVENT_PAGEFAULT, | |
| 763 | + }; | |
| 764 | + | |
| 765 | + uffd = syscall(__NR_userfaultfd, O_NONBLOCK); | |
| 766 | + if (uffd == -1) { | |
| 767 | + err = errno; | |
| 768 | + perror("userfaultfd"); | |
| 769 | + if (err == EPERM) { | |
| 770 | + ksft_test_result_skip("%s - missing uffd", test_name); | |
| 771 | + return; | |
| 772 | + } | |
| 773 | + success = false; | |
| 774 | + goto out; | |
| 775 | + } | |
| 776 | + if (ioctl(uffd, UFFDIO_API, &api)) { | |
| 777 | + perror("ioctl UFFDIO_API"); | |
| 778 | + success = false; | |
| 779 | + goto out_close_uffd; | |
| 780 | + } | |
| 781 | + | |
| 782 | + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, | |
| 783 | + MAP_PRIVATE | MAP_ANON, -1, 0); | |
| 784 | + if (ptr == MAP_FAILED) { | |
| 785 | + perror("mmap"); | |
| 786 | + success = false; | |
| 787 | + goto out_close_uffd; | |
| 788 | + } | |
| 789 | + | |
| 790 | + tgt_ptr = mmap(NULL, size, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); | |
| 791 | + if (tgt_ptr == MAP_FAILED) { | |
| 792 | + perror("mmap"); | |
| 793 | + success = false; | |
| 794 | + goto out_close_uffd; | |
| 795 | + } | |
| 796 | + if (munmap(tgt_ptr, size)) { | |
| 797 | + perror("munmap"); | |
| 798 | + success = false; | |
| 799 | + goto out_unmap; | |
| 800 | + } | |
| 801 | + | |
| 802 | + /* | |
| 803 | + * Unmap so we end up with: | |
| 804 | + * | |
| 805 | + * 0 2 4 6 8 10 offset in buffer | |
| 806 | + * |*| |*| |*| |*| |*| | |
| 807 | + * |*| |*| |*| |*| |*| | |
| 808 | + * | |
| 809 | + * Additionally, register each with UFFD. | |
| 810 | + */ | |
| 811 | + for (i = 0; i < 10; i += 2) { | |
| 812 | + void *unmap_ptr = &ptr[(i + 1) * page_size]; | |
| 813 | + unsigned long start = (unsigned long)&ptr[i * page_size]; | |
| 814 | + struct uffdio_register reg = { | |
| 815 | + .range = { | |
| 816 | + .start = start, | |
| 817 | + .len = page_size, | |
| 818 | + }, | |
| 819 | + .mode = UFFDIO_REGISTER_MODE_MISSING, | |
| 820 | + }; | |
| 821 | + | |
| 822 | + if (ioctl(uffd, UFFDIO_REGISTER, ®) == -1) { | |
| 823 | + perror("ioctl UFFDIO_REGISTER"); | |
| 824 | + success = false; | |
| 825 | + goto out_unmap; | |
| 826 | + } | |
| 827 | + if (munmap(unmap_ptr, page_size)) { | |
| 828 | + perror("munmap"); | |
| 829 | + success = false; | |
| 830 | + goto out_unmap; | |
| 831 | + } | |
| 832 | + } | |
| 833 | + | |
| 834 | + /* | |
| 835 | + * Now try to move the entire range which is invalid for multi VMA move. | |
| 836 | + * | |
| 837 | + * This will fail, and no VMA should be moved, as we check this ahead of | |
| 838 | + * time. | |
| 839 | + */ | |
| 840 | + res = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr); | |
| 841 | + err = errno; | |
| 842 | + if (res != MAP_FAILED) { | |
| 843 | + fprintf(stderr, "mremap() succeeded for multi VMA uffd armed\n"); | |
| 844 | + success = false; | |
| 845 | + goto out_unmap; | |
| 846 | + } | |
| 847 | + if (err != EFAULT) { | |
| 848 | + errno = err; | |
| 849 | + perror("mrmeap() unexpected error"); | |
| 850 | + success = false; | |
| 851 | + goto out_unmap; | |
| 852 | + } | |
| 853 | + if (is_ptr_mapped(maps_fp, tgt_ptr, page_size)) { | |
| 854 | + fprintf(stderr, | |
| 855 | + "Invalid uffd-armed VMA at start of multi range moved\n"); | |
| 856 | + success = false; | |
| 857 | + goto out_unmap; | |
| 858 | + } | |
| 859 | + | |
| 860 | + /* | |
| 861 | + * Now try to move a single VMA, this should succeed as not multi VMA | |
| 862 | + * move. | |
| 863 | + */ | |
| 864 | + res = mremap(ptr, page_size, page_size, | |
| 865 | + MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr); | |
| 866 | + if (res == MAP_FAILED) { | |
| 867 | + perror("mremap single invalid-multi VMA"); | |
| 868 | + success = false; | |
| 869 | + goto out_unmap; | |
| 870 | + } | |
| 871 | + | |
| 872 | + /* | |
| 873 | + * Unmap the VMA, and remap a non-uffd registered (therefore, multi VMA | |
| 874 | + * move valid) VMA at the start of ptr range. | |
| 875 | + */ | |
| 876 | + if (munmap(tgt_ptr, page_size)) { | |
| 877 | + perror("munmap"); | |
| 878 | + success = false; | |
| 879 | + goto out_unmap; | |
| 880 | + } | |
| 881 | + res = mmap(ptr, page_size, PROT_READ | PROT_WRITE, | |
| 882 | + MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); | |
| 883 | + if (res == MAP_FAILED) { | |
| 884 | + perror("mmap"); | |
| 885 | + success = false; | |
| 886 | + goto out_unmap; | |
| 887 | + } | |
| 888 | + | |
| 889 | + /* | |
| 890 | + * Now try to move the entire range, we should succeed in moving the | |
| 891 | + * first VMA, but no others, and report a failure. | |
| 892 | + */ | |
| 893 | + res = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr); | |
| 894 | + err = errno; | |
| 895 | + if (res != MAP_FAILED) { | |
| 896 | + fprintf(stderr, "mremap() succeeded for multi VMA uffd armed\n"); | |
| 897 | + success = false; | |
| 898 | + goto out_unmap; | |
| 899 | + } | |
| 900 | + if (err != EFAULT) { | |
| 901 | + errno = err; | |
| 902 | + perror("mrmeap() unexpected error"); | |
| 903 | + success = false; | |
| 904 | + goto out_unmap; | |
| 905 | + } | |
| 906 | + if (!is_ptr_mapped(maps_fp, tgt_ptr, page_size)) { | |
| 907 | + fprintf(stderr, "Valid VMA not moved\n"); | |
| 908 | + success = false; | |
| 909 | + goto out_unmap; | |
| 910 | + } | |
| 911 | + | |
| 912 | + /* | |
| 913 | + * Unmap the VMA, and map valid VMA at start of ptr range, and replace | |
| 914 | + * all existing multi-move invalid VMAs, except the last, with valid | |
| 915 | + * multi-move VMAs. | |
| 916 | + */ | |
| 917 | + if (munmap(tgt_ptr, page_size)) { | |
| 918 | + perror("munmap"); | |
| 919 | + success = false; | |
| 920 | + goto out_unmap; | |
| 921 | + } | |
| 922 | + if (munmap(ptr, size - 2 * page_size)) { | |
| 923 | + perror("munmap"); | |
| 924 | + success = false; | |
| 925 | + goto out_unmap; | |
| 926 | + } | |
| 927 | + for (i = 0; i < 8; i += 2) { | |
| 928 | + res = mmap(&ptr[i * page_size], page_size, | |
| 929 | + PROT_READ | PROT_WRITE, | |
| 930 | + MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); | |
| 931 | + if (res == MAP_FAILED) { | |
| 932 | + perror("mmap"); | |
| 933 | + success = false; | |
| 934 | + goto out_unmap; | |
| 935 | + } | |
| 936 | + } | |
| 937 | + | |
| 938 | + /* | |
| 939 | + * Now try to move the entire range, we should succeed in moving all but | |
| 940 | + * the last VMA, and report a failure. | |
| 941 | + */ | |
| 942 | + res = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr); | |
| 943 | + err = errno; | |
| 944 | + if (res != MAP_FAILED) { | |
| 945 | + fprintf(stderr, "mremap() succeeded for multi VMA uffd armed\n"); | |
| 946 | + success = false; | |
| 947 | + goto out_unmap; | |
| 948 | + } | |
| 949 | + if (err != EFAULT) { | |
| 950 | + errno = err; | |
| 951 | + perror("mrmeap() unexpected error"); | |
| 952 | + success = false; | |
| 953 | + goto out_unmap; | |
| 954 | + } | |
| 955 | + | |
| 956 | + for (i = 0; i < 10; i += 2) { | |
| 957 | + bool is_mapped = is_ptr_mapped(maps_fp, | |
| 958 | + &tgt_ptr[i * page_size], page_size); | |
| 959 | + | |
| 960 | + if (i < 8 && !is_mapped) { | |
| 961 | + fprintf(stderr, "Valid VMA not moved at %d\n", i); | |
| 962 | + success = false; | |
| 963 | + goto out_unmap; | |
| 964 | + } else if (i == 8 && is_mapped) { | |
| 965 | + fprintf(stderr, "Invalid VMA moved at %d\n", i); | |
| 966 | + success = false; | |
| 967 | + goto out_unmap; | |
| 968 | + } | |
| 969 | + } | |
| 970 | + | |
| 971 | +out_unmap: | |
| 972 | + if (munmap(tgt_ptr, size)) | |
| 973 | + perror("munmap tgt"); | |
| 974 | + if (munmap(ptr, size)) | |
| 975 | + perror("munmap src"); | |
| 976 | +out_close_uffd: | |
| 977 | + close(uffd); | |
| 978 | +out: | |
| 979 | + if (success) | |
| 980 | + ksft_test_result_pass("%s\n", test_name); | |
| 981 | + else | |
| 982 | + ksft_test_result_fail("%s\n", test_name); | |
| 983 | +} | |
| 984 | +#else | |
| 985 | +static void mremap_move_multi_invalid_vmas(FILE *maps_fp, unsigned long page_size) | |
| 986 | +{ | |
| 987 | + char *test_name = "mremap move multiple invalid vmas"; | |
| 988 | + | |
| 989 | + ksft_test_result_skip("%s - missing uffd", test_name); | |
| 990 | +} | |
| 991 | +#endif /* __NR_userfaultfd */ | |
| 992 | + | |
| 736 | 993 | /* Returns the time taken for the remap on success else returns -1. */ |
| 737 | 994 | static long long remap_region(struct config c, unsigned int threshold_mb, |
| 738 | 995 | char *rand_addr) |
| @@ -1074,7 +1331,7 @@ int main(int argc, char **argv) · 335 unmodified lines | ||
| 1074 | 1331 | char *rand_addr; |
| 1075 | 1332 | size_t rand_size; |
| 1076 | 1333 | int num_expand_tests = 2; |
| 1077 | − int num_misc_tests = 8; | |
| 1334 | + int num_misc_tests = 9; | |
| 1078 | 1335 | struct test test_cases[MAX_TEST] = {}; |
| 1079 | 1336 | struct test perf_test_cases[MAX_PERF_TEST]; |
| 1080 | 1337 | int page_size; |
| @@ -1197,8 +1454,6 @@ int main(int argc, char **argv) · 116 unmodified lines | ||
| 1197 | 1454 | mremap_expand_merge(maps_fp, page_size); |
| 1198 | 1455 | mremap_expand_merge_offset(maps_fp, page_size); |
| 1199 | 1456 | |
| 1200 | − fclose(maps_fp); | |
| 1201 | − | |
| 1202 | 1457 | mremap_move_within_range(pattern_seed, rand_addr); |
| 1203 | 1458 | mremap_move_1mb_from_start(pattern_seed, rand_addr); |
| 1204 | 1459 | mremap_shrink_multiple_vmas(page_size, /* inplace= */true); |
| @@ -1207,6 +1462,9 @@ int main(int argc, char **argv) · 2 unmodified lines | ||
| 1207 | 1462 | mremap_move_multiple_vmas(pattern_seed, page_size, /* dontunmap= */ true); |
| 1208 | 1463 | mremap_move_multiple_vmas_split(pattern_seed, page_size, /* dontunmap= */ false); |
| 1209 | 1464 | mremap_move_multiple_vmas_split(pattern_seed, page_size, /* dontunmap= */ true); |
| 1465 | + mremap_move_multi_invalid_vmas(maps_fp, page_size); | |
| 1466 | + | |
| 1467 | + fclose(maps_fp); | |
| 1210 | 1468 | |
| 1211 | 1469 | if (run_perf_tests) { |
| 1212 | 1470 | ksft_print_msg("\n%s\n", |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <bpf/bpf.h> |
| 7 | 7 | #include <sched.h> |
| 8 | 8 | #include <scx/common.h> |
| 9 | −#include <sched.h> | |
| 10 | 9 | #include <sys/wait.h> |
| 11 | 10 | #include <unistd.h> |
| 12 | 11 | |
| @@ -1400,7 +1400,7 @@ static int cmd_dev_get_features(void) · 1399 unmodified lines | ||
| 1400 | 1400 | |
| 1401 | 1401 | if (!((1ULL << i) & features)) |
| 1402 | 1402 | continue; |
| 1403 | − if (i < sizeof(feat_map) / sizeof(feat_map[0])) | |
| 1403 | + if (i < ARRAY_SIZE(feat_map)) | |
| 1404 | 1404 | feat = feat_map[i]; |
| 1405 | 1405 | else |
| 1406 | 1406 | feat = "unknown"; |
| @@ -1477,7 +1477,7 @@ static void __cmd_create_help(char *exe, bool recovery) · 70 unmodified lines | ||
| 1477 | 1477 | printf("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n"); |
| 1478 | 1478 | printf("\tdefault: nthreads=nr_queues"); |
| 1479 | 1479 | |
| 1480 | − for (i = 0; i < sizeof(tgt_ops_list) / sizeof(tgt_ops_list[0]); i++) { | |
| 1480 | + for (i = 0; i < ARRAY_SIZE(tgt_ops_list); i++) { | |
| 1481 | 1481 | const struct ublk_tgt_ops *ops = tgt_ops_list[i]; |
| 1482 | 1482 | |
| 1483 | 1483 | if (ops->usage) |
| @@ -1 +1,5 @@ | ||
| 1 | +/* Avoid duplicate definitions due to system headers. */ | |
| 2 | +#ifdef __CONCAT | |
| 3 | +#undef __CONCAT | |
| 4 | +#endif | |
| 1 | 5 | #include "../../../../include/linux/idr.h" |
| @@ -1,7 +1,15 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | 2 | |
| 3 | +include $(srctree)/tools/scripts/utilities.mak | |
| 4 | + | |
| 3 | 5 | STOP_ERROR := |
| 4 | 6 | |
| 7 | +ifndef ($(NO_LIBTRACEEVENT),1) | |
| 8 | + ifeq ($(call get-executable,$(PKG_CONFIG)),) | |
| 9 | + $(error Error: $(PKG_CONFIG) needed by libtraceevent/libtracefs is missing on this system, please install it) | |
| 10 | + endif | |
| 11 | +endif | |
| 12 | + | |
| 5 | 13 | define lib_setup |
| 6 | 14 | $(eval LIB_INCLUDES += $(shell sh -c "$(PKG_CONFIG) --cflags lib$(1)")) |
| 7 | 15 | $(eval LDFLAGS += $(shell sh -c "$(PKG_CONFIG) --libs-only-L lib$(1)")) |
| @@ -1,10 +1,18 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | 2 | |
| 3 | +include $(srctree)/tools/scripts/utilities.mak | |
| 4 | + | |
| 3 | 5 | STOP_ERROR := |
| 4 | 6 | |
| 5 | 7 | LIBTRACEEVENT_MIN_VERSION = 1.5 |
| 6 | 8 | LIBTRACEFS_MIN_VERSION = 1.6 |
| 7 | 9 | |
| 10 | +ifndef ($(NO_LIBTRACEEVENT),1) | |
| 11 | + ifeq ($(call get-executable,$(PKG_CONFIG)),) | |
| 12 | + $(error Error: $(PKG_CONFIG) needed by libtraceevent/libtracefs is missing on this system, please install it) | |
| 13 | + endif | |
| 14 | +endif | |
| 15 | + | |
| 8 | 16 | define lib_setup |
| 9 | 17 | $(eval LIB_INCLUDES += $(shell sh -c "$(PKG_CONFIG) --cflags lib$(1)")) |
| 10 | 18 | $(eval LDFLAGS += $(shell sh -c "$(PKG_CONFIG) --libs-only-L lib$(1)")) |