No conflicts.
Unified · Split
| @@ -100,6 +100,8 @@ stable kernels. · 99 unmodified lines | ||
| 100 | 100 | +----------------+-----------------+-----------------+-----------------------------+ |
| 101 | 101 | | ARM | Cortex-A510 | #2051678 | ARM64_ERRATUM_2051678 | |
| 102 | 102 | +----------------+-----------------+-----------------+-----------------------------+ |
| 103 | +| ARM | Cortex-A510 | #2077057 | ARM64_ERRATUM_2077057 | | |
| 104 | ++----------------+-----------------+-----------------+-----------------------------+ | |
| 103 | 105 | | ARM | Cortex-A710 | #2119858 | ARM64_ERRATUM_2119858 | |
| 104 | 106 | +----------------+-----------------+-----------------+-----------------------------+ |
| 105 | 107 | | ARM | Cortex-A710 | #2054223 | ARM64_ERRATUM_2054223 | |
| @@ -242,7 +242,7 @@ example: · 241 unmodified lines | ||
| 242 | 242 | |
| 243 | 243 | int rectangle_area(struct shape *this) |
| 244 | 244 | { |
| 245 | − struct rectangle *self = container_of(this, struct shape, parent); | |
| 245 | + struct rectangle *self = container_of(this, struct rectangle, parent); | |
| 246 | 246 | |
| 247 | 247 | return self->length * self->width; |
| 248 | 248 | }; |
| @@ -462,6 +462,10 @@ operation table looks like the following:: · 461 unmodified lines | ||
| 462 | 462 | struct iov_iter *iter, |
| 463 | 463 | netfs_io_terminated_t term_func, |
| 464 | 464 | void *term_func_priv); |
| 465 | + | |
| 466 | + int (*query_occupancy)(struct netfs_cache_resources *cres, | |
| 467 | + loff_t start, size_t len, size_t granularity, | |
| 468 | + loff_t *_data_start, size_t *_data_len); | |
| 465 | 469 | }; |
| 466 | 470 | |
| 467 | 471 | With a termination handler function pointer:: |
| @@ -536,6 +540,18 @@ The methods defined in the table are: · 68 unmodified lines | ||
| 536 | 540 | indicating whether the termination is definitely happening in the caller's |
| 537 | 541 | context. |
| 538 | 542 | |
| 543 | + * ``query_occupancy()`` | |
| 544 | + | |
| 545 | + [Required] Called to find out where the next piece of data is within a | |
| 546 | + particular region of the cache. The start and length of the region to be | |
| 547 | + queried are passed in, along with the granularity to which the answer needs | |
| 548 | + to be aligned. The function passes back the start and length of the data, | |
| 549 | + if any, available within that region. Note that there may be a hole at the | |
| 550 | + front. | |
| 551 | + | |
| 552 | + It returns 0 if some data was found, -ENODATA if there was no usable data | |
| 553 | + within the region or -ENOBUFS if there is no caching on this file. | |
| 554 | + | |
| 539 | 555 | Note that these methods are passed a pointer to the cache resource structure, |
| 540 | 556 | not the read request structure as they could be used in other situations where |
| 541 | 557 | there isn't a read request structure as well, such as writing dirty data to the |
| @@ -300,30 +300,6 @@ Contact: Daniel Vetter, Noralf Tronnes · 299 unmodified lines | ||
| 300 | 300 | |
| 301 | 301 | Level: Advanced |
| 302 | 302 | |
| 303 | −Garbage collect fbdev scrolling acceleration | |
| 304 | −-------------------------------------------- | |
| 305 | − | |
| 306 | −Scroll acceleration has been disabled in fbcon. Now it works as the old | |
| 307 | −SCROLL_REDRAW mode. A ton of code was removed in fbcon.c and the hook bmove was | |
| 308 | −removed from fbcon_ops. | |
| 309 | −Remaining tasks: | |
| 310 | − | |
| 311 | −- a bunch of the hooks in fbcon_ops could be removed or simplified by calling | |
| 312 | − directly instead of the function table (with a switch on p->rotate) | |
| 313 | − | |
| 314 | −- fb_copyarea is unused after this, and can be deleted from all drivers | |
| 315 | − | |
| 316 | −- after that, fb_copyarea can be deleted from fb_ops in include/linux/fb.h as | |
| 317 | − well as cfb_copyarea | |
| 318 | − | |
| 319 | −Note that not all acceleration code can be deleted, since clearing and cursor | |
| 320 | −support is still accelerated, which might be good candidates for further | |
| 321 | −deletion projects. | |
| 322 | − | |
| 323 | −Contact: Daniel Vetter | |
| 324 | − | |
| 325 | −Level: Intermediate | |
| 326 | − | |
| 327 | 303 | idr_init_base() |
| 328 | 304 | --------------- |
| 329 | 305 | |
| @@ -115,6 +115,7 @@ Code Seq# Include File Comments · 114 unmodified lines | ||
| 115 | 115 | 'B' 00-1F linux/cciss_ioctl.h conflict! |
| 116 | 116 | 'B' 00-0F include/linux/pmu.h conflict! |
| 117 | 117 | 'B' C0-FF advanced bbus <mailto:maassen@uni-freiburg.de> |
| 118 | +'B' 00-0F xen/xenbus_dev.h conflict! | |
| 118 | 119 | 'C' all linux/soundcard.h conflict! |
| 119 | 120 | 'C' 01-2F linux/capi.h conflict! |
| 120 | 121 | 'C' F0-FF drivers/net/wan/cosa.h conflict! |
| @@ -134,6 +135,7 @@ Code Seq# Include File Comments · 13 unmodified lines | ||
| 134 | 135 | 'F' 80-8F linux/arcfb.h conflict! |
| 135 | 136 | 'F' DD video/sstfb.h conflict! |
| 136 | 137 | 'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict! |
| 138 | +'G' 00-0F xen/gntalloc.h, xen/gntdev.h conflict! | |
| 137 | 139 | 'H' 00-7F linux/hiddev.h conflict! |
| 138 | 140 | 'H' 00-0F linux/hidraw.h conflict! |
| 139 | 141 | 'H' 01 linux/mei.h conflict! |
| @@ -176,6 +178,7 @@ Code Seq# Include File Comments · 36 unmodified lines | ||
| 176 | 178 | 'P' 60-6F sound/sscape_ioctl.h conflict! |
| 177 | 179 | 'P' 00-0F drivers/usb/class/usblp.c conflict! |
| 178 | 180 | 'P' 01-09 drivers/misc/pci_endpoint_test.c conflict! |
| 181 | +'P' 00-0F xen/privcmd.h conflict! | |
| 179 | 182 | 'Q' all linux/soundcard.h |
| 180 | 183 | 'R' 00-1F linux/random.h conflict! |
| 181 | 184 | 'R' 01 linux/rfkill.h conflict! |
| @@ -10881,6 +10881,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git · 10880 unmodified lines | ||
| 10881 | 10881 | F: drivers/ata/pata_arasan_cf.c |
| 10882 | 10882 | F: include/linux/pata_arasan_cf_data.h |
| 10883 | 10883 | |
| 10884 | +LIBATA PATA DRIVERS | |
| 10885 | +R: Sergey Shtylyov <s.shtylyov@omp.ru> | |
| 10886 | +L: linux-ide@vger.kernel.org | |
| 10887 | +F: drivers/ata/ata_*.c | |
| 10888 | +F: drivers/ata/pata_*.c | |
| 10889 | + | |
| 10884 | 10890 | LIBATA PATA FARADAY FTIDE010 AND GEMINI SATA BRIDGE DRIVERS |
| 10885 | 10891 | M: Linus Walleij <linus.walleij@linaro.org> |
| 10886 | 10892 | L: linux-ide@vger.kernel.org |
| @@ -12401,7 +12407,7 @@ F: include/uapi/linux/membarrier.h · 1514 unmodified lines | ||
| 12401 | 12407 | F: kernel/sched/membarrier.c |
| 12402 | 12408 | |
| 12403 | 12409 | MEMBLOCK |
| 12404 | −M: Mike Rapoport <rppt@linux.ibm.com> | |
| 12410 | +M: Mike Rapoport <rppt@kernel.org> | |
| 12405 | 12411 | L: linux-mm@kvack.org |
| 12406 | 12412 | S: Maintained |
| 12407 | 12413 | F: Documentation/core-api/boot-time-mm.rst |
| @@ -13299,8 +13305,8 @@ W: http://www.iptables.org/ · 891 unmodified lines | ||
| 13299 | 13305 | W: http://www.nftables.org/ |
| 13300 | 13306 | Q: http://patchwork.ozlabs.org/project/netfilter-devel/list/ |
| 13301 | 13307 | C: irc://irc.libera.chat/netfilter |
| 13302 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git | |
| 13303 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git | |
| 13308 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git | |
| 13309 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next.git | |
| 13304 | 13310 | F: include/linux/netfilter* |
| 13305 | 13311 | F: include/linux/netfilter/ |
| 13306 | 13312 | F: include/net/netfilter/ |
| @@ -13567,7 +13573,7 @@ F: tools/testing/selftests/nci/ · 260 unmodified lines | ||
| 13567 | 13573 | |
| 13568 | 13574 | NFS, SUNRPC, AND LOCKD CLIENTS |
| 13569 | 13575 | M: Trond Myklebust <trond.myklebust@hammerspace.com> |
| 13570 | −M: Anna Schumaker <anna.schumaker@netapp.com> | |
| 13576 | +M: Anna Schumaker <anna@kernel.org> | |
| 13571 | 13577 | L: linux-nfs@vger.kernel.org |
| 13572 | 13578 | S: Maintained |
| 13573 | 13579 | W: http://client.linux-nfs.org |
| @@ -16469,6 +16475,14 @@ F: Documentation/devicetree/bindings/i2c/renesas,rmobile-iic.yaml · 2895 unmodified lines | ||
| 16469 | 16475 | F: drivers/i2c/busses/i2c-rcar.c |
| 16470 | 16476 | F: drivers/i2c/busses/i2c-sh_mobile.c |
| 16471 | 16477 | |
| 16478 | +RENESAS R-CAR SATA DRIVER | |
| 16479 | +R: Sergey Shtylyov <s.shtylyov@omp.ru> | |
| 16480 | +S: Supported | |
| 16481 | +L: linux-ide@vger.kernel.org | |
| 16482 | +L: linux-renesas-soc@vger.kernel.org | |
| 16483 | +F: Documentation/devicetree/bindings/ata/renesas,rcar-sata.yaml | |
| 16484 | +F: drivers/ata/sata_rcar.c | |
| 16485 | + | |
| 16472 | 16486 | RENESAS R-CAR THERMAL DRIVERS |
| 16473 | 16487 | M: Niklas Söderlund <niklas.soderlund@ragnatech.se> |
| 16474 | 16488 | L: linux-renesas-soc@vger.kernel.org |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 5 |
| 3 | 3 | PATCHLEVEL = 17 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc2 | |
| 5 | +EXTRAVERSION = -rc3 | |
| 6 | 6 | NAME = Gobble Gobble |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -13,12 +13,12 @@ · 12 unmodified lines | ||
| 13 | 13 | static int crypto_blake2s_update_arm(struct shash_desc *desc, |
| 14 | 14 | const u8 *in, unsigned int inlen) |
| 15 | 15 | { |
| 16 | − return crypto_blake2s_update(desc, in, inlen, blake2s_compress); | |
| 16 | + return crypto_blake2s_update(desc, in, inlen, false); | |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | 19 | static int crypto_blake2s_final_arm(struct shash_desc *desc, u8 *out) |
| 20 | 20 | { |
| 21 | − return crypto_blake2s_final(desc, out, blake2s_compress); | |
| 21 | + return crypto_blake2s_final(desc, out, false); | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | #define BLAKE2S_ALG(name, driver_name, digest_size) \ |
| @@ -680,6 +680,22 @@ config ARM64_ERRATUM_2051678 · 679 unmodified lines | ||
| 680 | 680 | |
| 681 | 681 | If unsure, say Y. |
| 682 | 682 | |
| 683 | +config ARM64_ERRATUM_2077057 | |
| 684 | + bool "Cortex-A510: 2077057: workaround software-step corrupting SPSR_EL2" | |
| 685 | + help | |
| 686 | + This option adds the workaround for ARM Cortex-A510 erratum 2077057. | |
| 687 | + Affected Cortex-A510 may corrupt SPSR_EL2 when the a step exception is | |
| 688 | + expected, but a Pointer Authentication trap is taken instead. The | |
| 689 | + erratum causes SPSR_EL1 to be copied to SPSR_EL2, which could allow | |
| 690 | + EL1 to cause a return to EL2 with a guest controlled ELR_EL2. | |
| 691 | + | |
| 692 | + This can only happen when EL2 is stepping EL1. | |
| 693 | + | |
| 694 | + When these conditions occur, the SPSR_EL2 value is unchanged from the | |
| 695 | + previous guest entry, and can be restored from the in-memory copy. | |
| 696 | + | |
| 697 | + If unsure, say Y. | |
| 698 | + | |
| 683 | 699 | config ARM64_ERRATUM_2119858 |
| 684 | 700 | bool "Cortex-A710/X2: 2119858: workaround TRBE overwriting trace data in FILL mode" |
| 685 | 701 | default y |
| @@ -600,6 +600,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { · 599 unmodified lines | ||
| 600 | 600 | CAP_MIDR_RANGE_LIST(trbe_write_out_of_range_cpus), |
| 601 | 601 | }, |
| 602 | 602 | #endif |
| 603 | +#ifdef CONFIG_ARM64_ERRATUM_2077057 | |
| 604 | + { | |
| 605 | + .desc = "ARM erratum 2077057", | |
| 606 | + .capability = ARM64_WORKAROUND_2077057, | |
| 607 | + .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, | |
| 608 | + ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A510, 0, 0, 2), | |
| 609 | + }, | |
| 610 | +#endif | |
| 603 | 611 | #ifdef CONFIG_ARM64_ERRATUM_2064142 |
| 604 | 612 | { |
| 605 | 613 | .desc = "ARM erratum 2064142", |
| @@ -797,6 +797,24 @@ static bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu, int *ret) · 796 unmodified lines | ||
| 797 | 797 | xfer_to_guest_mode_work_pending(); |
| 798 | 798 | } |
| 799 | 799 | |
| 800 | +/* | |
| 801 | + * Actually run the vCPU, entering an RCU extended quiescent state (EQS) while | |
| 802 | + * the vCPU is running. | |
| 803 | + * | |
| 804 | + * This must be noinstr as instrumentation may make use of RCU, and this is not | |
| 805 | + * safe during the EQS. | |
| 806 | + */ | |
| 807 | +static int noinstr kvm_arm_vcpu_enter_exit(struct kvm_vcpu *vcpu) | |
| 808 | +{ | |
| 809 | + int ret; | |
| 810 | + | |
| 811 | + guest_state_enter_irqoff(); | |
| 812 | + ret = kvm_call_hyp_ret(__kvm_vcpu_run, vcpu); | |
| 813 | + guest_state_exit_irqoff(); | |
| 814 | + | |
| 815 | + return ret; | |
| 816 | +} | |
| 817 | + | |
| 800 | 818 | /** |
| 801 | 819 | * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code |
| 802 | 820 | * @vcpu: The VCPU pointer |
| @@ -881,9 +899,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 78 unmodified lines | ||
| 881 | 899 | * Enter the guest |
| 882 | 900 | */ |
| 883 | 901 | trace_kvm_entry(*vcpu_pc(vcpu)); |
| 884 | − guest_enter_irqoff(); | |
| 902 | + guest_timing_enter_irqoff(); | |
| 885 | 903 | |
| 886 | − ret = kvm_call_hyp_ret(__kvm_vcpu_run, vcpu); | |
| 904 | + ret = kvm_arm_vcpu_enter_exit(vcpu); | |
| 887 | 905 | |
| 888 | 906 | vcpu->mode = OUTSIDE_GUEST_MODE; |
| 889 | 907 | vcpu->stat.exits++; |
| @@ -918,26 +936,23 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 28 unmodified lines | ||
| 918 | 936 | kvm_arch_vcpu_ctxsync_fp(vcpu); |
| 919 | 937 | |
| 920 | 938 | /* |
| 921 | − * We may have taken a host interrupt in HYP mode (ie | |
| 922 | − * while executing the guest). This interrupt is still | |
| 923 | − * pending, as we haven't serviced it yet! | |
| 939 | + * We must ensure that any pending interrupts are taken before | |
| 940 | + * we exit guest timing so that timer ticks are accounted as | |
| 941 | + * guest time. Transiently unmask interrupts so that any | |
| 942 | + * pending interrupts are taken. | |
| 924 | 943 | * |
| 925 | − * We're now back in SVC mode, with interrupts | |
| 926 | − * disabled. Enabling the interrupts now will have | |
| 927 | − * the effect of taking the interrupt again, in SVC | |
| 928 | − * mode this time. | |
| 944 | + * Per ARM DDI 0487G.b section D1.13.4, an ISB (or other | |
| 945 | + * context synchronization event) is necessary to ensure that | |
| 946 | + * pending interrupts are taken. | |
| 929 | 947 | */ |
| 930 | 948 | local_irq_enable(); |
| 949 | + isb(); | |
| 950 | + local_irq_disable(); | |
| 951 | + | |
| 952 | + guest_timing_exit_irqoff(); | |
| 953 | + | |
| 954 | + local_irq_enable(); | |
| 931 | 955 | |
| 932 | − /* | |
| 933 | − * We do local_irq_enable() before calling guest_exit() so | |
| 934 | − * that if a timer interrupt hits while running the guest we | |
| 935 | − * account that tick as being spent in the guest. We enable | |
| 936 | − * preemption after calling guest_exit() so that if we get | |
| 937 | − * preempted we make sure ticks after that is not counted as | |
| 938 | − * guest time. | |
| 939 | − */ | |
| 940 | − guest_exit(); | |
| 941 | 956 | trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu)); |
| 942 | 957 | |
| 943 | 958 | /* Exit types that need handling before we can be preempted */ |
| @@ -228,6 +228,14 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index) · 227 unmodified lines | ||
| 228 | 228 | { |
| 229 | 229 | struct kvm_run *run = vcpu->run; |
| 230 | 230 | |
| 231 | + if (ARM_SERROR_PENDING(exception_index)) { | |
| 232 | + /* | |
| 233 | + * The SError is handled by handle_exit_early(). If the guest | |
| 234 | + * survives it will re-execute the original instruction. | |
| 235 | + */ | |
| 236 | + return 1; | |
| 237 | + } | |
| 238 | + | |
| 231 | 239 | exception_index = ARM_EXCEPTION_CODE(exception_index); |
| 232 | 240 | |
| 233 | 241 | switch (exception_index) { |
| @@ -402,6 +402,24 @@ static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code) · 401 unmodified lines | ||
| 402 | 402 | return false; |
| 403 | 403 | } |
| 404 | 404 | |
| 405 | +static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code) | |
| 406 | +{ | |
| 407 | + /* | |
| 408 | + * Check for the conditions of Cortex-A510's #2077057. When these occur | |
| 409 | + * SPSR_EL2 can't be trusted, but isn't needed either as it is | |
| 410 | + * unchanged from the value in vcpu_gp_regs(vcpu)->pstate. | |
| 411 | + * Are we single-stepping the guest, and took a PAC exception from the | |
| 412 | + * active-not-pending state? | |
| 413 | + */ | |
| 414 | + if (cpus_have_final_cap(ARM64_WORKAROUND_2077057) && | |
| 415 | + vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP && | |
| 416 | + *vcpu_cpsr(vcpu) & DBG_SPSR_SS && | |
| 417 | + ESR_ELx_EC(read_sysreg_el2(SYS_ESR)) == ESR_ELx_EC_PAC) | |
| 418 | + write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR); | |
| 419 | + | |
| 420 | + vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR); | |
| 421 | +} | |
| 422 | + | |
| 405 | 423 | /* |
| 406 | 424 | * Return true when we were able to fixup the guest exit and should return to |
| 407 | 425 | * the guest, false when we should restore the host state and return to the |
| @@ -413,7 +431,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) · 5 unmodified lines | ||
| 413 | 431 | * Save PSTATE early so that we can evaluate the vcpu mode |
| 414 | 432 | * early on. |
| 415 | 433 | */ |
| 416 | − vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR); | |
| 434 | + synchronize_vcpu_pstate(vcpu, exit_code); | |
| 417 | 435 | |
| 418 | 436 | /* |
| 419 | 437 | * Check whether we want to repaint the state one way or |
| @@ -424,7 +442,8 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) · 4 unmodified lines | ||
| 424 | 442 | if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) |
| 425 | 443 | vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); |
| 426 | 444 | |
| 427 | − if (ARM_SERROR_PENDING(*exit_code)) { | |
| 445 | + if (ARM_SERROR_PENDING(*exit_code) && | |
| 446 | + ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) { | |
| 428 | 447 | u8 esr_ec = kvm_vcpu_trap_get_class(vcpu); |
| 429 | 448 | |
| 430 | 449 | /* |
| @@ -55,9 +55,10 @@ WORKAROUND_1418040 · 54 unmodified lines | ||
| 55 | 55 | WORKAROUND_1463225 |
| 56 | 56 | WORKAROUND_1508412 |
| 57 | 57 | WORKAROUND_1542419 |
| 58 | −WORKAROUND_2064142 | |
| 59 | −WORKAROUND_2038923 | |
| 60 | 58 | WORKAROUND_1902691 |
| 59 | +WORKAROUND_2038923 | |
| 60 | +WORKAROUND_2064142 | |
| 61 | +WORKAROUND_2077057 | |
| 61 | 62 | WORKAROUND_TRBE_OVERWRITE_FILL_MODE |
| 62 | 63 | WORKAROUND_TSB_FLUSH_FAILURE |
| 63 | 64 | WORKAROUND_TRBE_WRITE_OUT_OF_RANGE |
| @@ -83,6 +83,8 @@ · 82 unmodified lines | ||
| 83 | 83 | label = "HDMI OUT"; |
| 84 | 84 | type = "a"; |
| 85 | 85 | |
| 86 | + ddc-en-gpios = <&gpa 25 GPIO_ACTIVE_HIGH>; | |
| 87 | + | |
| 86 | 88 | port { |
| 87 | 89 | hdmi_con: endpoint { |
| 88 | 90 | remote-endpoint = <&dw_hdmi_out>; |
| @@ -114,17 +116,6 @@ · 25 unmodified lines | ||
| 114 | 116 | gpio = <&gpf 14 GPIO_ACTIVE_LOW>; |
| 115 | 117 | enable-active-high; |
| 116 | 118 | }; |
| 117 | − | |
| 118 | − hdmi_power: fixedregulator@3 { | |
| 119 | − compatible = "regulator-fixed"; | |
| 120 | − | |
| 121 | − regulator-name = "hdmi_power"; | |
| 122 | − regulator-min-microvolt = <5000000>; | |
| 123 | − regulator-max-microvolt = <5000000>; | |
| 124 | − | |
| 125 | − gpio = <&gpa 25 0>; | |
| 126 | − enable-active-high; | |
| 127 | − }; | |
| 128 | 119 | }; |
| 129 | 120 | |
| 130 | 121 | &ext { |
| @@ -576,8 +567,6 @@ · 445 unmodified lines | ||
| 576 | 567 | pinctrl-names = "default"; |
| 577 | 568 | pinctrl-0 = <&pins_hdmi_ddc>; |
| 578 | 569 | |
| 579 | − hdmi-5v-supply = <&hdmi_power>; | |
| 580 | − | |
| 581 | 570 | ports { |
| 582 | 571 | #address-cells = <1>; |
| 583 | 572 | #size-cells = <0>; |
| @@ -414,6 +414,24 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, · 413 unmodified lines | ||
| 414 | 414 | return -ENOIOCTLCMD; |
| 415 | 415 | } |
| 416 | 416 | |
| 417 | +/* | |
| 418 | + * Actually run the vCPU, entering an RCU extended quiescent state (EQS) while | |
| 419 | + * the vCPU is running. | |
| 420 | + * | |
| 421 | + * This must be noinstr as instrumentation may make use of RCU, and this is not | |
| 422 | + * safe during the EQS. | |
| 423 | + */ | |
| 424 | +static int noinstr kvm_mips_vcpu_enter_exit(struct kvm_vcpu *vcpu) | |
| 425 | +{ | |
| 426 | + int ret; | |
| 427 | + | |
| 428 | + guest_state_enter_irqoff(); | |
| 429 | + ret = kvm_mips_callbacks->vcpu_run(vcpu); | |
| 430 | + guest_state_exit_irqoff(); | |
| 431 | + | |
| 432 | + return ret; | |
| 433 | +} | |
| 434 | + | |
| 417 | 435 | int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) |
| 418 | 436 | { |
| 419 | 437 | int r = -EINTR; |
| @@ -434,7 +452,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 14 unmodified lines | ||
| 434 | 452 | lose_fpu(1); |
| 435 | 453 | |
| 436 | 454 | local_irq_disable(); |
| 437 | − guest_enter_irqoff(); | |
| 455 | + guest_timing_enter_irqoff(); | |
| 438 | 456 | trace_kvm_enter(vcpu); |
| 439 | 457 | |
| 440 | 458 | /* |
| @@ -445,10 +463,23 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 4 unmodified lines | ||
| 445 | 463 | */ |
| 446 | 464 | smp_store_mb(vcpu->mode, IN_GUEST_MODE); |
| 447 | 465 | |
| 448 | − r = kvm_mips_callbacks->vcpu_run(vcpu); | |
| 466 | + r = kvm_mips_vcpu_enter_exit(vcpu); | |
| 467 | + | |
| 468 | + /* | |
| 469 | + * We must ensure that any pending interrupts are taken before | |
| 470 | + * we exit guest timing so that timer ticks are accounted as | |
| 471 | + * guest time. Transiently unmask interrupts so that any | |
| 472 | + * pending interrupts are taken. | |
| 473 | + * | |
| 474 | + * TODO: is there a barrier which ensures that pending interrupts are | |
| 475 | + * recognised? Currently this just hopes that the CPU takes any pending | |
| 476 | + * interrupts between the enable and disable. | |
| 477 | + */ | |
| 478 | + local_irq_enable(); | |
| 479 | + local_irq_disable(); | |
| 449 | 480 | |
| 450 | 481 | trace_kvm_out(vcpu); |
| 451 | − guest_exit_irqoff(); | |
| 482 | + guest_timing_exit_irqoff(); | |
| 452 | 483 | local_irq_enable(); |
| 453 | 484 | |
| 454 | 485 | out: |
| @@ -1168,7 +1199,7 @@ static void kvm_mips_set_c0_status(void) · 713 unmodified lines | ||
| 1168 | 1199 | /* |
| 1169 | 1200 | * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV) |
| 1170 | 1201 | */ |
| 1171 | −int kvm_mips_handle_exit(struct kvm_vcpu *vcpu) | |
| 1202 | +static int __kvm_mips_handle_exit(struct kvm_vcpu *vcpu) | |
| 1172 | 1203 | { |
| 1173 | 1204 | struct kvm_run *run = vcpu->run; |
| 1174 | 1205 | u32 cause = vcpu->arch.host_cp0_cause; |
| @@ -1357,6 +1388,17 @@ int kvm_mips_handle_exit(struct kvm_vcpu *vcpu) · 182 unmodified lines | ||
| 1357 | 1388 | return ret; |
| 1358 | 1389 | } |
| 1359 | 1390 | |
| 1391 | +int noinstr kvm_mips_handle_exit(struct kvm_vcpu *vcpu) | |
| 1392 | +{ | |
| 1393 | + int ret; | |
| 1394 | + | |
| 1395 | + guest_state_exit_irqoff(); | |
| 1396 | + ret = __kvm_mips_handle_exit(vcpu); | |
| 1397 | + guest_state_enter_irqoff(); | |
| 1398 | + | |
| 1399 | + return ret; | |
| 1400 | +} | |
| 1401 | + | |
| 1360 | 1402 | /* Enable FPU for guest and restore context */ |
| 1361 | 1403 | void kvm_own_fpu(struct kvm_vcpu *vcpu) |
| 1362 | 1404 | { |
| @@ -90,6 +90,7 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id) · 89 unmodified lines | ||
| 90 | 90 | int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) |
| 91 | 91 | { |
| 92 | 92 | struct kvm_cpu_context *cntx; |
| 93 | + struct kvm_vcpu_csr *reset_csr = &vcpu->arch.guest_reset_csr; | |
| 93 | 94 | |
| 94 | 95 | /* Mark this VCPU never ran */ |
| 95 | 96 | vcpu->arch.ran_atleast_once = false; |
| @@ -106,6 +107,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) · 10 unmodified lines | ||
| 106 | 107 | cntx->hstatus |= HSTATUS_SPVP; |
| 107 | 108 | cntx->hstatus |= HSTATUS_SPV; |
| 108 | 109 | |
| 110 | + /* By default, make CY, TM, and IR counters accessible in VU mode */ | |
| 111 | + reset_csr->scounteren = 0x7; | |
| 112 | + | |
| 109 | 113 | /* Setup VCPU timer */ |
| 110 | 114 | kvm_riscv_vcpu_timer_init(vcpu); |
| 111 | 115 | |
| @@ -699,6 +703,20 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu) · 587 unmodified lines | ||
| 699 | 703 | csr_write(CSR_HVIP, csr->hvip); |
| 700 | 704 | } |
| 701 | 705 | |
| 706 | +/* | |
| 707 | + * Actually run the vCPU, entering an RCU extended quiescent state (EQS) while | |
| 708 | + * the vCPU is running. | |
| 709 | + * | |
| 710 | + * This must be noinstr as instrumentation may make use of RCU, and this is not | |
| 711 | + * safe during the EQS. | |
| 712 | + */ | |
| 713 | +static void noinstr kvm_riscv_vcpu_enter_exit(struct kvm_vcpu *vcpu) | |
| 714 | +{ | |
| 715 | + guest_state_enter_irqoff(); | |
| 716 | + __kvm_riscv_switch_to(&vcpu->arch); | |
| 717 | + guest_state_exit_irqoff(); | |
| 718 | +} | |
| 719 | + | |
| 702 | 720 | int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) |
| 703 | 721 | { |
| 704 | 722 | int ret; |
| @@ -790,9 +808,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 85 unmodified lines | ||
| 790 | 808 | continue; |
| 791 | 809 | } |
| 792 | 810 | |
| 793 | − guest_enter_irqoff(); | |
| 811 | + guest_timing_enter_irqoff(); | |
| 794 | 812 | |
| 795 | − __kvm_riscv_switch_to(&vcpu->arch); | |
| 813 | + kvm_riscv_vcpu_enter_exit(vcpu); | |
| 796 | 814 | |
| 797 | 815 | vcpu->mode = OUTSIDE_GUEST_MODE; |
| 798 | 816 | vcpu->stat.exits++; |
| @@ -812,25 +830,21 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 13 unmodified lines | ||
| 812 | 830 | kvm_riscv_vcpu_sync_interrupts(vcpu); |
| 813 | 831 | |
| 814 | 832 | /* |
| 815 | − * We may have taken a host interrupt in VS/VU-mode (i.e. | |
| 816 | − * while executing the guest). This interrupt is still | |
| 817 | − * pending, as we haven't serviced it yet! | |
| 833 | + * We must ensure that any pending interrupts are taken before | |
| 834 | + * we exit guest timing so that timer ticks are accounted as | |
| 835 | + * guest time. Transiently unmask interrupts so that any | |
| 836 | + * pending interrupts are taken. | |
| 818 | 837 | * |
| 819 | − * We're now back in HS-mode with interrupts disabled | |
| 820 | − * so enabling the interrupts now will have the effect | |
| 821 | − * of taking the interrupt again, in HS-mode this time. | |
| 838 | + * There's no barrier which ensures that pending interrupts are | |
| 839 | + * recognised, so we just hope that the CPU takes any pending | |
| 840 | + * interrupts between the enable and disable. | |
| 822 | 841 | */ |
| 823 | 842 | local_irq_enable(); |
| 843 | + local_irq_disable(); | |
| 824 | 844 | |
| 825 | − /* | |
| 826 | − * We do local_irq_enable() before calling guest_exit() so | |
| 827 | − * that if a timer interrupt hits while running the guest | |
| 828 | − * we account that tick as being spent in the guest. We | |
| 829 | − * enable preemption after calling guest_exit() so that if | |
| 830 | − * we get preempted we make sure ticks after that is not | |
| 831 | − * counted as guest time. | |
| 832 | − */ | |
| 833 | − guest_exit(); | |
| 845 | + guest_timing_exit_irqoff(); | |
| 846 | + | |
| 847 | + local_irq_enable(); | |
| 834 | 848 | |
| 835 | 849 | preempt_enable(); |
| 836 | 850 | |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/errno.h> |
| 10 | 10 | #include <linux/err.h> |
| 11 | 11 | #include <linux/kvm_host.h> |
| 12 | +#include <linux/version.h> | |
| 12 | 13 | #include <asm/csr.h> |
| 13 | 14 | #include <asm/sbi.h> |
| 14 | 15 | #include <asm/kvm_vcpu_timer.h> |
| @@ -32,7 +33,7 @@ static int kvm_sbi_ext_base_handler(struct kvm_vcpu *vcpu, struct kvm_run *run, · 17 unmodified lines | ||
| 32 | 33 | *out_val = KVM_SBI_IMPID; |
| 33 | 34 | break; |
| 34 | 35 | case SBI_EXT_BASE_GET_IMP_VERSION: |
| 35 | − *out_val = 0; | |
| 36 | + *out_val = LINUX_VERSION_CODE; | |
| 36 | 37 | break; |
| 37 | 38 | case SBI_EXT_BASE_PROBE_EXT: |
| 38 | 39 | if ((cp->a0 >= SBI_EXT_EXPERIMENTAL_START && |
| @@ -4667,6 +4667,8 @@ static long kvm_s390_guest_sida_op(struct kvm_vcpu *vcpu, · 4666 unmodified lines | ||
| 4667 | 4667 | return -EINVAL; |
| 4668 | 4668 | if (mop->size + mop->sida_offset > sida_size(vcpu->arch.sie_block)) |
| 4669 | 4669 | return -E2BIG; |
| 4670 | + if (!kvm_s390_pv_cpu_is_protected(vcpu)) | |
| 4671 | + return -EINVAL; | |
| 4670 | 4672 | |
| 4671 | 4673 | switch (mop->op) { |
| 4672 | 4674 | case KVM_S390_MEMOP_SIDA_READ: |
| @@ -18,12 +18,12 @@ · 17 unmodified lines | ||
| 18 | 18 | static int crypto_blake2s_update_x86(struct shash_desc *desc, |
| 19 | 19 | const u8 *in, unsigned int inlen) |
| 20 | 20 | { |
| 21 | − return crypto_blake2s_update(desc, in, inlen, blake2s_compress); | |
| 21 | + return crypto_blake2s_update(desc, in, inlen, false); | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | static int crypto_blake2s_final_x86(struct shash_desc *desc, u8 *out) |
| 25 | 25 | { |
| 26 | − return crypto_blake2s_final(desc, out, blake2s_compress); | |
| 26 | + return crypto_blake2s_final(desc, out, false); | |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | #define BLAKE2S_ALG(name, driver_name, digest_size) \ |
| @@ -4703,6 +4703,19 @@ static __initconst const struct x86_pmu intel_pmu = { · 4702 unmodified lines | ||
| 4703 | 4703 | .lbr_read = intel_pmu_lbr_read_64, |
| 4704 | 4704 | .lbr_save = intel_pmu_lbr_save, |
| 4705 | 4705 | .lbr_restore = intel_pmu_lbr_restore, |
| 4706 | + | |
| 4707 | + /* | |
| 4708 | + * SMM has access to all 4 rings and while traditionally SMM code only | |
| 4709 | + * ran in CPL0, 2021-era firmware is starting to make use of CPL3 in SMM. | |
| 4710 | + * | |
| 4711 | + * Since the EVENTSEL.{USR,OS} CPL filtering makes no distinction | |
| 4712 | + * between SMM or not, this results in what should be pure userspace | |
| 4713 | + * counters including SMM data. | |
| 4714 | + * | |
| 4715 | + * This is a clear privilege issue, therefore globally disable | |
| 4716 | + * counting SMM by default. | |
| 4717 | + */ | |
| 4718 | + .attr_freeze_on_smi = 1, | |
| 4706 | 4719 | }; |
| 4707 | 4720 | |
| 4708 | 4721 | static __init void intel_clovertown_quirk(void) |
| @@ -897,8 +897,9 @@ static void pt_handle_status(struct pt *pt) · 896 unmodified lines | ||
| 897 | 897 | * means we are already losing data; need to let the decoder |
| 898 | 898 | * know. |
| 899 | 899 | */ |
| 900 | − if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) || | |
| 901 | − buf->output_off == pt_buffer_region_size(buf)) { | |
| 900 | + if (!buf->single && | |
| 901 | + (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) || | |
| 902 | + buf->output_off == pt_buffer_region_size(buf))) { | |
| 902 | 903 | perf_aux_output_flag(&pt->handle, |
| 903 | 904 | PERF_AUX_FLAG_TRUNCATED); |
| 904 | 905 | advance++; |
| @@ -82,7 +82,7 @@ KVM_X86_OP_NULL(guest_apic_has_interrupt) · 81 unmodified lines | ||
| 82 | 82 | KVM_X86_OP(load_eoi_exitmap) |
| 83 | 83 | KVM_X86_OP(set_virtual_apic_mode) |
| 84 | 84 | KVM_X86_OP_NULL(set_apic_access_page_addr) |
| 85 | −KVM_X86_OP(deliver_posted_interrupt) | |
| 85 | +KVM_X86_OP(deliver_interrupt) | |
| 86 | 86 | KVM_X86_OP_NULL(sync_pir_to_irr) |
| 87 | 87 | KVM_X86_OP(set_tss_addr) |
| 88 | 88 | KVM_X86_OP(set_identity_map_addr) |
| @@ -1410,7 +1410,8 @@ struct kvm_x86_ops { · 1409 unmodified lines | ||
| 1410 | 1410 | void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap); |
| 1411 | 1411 | void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu); |
| 1412 | 1412 | void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu); |
| 1413 | − int (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector); | |
| 1413 | + void (*deliver_interrupt)(struct kvm_lapic *apic, int delivery_mode, | |
| 1414 | + int trig_mode, int vector); | |
| 1414 | 1415 | int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu); |
| 1415 | 1416 | int (*set_tss_addr)(struct kvm *kvm, unsigned int addr); |
| 1416 | 1417 | int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr); |
| @@ -43,20 +43,6 @@ static inline uint32_t xen_cpuid_base(void) · 42 unmodified lines | ||
| 43 | 43 | return hypervisor_cpuid_base("XenVMMXenVMM", 2); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | −#ifdef CONFIG_XEN | |
| 47 | −extern bool __init xen_hvm_need_lapic(void); | |
| 48 | − | |
| 49 | −static inline bool __init xen_x2apic_para_available(void) | |
| 50 | −{ | |
| 51 | − return xen_hvm_need_lapic(); | |
| 52 | −} | |
| 53 | −#else | |
| 54 | −static inline bool __init xen_x2apic_para_available(void) | |
| 55 | −{ | |
| 56 | − return (xen_cpuid_base() != 0); | |
| 57 | −} | |
| 58 | −#endif | |
| 59 | − | |
| 60 | 46 | struct pci_dev; |
| 61 | 47 | |
| 62 | 48 | #ifdef CONFIG_XEN_PV_DOM0 |
| @@ -554,12 +554,13 @@ void kvm_set_cpu_caps(void) · 553 unmodified lines | ||
| 554 | 554 | ); |
| 555 | 555 | |
| 556 | 556 | kvm_cpu_cap_mask(CPUID_7_0_EBX, |
| 557 | − F(FSGSBASE) | F(SGX) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) | | |
| 558 | − F(BMI2) | F(ERMS) | F(INVPCID) | F(RTM) | 0 /*MPX*/ | F(RDSEED) | | |
| 559 | − F(ADX) | F(SMAP) | F(AVX512IFMA) | F(AVX512F) | F(AVX512PF) | | |
| 560 | − F(AVX512ER) | F(AVX512CD) | F(CLFLUSHOPT) | F(CLWB) | F(AVX512DQ) | | |
| 561 | − F(SHA_NI) | F(AVX512BW) | F(AVX512VL) | 0 /*INTEL_PT*/ | |
| 562 | − ); | |
| 557 | + F(FSGSBASE) | F(SGX) | F(BMI1) | F(HLE) | F(AVX2) | | |
| 558 | + F(FDP_EXCPTN_ONLY) | F(SMEP) | F(BMI2) | F(ERMS) | F(INVPCID) | | |
| 559 | + F(RTM) | F(ZERO_FCS_FDS) | 0 /*MPX*/ | F(AVX512F) | | |
| 560 | + F(AVX512DQ) | F(RDSEED) | F(ADX) | F(SMAP) | F(AVX512IFMA) | | |
| 561 | + F(CLFLUSHOPT) | F(CLWB) | 0 /*INTEL_PT*/ | F(AVX512PF) | | |
| 562 | + F(AVX512ER) | F(AVX512CD) | F(SHA_NI) | F(AVX512BW) | | |
| 563 | + F(AVX512VL)); | |
| 563 | 564 | |
| 564 | 565 | kvm_cpu_cap_mask(CPUID_7_ECX, |
| 565 | 566 | F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) | |
| @@ -1096,14 +1096,8 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, · 1095 unmodified lines | ||
| 1096 | 1096 | apic->regs + APIC_TMR); |
| 1097 | 1097 | } |
| 1098 | 1098 | |
| 1099 | − if (static_call(kvm_x86_deliver_posted_interrupt)(vcpu, vector)) { | |
| 1100 | − kvm_lapic_set_irr(vector, apic); | |
| 1101 | − kvm_make_request(KVM_REQ_EVENT, vcpu); | |
| 1102 | − kvm_vcpu_kick(vcpu); | |
| 1103 | − } else { | |
| 1104 | − trace_kvm_apicv_accept_irq(vcpu->vcpu_id, delivery_mode, | |
| 1105 | − trig_mode, vector); | |
| 1106 | − } | |
| 1099 | + static_call(kvm_x86_deliver_interrupt)(apic, delivery_mode, | |
| 1100 | + trig_mode, vector); | |
| 1107 | 1101 | break; |
| 1108 | 1102 | |
| 1109 | 1103 | case APIC_DM_REMRD: |
| @@ -3291,6 +3291,21 @@ static void svm_set_irq(struct kvm_vcpu *vcpu) · 3290 unmodified lines | ||
| 3291 | 3291 | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR; |
| 3292 | 3292 | } |
| 3293 | 3293 | |
| 3294 | +static void svm_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode, | |
| 3295 | + int trig_mode, int vector) | |
| 3296 | +{ | |
| 3297 | + struct kvm_vcpu *vcpu = apic->vcpu; | |
| 3298 | + | |
| 3299 | + if (svm_deliver_avic_intr(vcpu, vector)) { | |
| 3300 | + kvm_lapic_set_irr(vector, apic); | |
| 3301 | + kvm_make_request(KVM_REQ_EVENT, vcpu); | |
| 3302 | + kvm_vcpu_kick(vcpu); | |
| 3303 | + } else { | |
| 3304 | + trace_kvm_apicv_accept_irq(vcpu->vcpu_id, delivery_mode, | |
| 3305 | + trig_mode, vector); | |
| 3306 | + } | |
| 3307 | +} | |
| 3308 | + | |
| 3294 | 3309 | static void svm_update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) |
| 3295 | 3310 | { |
| 3296 | 3311 | struct vcpu_svm *svm = to_svm(vcpu); |
| @@ -3615,7 +3630,7 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu) · 318 unmodified lines | ||
| 3615 | 3630 | struct vcpu_svm *svm = to_svm(vcpu); |
| 3616 | 3631 | unsigned long vmcb_pa = svm->current_vmcb->pa; |
| 3617 | 3632 | |
| 3618 | − kvm_guest_enter_irqoff(); | |
| 3633 | + guest_state_enter_irqoff(); | |
| 3619 | 3634 | |
| 3620 | 3635 | if (sev_es_guest(vcpu->kvm)) { |
| 3621 | 3636 | __svm_sev_es_vcpu_run(vmcb_pa); |
| @@ -3635,7 +3650,7 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu) · 13 unmodified lines | ||
| 3635 | 3650 | vmload(__sme_page_pa(sd->save_area)); |
| 3636 | 3651 | } |
| 3637 | 3652 | |
| 3638 | − kvm_guest_exit_irqoff(); | |
| 3653 | + guest_state_exit_irqoff(); | |
| 3639 | 3654 | } |
| 3640 | 3655 | |
| 3641 | 3656 | static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu) |
| @@ -4545,7 +4560,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { · 903 unmodified lines | ||
| 4545 | 4560 | .pmu_ops = &amd_pmu_ops, |
| 4546 | 4561 | .nested_ops = &svm_nested_ops, |
| 4547 | 4562 | |
| 4548 | − .deliver_posted_interrupt = svm_deliver_avic_intr, | |
| 4563 | + .deliver_interrupt = svm_deliver_interrupt, | |
| 4549 | 4564 | .dy_apicv_has_pending_interrupt = svm_dy_apicv_has_pending_interrupt, |
| 4550 | 4565 | .update_pi_irte = svm_update_pi_irte, |
| 4551 | 4566 | .setup_mce = svm_setup_mce, |
| @@ -4041,6 +4041,21 @@ static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector) · 4040 unmodified lines | ||
| 4041 | 4041 | return 0; |
| 4042 | 4042 | } |
| 4043 | 4043 | |
| 4044 | +static void vmx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode, | |
| 4045 | + int trig_mode, int vector) | |
| 4046 | +{ | |
| 4047 | + struct kvm_vcpu *vcpu = apic->vcpu; | |
| 4048 | + | |
| 4049 | + if (vmx_deliver_posted_interrupt(vcpu, vector)) { | |
| 4050 | + kvm_lapic_set_irr(vector, apic); | |
| 4051 | + kvm_make_request(KVM_REQ_EVENT, vcpu); | |
| 4052 | + kvm_vcpu_kick(vcpu); | |
| 4053 | + } else { | |
| 4054 | + trace_kvm_apicv_accept_irq(vcpu->vcpu_id, delivery_mode, | |
| 4055 | + trig_mode, vector); | |
| 4056 | + } | |
| 4057 | +} | |
| 4058 | + | |
| 4044 | 4059 | /* |
| 4045 | 4060 | * Set up the vmcs's constant host-state fields, i.e., host-state fields that |
| 4046 | 4061 | * will not change in the lifetime of the guest. |
| @@ -6754,7 +6769,7 @@ static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu) · 2707 unmodified lines | ||
| 6754 | 6769 | static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu, |
| 6755 | 6770 | struct vcpu_vmx *vmx) |
| 6756 | 6771 | { |
| 6757 | − kvm_guest_enter_irqoff(); | |
| 6772 | + guest_state_enter_irqoff(); | |
| 6758 | 6773 | |
| 6759 | 6774 | /* L1D Flush includes CPU buffer clear to mitigate MDS */ |
| 6760 | 6775 | if (static_branch_unlikely(&vmx_l1d_should_flush)) |
| @@ -6770,7 +6785,7 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu, · 9 unmodified lines | ||
| 6770 | 6785 | |
| 6771 | 6786 | vcpu->arch.cr2 = native_read_cr2(); |
| 6772 | 6787 | |
| 6773 | − kvm_guest_exit_irqoff(); | |
| 6788 | + guest_state_exit_irqoff(); | |
| 6774 | 6789 | } |
| 6775 | 6790 | |
| 6776 | 6791 | static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu) |
| @@ -7768,7 +7783,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { · 991 unmodified lines | ||
| 7768 | 7783 | .hwapic_isr_update = vmx_hwapic_isr_update, |
| 7769 | 7784 | .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt, |
| 7770 | 7785 | .sync_pir_to_irr = vmx_sync_pir_to_irr, |
| 7771 | − .deliver_posted_interrupt = vmx_deliver_posted_interrupt, | |
| 7786 | + .deliver_interrupt = vmx_deliver_interrupt, | |
| 7772 | 7787 | .dy_apicv_has_pending_interrupt = pi_has_pending_interrupt, |
| 7773 | 7788 | |
| 7774 | 7789 | .set_tss_addr = vmx_set_tss_addr, |
| @@ -90,6 +90,8 @@ · 89 unmodified lines | ||
| 90 | 90 | u64 __read_mostly kvm_mce_cap_supported = MCG_CTL_P | MCG_SER_P; |
| 91 | 91 | EXPORT_SYMBOL_GPL(kvm_mce_cap_supported); |
| 92 | 92 | |
| 93 | +#define ERR_PTR_USR(e) ((void __user *)ERR_PTR(e)) | |
| 94 | + | |
| 93 | 95 | #define emul_to_vcpu(ctxt) \ |
| 94 | 96 | ((struct kvm_vcpu *)(ctxt)->vcpu) |
| 95 | 97 | |
| @@ -4340,7 +4342,7 @@ static inline void __user *kvm_get_attr_addr(struct kvm_device_attr *attr) · 4244 unmodified lines | ||
| 4340 | 4342 | void __user *uaddr = (void __user*)(unsigned long)attr->addr; |
| 4341 | 4343 | |
| 4342 | 4344 | if ((u64)(unsigned long)uaddr != attr->addr) |
| 4343 | − return ERR_PTR(-EFAULT); | |
| 4345 | + return ERR_PTR_USR(-EFAULT); | |
| 4344 | 4346 | return uaddr; |
| 4345 | 4347 | } |
| 4346 | 4348 | |
| @@ -10041,6 +10043,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 5694 unmodified lines | ||
| 10041 | 10043 | set_debugreg(0, 7); |
| 10042 | 10044 | } |
| 10043 | 10045 | |
| 10046 | + guest_timing_enter_irqoff(); | |
| 10047 | + | |
| 10044 | 10048 | for (;;) { |
| 10045 | 10049 | /* |
| 10046 | 10050 | * Assert that vCPU vs. VM APICv state is consistent. An APICv |
| @@ -10125,7 +10129,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 78 unmodified lines | ||
| 10125 | 10129 | * of accounting via context tracking, but the loss of accuracy is |
| 10126 | 10130 | * acceptable for all known use cases. |
| 10127 | 10131 | */ |
| 10128 | − vtime_account_guest_exit(); | |
| 10132 | + guest_timing_exit_irqoff(); | |
| 10129 | 10133 | |
| 10130 | 10134 | if (lapic_in_kernel(vcpu)) { |
| 10131 | 10135 | s64 delta = vcpu->arch.apic->lapic_timer.advance_expire_delta; |
| @@ -11639,8 +11643,6 @@ void kvm_arch_sync_events(struct kvm *kvm) · 1507 unmodified lines | ||
| 11639 | 11643 | kvm_free_pit(kvm); |
| 11640 | 11644 | } |
| 11641 | 11645 | |
| 11642 | −#define ERR_PTR_USR(e) ((void __user *)ERR_PTR(e)) | |
| 11643 | − | |
| 11644 | 11646 | /** |
| 11645 | 11647 | * __x86_set_memory_region: Setup KVM internal memory slot |
| 11646 | 11648 | * |
| @@ -10,51 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | void kvm_spurious_fault(void); |
| 12 | 12 | |
| 13 | −static __always_inline void kvm_guest_enter_irqoff(void) | |
| 14 | −{ | |
| 15 | − /* | |
| 16 | − * VMENTER enables interrupts (host state), but the kernel state is | |
| 17 | − * interrupts disabled when this is invoked. Also tell RCU about | |
| 18 | − * it. This is the same logic as for exit_to_user_mode(). | |
| 19 | − * | |
| 20 | − * This ensures that e.g. latency analysis on the host observes | |
| 21 | − * guest mode as interrupt enabled. | |
| 22 | − * | |
| 23 | − * guest_enter_irqoff() informs context tracking about the | |
| 24 | − * transition to guest mode and if enabled adjusts RCU state | |
| 25 | − * accordingly. | |
| 26 | − */ | |
| 27 | − instrumentation_begin(); | |
| 28 | − trace_hardirqs_on_prepare(); | |
| 29 | − lockdep_hardirqs_on_prepare(CALLER_ADDR0); | |
| 30 | − instrumentation_end(); | |
| 31 | − | |
| 32 | − guest_enter_irqoff(); | |
| 33 | − lockdep_hardirqs_on(CALLER_ADDR0); | |
| 34 | −} | |
| 35 | − | |
| 36 | −static __always_inline void kvm_guest_exit_irqoff(void) | |
| 37 | −{ | |
| 38 | − /* | |
| 39 | − * VMEXIT disables interrupts (host state), but tracing and lockdep | |
| 40 | − * have them in state 'on' as recorded before entering guest mode. | |
| 41 | − * Same as enter_from_user_mode(). | |
| 42 | − * | |
| 43 | − * context_tracking_guest_exit() restores host context and reinstates | |
| 44 | − * RCU if enabled and required. | |
| 45 | − * | |
| 46 | − * This needs to be done immediately after VM-Exit, before any code | |
| 47 | − * that might contain tracepoints or call out to the greater world, | |
| 48 | − * e.g. before x86_spec_ctrl_restore_host(). | |
| 49 | − */ | |
| 50 | − lockdep_hardirqs_off(CALLER_ADDR0); | |
| 51 | − context_tracking_guest_exit(); | |
| 52 | − | |
| 53 | − instrumentation_begin(); | |
| 54 | − trace_hardirqs_off_finish(); | |
| 55 | − instrumentation_end(); | |
| 56 | −} | |
| 57 | − | |
| 58 | 13 | #define KVM_NESTED_VMENTER_CONSISTENCY_CHECK(consistency_check) \ |
| 59 | 14 | ({ \ |
| 60 | 15 | bool failed = (consistency_check); \ |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <xen/events.h> |
| 10 | 10 | #include <xen/interface/memory.h> |
| 11 | 11 | |
| 12 | +#include <asm/apic.h> | |
| 12 | 13 | #include <asm/cpu.h> |
| 13 | 14 | #include <asm/smp.h> |
| 14 | 15 | #include <asm/io_apic.h> |
| @@ -242,15 +243,9 @@ static __init int xen_parse_no_vector_callback(char *arg) · 227 unmodified lines | ||
| 242 | 243 | } |
| 243 | 244 | early_param("xen_no_vector_callback", xen_parse_no_vector_callback); |
| 244 | 245 | |
| 245 | −bool __init xen_hvm_need_lapic(void) | |
| 246 | +static __init bool xen_x2apic_available(void) | |
| 246 | 247 | { |
| 247 | − if (xen_pv_domain()) | |
| 248 | − return false; | |
| 249 | − if (!xen_hvm_domain()) | |
| 250 | − return false; | |
| 251 | − if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback) | |
| 252 | − return false; | |
| 253 | − return true; | |
| 248 | + return x2apic_supported(); | |
| 254 | 249 | } |
| 255 | 250 | |
| 256 | 251 | static __init void xen_hvm_guest_late_init(void) |
| @@ -312,7 +307,7 @@ struct hypervisor_x86 x86_hyper_xen_hvm __initdata = { · 55 unmodified lines | ||
| 312 | 307 | .detect = xen_platform_hvm, |
| 313 | 308 | .type = X86_HYPER_XEN_HVM, |
| 314 | 309 | .init.init_platform = xen_hvm_guest_init, |
| 315 | − .init.x2apic_available = xen_x2apic_para_available, | |
| 310 | + .init.x2apic_available = xen_x2apic_available, | |
| 316 | 311 | .init.init_mem_mapping = xen_hvm_init_mem_mapping, |
| 317 | 312 | .init.guest_late_init = xen_hvm_guest_late_init, |
| 318 | 313 | .runtime.pin_vcpu = xen_pin_vcpu, |
| @@ -1341,10 +1341,6 @@ asmlinkage __visible void __init xen_start_kernel(void) · 1340 unmodified lines | ||
| 1341 | 1341 | |
| 1342 | 1342 | xen_acpi_sleep_register(); |
| 1343 | 1343 | |
| 1344 | − /* Avoid searching for BIOS MP tables */ | |
| 1345 | − x86_init.mpparse.find_smp_config = x86_init_noop; | |
| 1346 | − x86_init.mpparse.get_smp_config = x86_init_uint_noop; | |
| 1347 | − | |
| 1348 | 1344 | xen_boot_params_init_edd(); |
| 1349 | 1345 | |
| 1350 | 1346 | #ifdef CONFIG_ACPI |
| @@ -148,28 +148,12 @@ int xen_smp_intr_init_pv(unsigned int cpu) · 147 unmodified lines | ||
| 148 | 148 | return rc; |
| 149 | 149 | } |
| 150 | 150 | |
| 151 | −static void __init xen_fill_possible_map(void) | |
| 152 | −{ | |
| 153 | − int i, rc; | |
| 154 | − | |
| 155 | − if (xen_initial_domain()) | |
| 156 | − return; | |
| 157 | − | |
| 158 | − for (i = 0; i < nr_cpu_ids; i++) { | |
| 159 | − rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL); | |
| 160 | − if (rc >= 0) { | |
| 161 | − num_processors++; | |
| 162 | − set_cpu_possible(i, true); | |
| 163 | − } | |
| 164 | − } | |
| 165 | −} | |
| 166 | − | |
| 167 | −static void __init xen_filter_cpu_maps(void) | |
| 151 | +static void __init _get_smp_config(unsigned int early) | |
| 168 | 152 | { |
| 169 | 153 | int i, rc; |
| 170 | 154 | unsigned int subtract = 0; |
| 171 | 155 | |
| 172 | − if (!xen_initial_domain()) | |
| 156 | + if (early) | |
| 173 | 157 | return; |
| 174 | 158 | |
| 175 | 159 | num_processors = 0; |
| @@ -210,7 +194,6 @@ static void __init xen_pv_smp_prepare_boot_cpu(void) · 34 unmodified lines | ||
| 210 | 194 | * sure the old memory can be recycled. */ |
| 211 | 195 | make_lowmem_page_readwrite(xen_initial_gdt); |
| 212 | 196 | |
| 213 | − xen_filter_cpu_maps(); | |
| 214 | 197 | xen_setup_vcpu_info_placement(); |
| 215 | 198 | |
| 216 | 199 | /* |
| @@ -476,5 +459,8 @@ static const struct smp_ops xen_smp_ops __initconst = { · 259 unmodified lines | ||
| 476 | 459 | void __init xen_smp_init(void) |
| 477 | 460 | { |
| 478 | 461 | smp_ops = xen_smp_ops; |
| 479 | − xen_fill_possible_map(); | |
| 462 | + | |
| 463 | + /* Avoid searching for BIOS MP tables */ | |
| 464 | + x86_init.mpparse.find_smp_config = x86_init_noop; | |
| 465 | + x86_init.mpparse.get_smp_config = _get_smp_config; | |
| 480 | 466 | } |
| @@ -373,7 +373,7 @@ void bio_integrity_advance(struct bio *bio, unsigned int bytes_done) · 372 unmodified lines | ||
| 373 | 373 | struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); |
| 374 | 374 | unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9); |
| 375 | 375 | |
| 376 | − bip->bip_iter.bi_sector += bytes_done >> 9; | |
| 376 | + bip->bip_iter.bi_sector += bio_integrity_intervals(bi, bytes_done >> 9); | |
| 377 | 377 | bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes); |
| 378 | 378 | } |
| 379 | 379 | |
| @@ -566,34 +566,37 @@ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) · 565 unmodified lines | ||
| 566 | 566 | { |
| 567 | 567 | struct block_device *bdev = iocb->ki_filp->private_data; |
| 568 | 568 | loff_t size = bdev_nr_bytes(bdev); |
| 569 | − size_t count = iov_iter_count(to); | |
| 570 | 569 | loff_t pos = iocb->ki_pos; |
| 571 | 570 | size_t shorted = 0; |
| 572 | 571 | ssize_t ret = 0; |
| 572 | + size_t count; | |
| 573 | 573 | |
| 574 | − if (unlikely(pos + count > size)) { | |
| 574 | + if (unlikely(pos + iov_iter_count(to) > size)) { | |
| 575 | 575 | if (pos >= size) |
| 576 | 576 | return 0; |
| 577 | 577 | size -= pos; |
| 578 | − if (count > size) { | |
| 579 | − shorted = count - size; | |
| 580 | − iov_iter_truncate(to, size); | |
| 581 | − } | |
| 578 | + shorted = iov_iter_count(to) - size; | |
| 579 | + iov_iter_truncate(to, size); | |
| 582 | 580 | } |
| 583 | 581 | |
| 582 | + count = iov_iter_count(to); | |
| 583 | + if (!count) | |
| 584 | + goto reexpand; /* skip atime */ | |
| 585 | + | |
| 584 | 586 | if (iocb->ki_flags & IOCB_DIRECT) { |
| 585 | 587 | struct address_space *mapping = iocb->ki_filp->f_mapping; |
| 586 | 588 | |
| 587 | 589 | if (iocb->ki_flags & IOCB_NOWAIT) { |
| 588 | − if (filemap_range_needs_writeback(mapping, iocb->ki_pos, | |
| 589 | − iocb->ki_pos + count - 1)) | |
| 590 | − return -EAGAIN; | |
| 590 | + if (filemap_range_needs_writeback(mapping, pos, | |
| 591 | + pos + count - 1)) { | |
| 592 | + ret = -EAGAIN; | |
| 593 | + goto reexpand; | |
| 594 | + } | |
| 591 | 595 | } else { |
| 592 | − ret = filemap_write_and_wait_range(mapping, | |
| 593 | − iocb->ki_pos, | |
| 594 | − iocb->ki_pos + count - 1); | |
| 596 | + ret = filemap_write_and_wait_range(mapping, pos, | |
| 597 | + pos + count - 1); | |
| 595 | 598 | if (ret < 0) |
| 596 | − return ret; | |
| 599 | + goto reexpand; | |
| 597 | 600 | } |
| 598 | 601 | |
| 599 | 602 | file_accessed(iocb->ki_filp); |
| @@ -603,12 +606,14 @@ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) · 3 unmodified lines | ||
| 603 | 606 | iocb->ki_pos += ret; |
| 604 | 607 | count -= ret; |
| 605 | 608 | } |
| 609 | + iov_iter_revert(to, count - iov_iter_count(to)); | |
| 606 | 610 | if (ret < 0 || !count) |
| 607 | − return ret; | |
| 611 | + goto reexpand; | |
| 608 | 612 | } |
| 609 | 613 | |
| 610 | 614 | ret = filemap_read(iocb, to, ret); |
| 611 | 615 | |
| 616 | +reexpand: | |
| 612 | 617 | if (unlikely(shorted)) |
| 613 | 618 | iov_iter_reexpand(to, iov_iter_count(to) + shorted); |
| 614 | 619 | return ret; |
| @@ -1324,3 +1324,4 @@ module_exit(crypto_algapi_exit); · 1323 unmodified lines | ||
| 1324 | 1324 | |
| 1325 | 1325 | MODULE_LICENSE("GPL"); |
| 1326 | 1326 | MODULE_DESCRIPTION("Cryptographic algorithms API"); |
| 1327 | +MODULE_SOFTDEP("pre: cryptomgr"); | |
| @@ -643,4 +643,3 @@ EXPORT_SYMBOL_GPL(crypto_req_done); · 642 unmodified lines | ||
| 643 | 643 | |
| 644 | 644 | MODULE_DESCRIPTION("Cryptographic core API"); |
| 645 | 645 | MODULE_LICENSE("GPL"); |
| 646 | −MODULE_SOFTDEP("pre: cryptomgr"); | |
| @@ -15,12 +15,12 @@ · 14 unmodified lines | ||
| 15 | 15 | static int crypto_blake2s_update_generic(struct shash_desc *desc, |
| 16 | 16 | const u8 *in, unsigned int inlen) |
| 17 | 17 | { |
| 18 | − return crypto_blake2s_update(desc, in, inlen, blake2s_compress_generic); | |
| 18 | + return crypto_blake2s_update(desc, in, inlen, true); | |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | static int crypto_blake2s_final_generic(struct shash_desc *desc, u8 *out) |
| 22 | 22 | { |
| 23 | − return crypto_blake2s_final(desc, out, blake2s_compress_generic); | |
| 23 | + return crypto_blake2s_final(desc, out, true); | |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 26 | #define BLAKE2S_ALG(name, driver_name, digest_size) \ |
| @@ -11,6 +11,7 @@ menuconfig ACPI · 10 unmodified lines | ||
| 11 | 11 | depends on ARCH_SUPPORTS_ACPI |
| 12 | 12 | select PNP |
| 13 | 13 | select NLS |
| 14 | + select CRC32 | |
| 14 | 15 | default y if X86 |
| 15 | 16 | help |
| 16 | 17 | Advanced Configuration and Power Interface (ACPI) support for |
| @@ -2007,6 +2007,9 @@ static bool ata_log_supported(struct ata_device *dev, u8 log) · 2006 unmodified lines | ||
| 2007 | 2007 | { |
| 2008 | 2008 | struct ata_port *ap = dev->link->ap; |
| 2009 | 2009 | |
| 2010 | + if (dev->horkage & ATA_HORKAGE_NO_LOG_DIR) | |
| 2011 | + return false; | |
| 2012 | + | |
| 2010 | 2013 | if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, ap->sector_buf, 1)) |
| 2011 | 2014 | return false; |
| 2012 | 2015 | return get_unaligned_le16(&ap->sector_buf[log * 2]) ? true : false; |
| @@ -2445,23 +2448,21 @@ static void ata_dev_config_cpr(struct ata_device *dev) · 432 unmodified lines | ||
| 2445 | 2448 | struct ata_cpr_log *cpr_log = NULL; |
| 2446 | 2449 | u8 *desc, *buf = NULL; |
| 2447 | 2450 | |
| 2448 | − if (!ata_identify_page_supported(dev, | |
| 2449 | − ATA_LOG_CONCURRENT_POSITIONING_RANGES)) | |
| 2451 | + if (ata_id_major_version(dev->id) < 11 || | |
| 2452 | + !ata_log_supported(dev, ATA_LOG_CONCURRENT_POSITIONING_RANGES)) | |
| 2450 | 2453 | goto out; |
| 2451 | 2454 | |
| 2452 | 2455 | /* |
| 2453 | − * Read IDENTIFY DEVICE data log, page 0x47 | |
| 2454 | − * (concurrent positioning ranges). We can have at most 255 32B range | |
| 2455 | − * descriptors plus a 64B header. | |
| 2456 | + * Read the concurrent positioning ranges log (0x47). We can have at | |
| 2457 | + * most 255 32B range descriptors plus a 64B header. | |
| 2456 | 2458 | */ |
| 2457 | 2459 | buf_len = (64 + 255 * 32 + 511) & ~511; |
| 2458 | 2460 | buf = kzalloc(buf_len, GFP_KERNEL); |
| 2459 | 2461 | if (!buf) |
| 2460 | 2462 | goto out; |
| 2461 | 2463 | |
| 2462 | − err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, | |
| 2463 | − ATA_LOG_CONCURRENT_POSITIONING_RANGES, | |
| 2464 | − buf, buf_len >> 9); | |
| 2464 | + err_mask = ata_read_log_page(dev, ATA_LOG_CONCURRENT_POSITIONING_RANGES, | |
| 2465 | + 0, buf, buf_len >> 9); | |
| 2465 | 2466 | if (err_mask) |
| 2466 | 2467 | goto out; |
| 2467 | 2468 | |
| @@ -4073,6 +4074,13 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { · 1605 unmodified lines | ||
| 4073 | 4074 | { "WDC WD3000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, |
| 4074 | 4075 | { "WDC WD3200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM }, |
| 4075 | 4076 | |
| 4077 | + /* | |
| 4078 | + * This sata dom device goes on a walkabout when the ATA_LOG_DIRECTORY | |
| 4079 | + * log page is accessed. Ensure we never ask for this log page with | |
| 4080 | + * these devices. | |
| 4081 | + */ | |
| 4082 | + { "SATADOM-ML 3ME", NULL, ATA_HORKAGE_NO_LOG_DIR }, | |
| 4083 | + | |
| 4076 | 4084 | /* End Marker */ |
| 4077 | 4085 | { } |
| 4078 | 4086 | }; |
| @@ -762,7 +762,7 @@ static bool crng_init_try_arch(struct crng_state *crng) · 761 unmodified lines | ||
| 762 | 762 | return arch_init; |
| 763 | 763 | } |
| 764 | 764 | |
| 765 | −static bool __init crng_init_try_arch_early(struct crng_state *crng) | |
| 765 | +static bool __init crng_init_try_arch_early(void) | |
| 766 | 766 | { |
| 767 | 767 | int i; |
| 768 | 768 | bool arch_init = true; |
| @@ -774,7 +774,7 @@ static bool __init crng_init_try_arch_early(struct crng_state *crng) · 5 unmodified lines | ||
| 774 | 774 | rv = random_get_entropy(); |
| 775 | 775 | arch_init = false; |
| 776 | 776 | } |
| 777 | − crng->state[i] ^= rv; | |
| 777 | + primary_crng.state[i] ^= rv; | |
| 778 | 778 | } |
| 779 | 779 | |
| 780 | 780 | return arch_init; |
| @@ -788,22 +788,20 @@ static void crng_initialize_secondary(struct crng_state *crng) · 7 unmodified lines | ||
| 788 | 788 | crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; |
| 789 | 789 | } |
| 790 | 790 | |
| 791 | −static void __init crng_initialize_primary(struct crng_state *crng) | |
| 791 | +static void __init crng_initialize_primary(void) | |
| 792 | 792 | { |
| 793 | − _extract_entropy(&crng->state[4], sizeof(u32) * 12); | |
| 794 | − if (crng_init_try_arch_early(crng) && trust_cpu && crng_init < 2) { | |
| 793 | + _extract_entropy(&primary_crng.state[4], sizeof(u32) * 12); | |
| 794 | + if (crng_init_try_arch_early() && trust_cpu && crng_init < 2) { | |
| 795 | 795 | invalidate_batched_entropy(); |
| 796 | 796 | numa_crng_init(); |
| 797 | 797 | crng_init = 2; |
| 798 | 798 | pr_notice("crng init done (trusting CPU's manufacturer)\n"); |
| 799 | 799 | } |
| 800 | − crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; | |
| 800 | + primary_crng.init_time = jiffies - CRNG_RESEED_INTERVAL - 1; | |
| 801 | 801 | } |
| 802 | 802 | |
| 803 | −static void crng_finalize_init(struct crng_state *crng) | |
| 803 | +static void crng_finalize_init(void) | |
| 804 | 804 | { |
| 805 | − if (crng != &primary_crng || crng_init >= 2) | |
| 806 | − return; | |
| 807 | 805 | if (!system_wq) { |
| 808 | 806 | /* We can't call numa_crng_init until we have workqueues, |
| 809 | 807 | * so mark this for processing later. */ |
| @@ -814,6 +812,7 @@ static void crng_finalize_init(struct crng_state *crng) · 4 unmodified lines | ||
| 814 | 812 | invalidate_batched_entropy(); |
| 815 | 813 | numa_crng_init(); |
| 816 | 814 | crng_init = 2; |
| 815 | + crng_need_final_init = false; | |
| 817 | 816 | process_random_ready_list(); |
| 818 | 817 | wake_up_interruptible(&crng_init_wait); |
| 819 | 818 | kill_fasync(&fasync, SIGIO, POLL_IN); |
| @@ -980,7 +979,8 @@ static void crng_reseed(struct crng_state *crng, bool use_input_pool) · 160 unmodified lines | ||
| 980 | 979 | memzero_explicit(&buf, sizeof(buf)); |
| 981 | 980 | WRITE_ONCE(crng->init_time, jiffies); |
| 982 | 981 | spin_unlock_irqrestore(&crng->lock, flags); |
| 983 | − crng_finalize_init(crng); | |
| 982 | + if (crng == &primary_crng && crng_init < 2) | |
| 983 | + crng_finalize_init(); | |
| 984 | 984 | } |
| 985 | 985 | |
| 986 | 986 | static void _extract_crng(struct crng_state *crng, u8 out[CHACHA_BLOCK_SIZE]) |
| @@ -1697,8 +1697,8 @@ int __init rand_initialize(void) · 710 unmodified lines | ||
| 1697 | 1697 | { |
| 1698 | 1698 | init_std_data(); |
| 1699 | 1699 | if (crng_need_final_init) |
| 1700 | − crng_finalize_init(&primary_crng); | |
| 1701 | − crng_initialize_primary(&primary_crng); | |
| 1700 | + crng_finalize_init(); | |
| 1701 | + crng_initialize_primary(); | |
| 1702 | 1702 | crng_global_init_time = jiffies; |
| 1703 | 1703 | if (ratelimit_disable) { |
| 1704 | 1704 | urandom_warning.interval = 0; |
| @@ -1856,7 +1856,10 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) · 151 unmodified lines | ||
| 1856 | 1856 | */ |
| 1857 | 1857 | if (!capable(CAP_SYS_ADMIN)) |
| 1858 | 1858 | return -EPERM; |
| 1859 | − input_pool.entropy_count = 0; | |
| 1859 | + if (xchg(&input_pool.entropy_count, 0) && random_write_wakeup_bits) { | |
| 1860 | + wake_up_interruptible(&random_write_wait); | |
| 1861 | + kill_fasync(&fasync, SIGIO, POLL_OUT); | |
| 1862 | + } | |
| 1860 | 1863 | return 0; |
| 1861 | 1864 | case RNDRESEEDCRNG: |
| 1862 | 1865 | if (!capable(CAP_SYS_ADMIN)) |
| @@ -2205,13 +2208,15 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, · 342 unmodified lines | ||
| 2205 | 2208 | return; |
| 2206 | 2209 | } |
| 2207 | 2210 | |
| 2208 | − /* Suspend writing if we're above the trickle threshold. | |
| 2211 | + /* Throttle writing if we're above the trickle threshold. | |
| 2209 | 2212 | * We'll be woken up again once below random_write_wakeup_thresh, |
| 2210 | − * or when the calling thread is about to terminate. | |
| 2213 | + * when the calling thread is about to terminate, or once | |
| 2214 | + * CRNG_RESEED_INTERVAL has lapsed. | |
| 2211 | 2215 | */ |
| 2212 | − wait_event_interruptible(random_write_wait, | |
| 2216 | + wait_event_interruptible_timeout(random_write_wait, | |
| 2213 | 2217 | !system_wq || kthread_should_stop() || |
| 2214 | − POOL_ENTROPY_BITS() <= random_write_wakeup_bits); | |
| 2218 | + POOL_ENTROPY_BITS() <= random_write_wakeup_bits, | |
| 2219 | + CRNG_RESEED_INTERVAL); | |
| 2215 | 2220 | mix_pool_bytes(buffer, count); |
| 2216 | 2221 | credit_entropy_bits(entropy); |
| 2217 | 2222 | } |
| @@ -1753,7 +1753,6 @@ void otx2_cpt_print_uc_dbg_info(struct otx2_cptpf_dev *cptpf) · 1752 unmodified lines | ||
| 1753 | 1753 | char engs_info[2 * OTX2_CPT_NAME_LENGTH]; |
| 1754 | 1754 | struct otx2_cpt_eng_grp_info *grp; |
| 1755 | 1755 | struct otx2_cpt_engs_rsvd *engs; |
| 1756 | − u32 mask[4]; | |
| 1757 | 1756 | int i, j; |
| 1758 | 1757 | |
| 1759 | 1758 | pr_debug("Engine groups global info"); |
| @@ -1785,6 +1784,8 @@ void otx2_cpt_print_uc_dbg_info(struct otx2_cptpf_dev *cptpf) · 25 unmodified lines | ||
| 1785 | 1784 | for (j = 0; j < OTX2_CPT_MAX_ETYPES_PER_GRP; j++) { |
| 1786 | 1785 | engs = &grp->engs[j]; |
| 1787 | 1786 | if (engs->type) { |
| 1787 | + u32 mask[5] = { }; | |
| 1788 | + | |
| 1788 | 1789 | get_engs_info(grp, engs_info, |
| 1789 | 1790 | 2 * OTX2_CPT_NAME_LENGTH, j); |
| 1790 | 1791 | pr_debug("Slot%d: %s", j, engs_info); |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/xarray.h> |
| 15 | 15 | #include <linux/list.h> |
| 16 | 16 | #include <linux/slab.h> |
| 17 | +#include <linux/nospec.h> | |
| 17 | 18 | #include <linux/uaccess.h> |
| 18 | 19 | #include <linux/syscalls.h> |
| 19 | 20 | #include <linux/dma-heap.h> |
| @@ -135,6 +136,7 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd, · 115 unmodified lines | ||
| 135 | 136 | if (nr >= ARRAY_SIZE(dma_heap_ioctl_cmds)) |
| 136 | 137 | return -EINVAL; |
| 137 | 138 | |
| 139 | + nr = array_index_nospec(nr, ARRAY_SIZE(dma_heap_ioctl_cmds)); | |
| 138 | 140 | /* Get the kernel ioctl cmd that matches */ |
| 139 | 141 | kcmd = dma_heap_ioctl_cmds[nr]; |
| 140 | 142 | |
| @@ -350,7 +350,7 @@ static int altr_sdram_probe(struct platform_device *pdev) · 349 unmodified lines | ||
| 350 | 350 | if (irq < 0) { |
| 351 | 351 | edac_printk(KERN_ERR, EDAC_MC, |
| 352 | 352 | "No irq %d in DT\n", irq); |
| 353 | − return -ENODEV; | |
| 353 | + return irq; | |
| 354 | 354 | } |
| 355 | 355 | |
| 356 | 356 | /* Arria10 has a 2nd IRQ */ |
| @@ -1919,7 +1919,7 @@ static int xgene_edac_probe(struct platform_device *pdev) · 1918 unmodified lines | ||
| 1919 | 1919 | irq = platform_get_irq_optional(pdev, i); |
| 1920 | 1920 | if (irq < 0) { |
| 1921 | 1921 | dev_err(&pdev->dev, "No IRQ resource\n"); |
| 1922 | − rc = -EINVAL; | |
| 1922 | + rc = irq; | |
| 1923 | 1923 | goto out_err; |
| 1924 | 1924 | } |
| 1925 | 1925 | rc = devm_request_irq(&pdev->dev, irq, |
| @@ -1408,12 +1408,10 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta · 1407 unmodified lines | ||
| 1408 | 1408 | int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); |
| 1409 | 1409 | |
| 1410 | 1410 | void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); |
| 1411 | −bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); | |
| 1412 | 1411 | void amdgpu_acpi_detect(void); |
| 1413 | 1412 | #else |
| 1414 | 1413 | static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } |
| 1415 | 1414 | static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } |
| 1416 | −static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } | |
| 1417 | 1415 | static inline void amdgpu_acpi_detect(void) { } |
| 1418 | 1416 | static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } |
| 1419 | 1417 | static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, |
| @@ -1422,6 +1420,14 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev, · 2 unmodified lines | ||
| 1422 | 1420 | enum amdgpu_ss ss_state) { return 0; } |
| 1423 | 1421 | #endif |
| 1424 | 1422 | |
| 1423 | +#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND) | |
| 1424 | +bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev); | |
| 1425 | +bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); | |
| 1426 | +#else | |
| 1427 | +static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } | |
| 1428 | +static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; } | |
| 1429 | +#endif | |
| 1430 | + | |
| 1425 | 1431 | int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, |
| 1426 | 1432 | uint64_t addr, struct amdgpu_bo **bo, |
| 1427 | 1433 | struct amdgpu_bo_va_mapping **mapping); |
| @@ -1031,6 +1031,20 @@ void amdgpu_acpi_detect(void) · 1030 unmodified lines | ||
| 1031 | 1031 | } |
| 1032 | 1032 | } |
| 1033 | 1033 | |
| 1034 | +#if IS_ENABLED(CONFIG_SUSPEND) | |
| 1035 | +/** | |
| 1036 | + * amdgpu_acpi_is_s3_active | |
| 1037 | + * | |
| 1038 | + * @adev: amdgpu_device_pointer | |
| 1039 | + * | |
| 1040 | + * returns true if supported, false if not. | |
| 1041 | + */ | |
| 1042 | +bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) | |
| 1043 | +{ | |
| 1044 | + return !(adev->flags & AMD_IS_APU) || | |
| 1045 | + (pm_suspend_target_state == PM_SUSPEND_MEM); | |
| 1046 | +} | |
| 1047 | + | |
| 1034 | 1048 | /** |
| 1035 | 1049 | * amdgpu_acpi_is_s0ix_active |
| 1036 | 1050 | * |
| @@ -1040,11 +1054,24 @@ void amdgpu_acpi_detect(void) · 3 unmodified lines | ||
| 1040 | 1054 | */ |
| 1041 | 1055 | bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) |
| 1042 | 1056 | { |
| 1043 | −#if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND) | |
| 1044 | − if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { | |
| 1045 | − if (adev->flags & AMD_IS_APU) | |
| 1046 | − return pm_suspend_target_state == PM_SUSPEND_TO_IDLE; | |
| 1057 | + if (!(adev->flags & AMD_IS_APU) || | |
| 1058 | + (pm_suspend_target_state != PM_SUSPEND_TO_IDLE)) | |
| 1059 | + return false; | |
| 1060 | + | |
| 1061 | + if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { | |
| 1062 | + dev_warn_once(adev->dev, | |
| 1063 | + "Power consumption will be higher as BIOS has not been configured for suspend-to-idle.\n" | |
| 1064 | + "To use suspend-to-idle change the sleep mode in BIOS setup.\n"); | |
| 1065 | + return false; | |
| 1047 | 1066 | } |
| 1048 | −#endif | |
| 1067 | + | |
| 1068 | +#if !IS_ENABLED(CONFIG_AMD_PMC) | |
| 1069 | + dev_warn_once(adev->dev, | |
| 1070 | + "Power consumption will be higher as the kernel has not been compiled with CONFIG_AMD_PMC.\n"); | |
| 1049 | 1071 | return false; |
| 1072 | +#else | |
| 1073 | + return true; | |
| 1074 | +#endif /* CONFIG_AMD_PMC */ | |
| 1050 | 1075 | } |
| 1076 | + | |
| 1077 | +#endif /* CONFIG_SUSPEND */ | |
| @@ -2246,13 +2246,20 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work) · 2245 unmodified lines | ||
| 2246 | 2246 | static int amdgpu_pmops_prepare(struct device *dev) |
| 2247 | 2247 | { |
| 2248 | 2248 | struct drm_device *drm_dev = dev_get_drvdata(dev); |
| 2249 | + struct amdgpu_device *adev = drm_to_adev(drm_dev); | |
| 2249 | 2250 | |
| 2250 | 2251 | /* Return a positive number here so |
| 2251 | 2252 | * DPM_FLAG_SMART_SUSPEND works properly |
| 2252 | 2253 | */ |
| 2253 | 2254 | if (amdgpu_device_supports_boco(drm_dev)) |
| 2254 | − return pm_runtime_suspended(dev) && | |
| 2255 | − pm_suspend_via_firmware(); | |
| 2255 | + return pm_runtime_suspended(dev); | |
| 2256 | + | |
| 2257 | + /* if we will not support s3 or s2i for the device | |
| 2258 | + * then skip suspend | |
| 2259 | + */ | |
| 2260 | + if (!amdgpu_acpi_is_s0ix_active(adev) && | |
| 2261 | + !amdgpu_acpi_is_s3_active(adev)) | |
| 2262 | + return 1; | |
| 2256 | 2263 | |
| 2257 | 2264 | return 0; |
| 2258 | 2265 | } |
| @@ -1904,7 +1904,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, · 1903 unmodified lines | ||
| 1904 | 1904 | unsigned i; |
| 1905 | 1905 | int r; |
| 1906 | 1906 | |
| 1907 | − if (direct_submit && !ring->sched.ready) { | |
| 1907 | + if (!direct_submit && !ring->sched.ready) { | |
| 1908 | 1908 | DRM_ERROR("Trying to move memory with ring turned off.\n"); |
| 1909 | 1909 | return -EINVAL; |
| 1910 | 1910 | } |
| @@ -1140,6 +1140,9 @@ static void gmc_v10_0_get_clockgating_state(void *handle, u32 *flags) · 1139 unmodified lines | ||
| 1140 | 1140 | { |
| 1141 | 1141 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1142 | 1142 | |
| 1143 | + if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 3)) | |
| 1144 | + return; | |
| 1145 | + | |
| 1143 | 1146 | adev->mmhub.funcs->get_clockgating(adev, flags); |
| 1144 | 1147 | |
| 1145 | 1148 | if (adev->ip_versions[ATHUB_HWIP][0] >= IP_VERSION(2, 1, 0)) |
| @@ -570,32 +570,32 @@ static struct wm_table lpddr5_wm_table = { · 569 unmodified lines | ||
| 570 | 570 | .wm_inst = WM_A, |
| 571 | 571 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 572 | 572 | .pstate_latency_us = 11.65333, |
| 573 | − .sr_exit_time_us = 7.95, | |
| 574 | − .sr_enter_plus_exit_time_us = 9, | |
| 573 | + .sr_exit_time_us = 13.5, | |
| 574 | + .sr_enter_plus_exit_time_us = 16.5, | |
| 575 | 575 | .valid = true, |
| 576 | 576 | }, |
| 577 | 577 | { |
| 578 | 578 | .wm_inst = WM_B, |
| 579 | 579 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 580 | 580 | .pstate_latency_us = 11.65333, |
| 581 | − .sr_exit_time_us = 9.82, | |
| 582 | − .sr_enter_plus_exit_time_us = 11.196, | |
| 581 | + .sr_exit_time_us = 13.5, | |
| 582 | + .sr_enter_plus_exit_time_us = 16.5, | |
| 583 | 583 | .valid = true, |
| 584 | 584 | }, |
| 585 | 585 | { |
| 586 | 586 | .wm_inst = WM_C, |
| 587 | 587 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 588 | 588 | .pstate_latency_us = 11.65333, |
| 589 | − .sr_exit_time_us = 9.89, | |
| 590 | − .sr_enter_plus_exit_time_us = 11.24, | |
| 589 | + .sr_exit_time_us = 13.5, | |
| 590 | + .sr_enter_plus_exit_time_us = 16.5, | |
| 591 | 591 | .valid = true, |
| 592 | 592 | }, |
| 593 | 593 | { |
| 594 | 594 | .wm_inst = WM_D, |
| 595 | 595 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 596 | 596 | .pstate_latency_us = 11.65333, |
| 597 | − .sr_exit_time_us = 9.748, | |
| 598 | − .sr_enter_plus_exit_time_us = 11.102, | |
| 597 | + .sr_exit_time_us = 13.5, | |
| 598 | + .sr_enter_plus_exit_time_us = 16.5, | |
| 599 | 599 | .valid = true, |
| 600 | 600 | }, |
| 601 | 601 | } |
| @@ -329,38 +329,38 @@ static struct clk_bw_params dcn31_bw_params = { · 328 unmodified lines | ||
| 329 | 329 | |
| 330 | 330 | }; |
| 331 | 331 | |
| 332 | −static struct wm_table ddr4_wm_table = { | |
| 332 | +static struct wm_table ddr5_wm_table = { | |
| 333 | 333 | .entries = { |
| 334 | 334 | { |
| 335 | 335 | .wm_inst = WM_A, |
| 336 | 336 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 337 | 337 | .pstate_latency_us = 11.72, |
| 338 | − .sr_exit_time_us = 6.09, | |
| 339 | − .sr_enter_plus_exit_time_us = 7.14, | |
| 338 | + .sr_exit_time_us = 9, | |
| 339 | + .sr_enter_plus_exit_time_us = 11, | |
| 340 | 340 | .valid = true, |
| 341 | 341 | }, |
| 342 | 342 | { |
| 343 | 343 | .wm_inst = WM_B, |
| 344 | 344 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 345 | 345 | .pstate_latency_us = 11.72, |
| 346 | − .sr_exit_time_us = 10.12, | |
| 347 | − .sr_enter_plus_exit_time_us = 11.48, | |
| 346 | + .sr_exit_time_us = 9, | |
| 347 | + .sr_enter_plus_exit_time_us = 11, | |
| 348 | 348 | .valid = true, |
| 349 | 349 | }, |
| 350 | 350 | { |
| 351 | 351 | .wm_inst = WM_C, |
| 352 | 352 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 353 | 353 | .pstate_latency_us = 11.72, |
| 354 | − .sr_exit_time_us = 10.12, | |
| 355 | − .sr_enter_plus_exit_time_us = 11.48, | |
| 354 | + .sr_exit_time_us = 9, | |
| 355 | + .sr_enter_plus_exit_time_us = 11, | |
| 356 | 356 | .valid = true, |
| 357 | 357 | }, |
| 358 | 358 | { |
| 359 | 359 | .wm_inst = WM_D, |
| 360 | 360 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 361 | 361 | .pstate_latency_us = 11.72, |
| 362 | − .sr_exit_time_us = 10.12, | |
| 363 | − .sr_enter_plus_exit_time_us = 11.48, | |
| 362 | + .sr_exit_time_us = 9, | |
| 363 | + .sr_enter_plus_exit_time_us = 11, | |
| 364 | 364 | .valid = true, |
| 365 | 365 | }, |
| 366 | 366 | } |
| @@ -687,7 +687,7 @@ void dcn31_clk_mgr_construct( · 320 unmodified lines | ||
| 687 | 687 | if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { |
| 688 | 688 | dcn31_bw_params.wm_table = lpddr5_wm_table; |
| 689 | 689 | } else { |
| 690 | − dcn31_bw_params.wm_table = ddr4_wm_table; | |
| 690 | + dcn31_bw_params.wm_table = ddr5_wm_table; | |
| 691 | 691 | } |
| 692 | 692 | /* Saved clocks configured at boot for debug purposes */ |
| 693 | 693 | dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); |
| @@ -5597,6 +5597,26 @@ static bool retrieve_link_cap(struct dc_link *link) · 5596 unmodified lines | ||
| 5597 | 5597 | dp_hw_fw_revision.ieee_fw_rev, |
| 5598 | 5598 | sizeof(dp_hw_fw_revision.ieee_fw_rev)); |
| 5599 | 5599 | |
| 5600 | + /* Quirk for Apple MBP 2018 15" Retina panels: wrong DP_MAX_LINK_RATE */ | |
| 5601 | + { | |
| 5602 | + uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 }; | |
| 5603 | + uint8_t fwrev_mbp_2018[] = { 7, 4 }; | |
| 5604 | + uint8_t fwrev_mbp_2018_vega[] = { 8, 4 }; | |
| 5605 | + | |
| 5606 | + /* We also check for the firmware revision as 16,1 models have an | |
| 5607 | + * identical device id and are incorrectly quirked otherwise. | |
| 5608 | + */ | |
| 5609 | + if ((link->dpcd_caps.sink_dev_id == 0x0010fa) && | |
| 5610 | + !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2018, | |
| 5611 | + sizeof(str_mbp_2018)) && | |
| 5612 | + (!memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018, | |
| 5613 | + sizeof(fwrev_mbp_2018)) || | |
| 5614 | + !memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018_vega, | |
| 5615 | + sizeof(fwrev_mbp_2018_vega)))) { | |
| 5616 | + link->reported_link_cap.link_rate = LINK_RATE_RBR2; | |
| 5617 | + } | |
| 5618 | + } | |
| 5619 | + | |
| 5600 | 5620 | memset(&link->dpcd_caps.dsc_caps, '\0', |
| 5601 | 5621 | sizeof(link->dpcd_caps.dsc_caps)); |
| 5602 | 5622 | memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap)); |
| @@ -1608,11 +1608,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( · 1607 unmodified lines | ||
| 1608 | 1608 | pipe_ctx->stream_res.stream_enc, |
| 1609 | 1609 | pipe_ctx->stream_res.tg->inst); |
| 1610 | 1610 | |
| 1611 | − if (dc_is_embedded_signal(pipe_ctx->stream->signal) && | |
| 1612 | − pipe_ctx->stream_res.stream_enc->funcs->reset_fifo) | |
| 1613 | − pipe_ctx->stream_res.stream_enc->funcs->reset_fifo( | |
| 1614 | − pipe_ctx->stream_res.stream_enc); | |
| 1615 | − | |
| 1616 | 1611 | if (dc_is_dp_signal(pipe_ctx->stream->signal)) |
| 1617 | 1612 | dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG); |
| 1618 | 1613 | |
| @@ -902,19 +902,6 @@ void enc1_stream_encoder_stop_dp_info_packets( · 901 unmodified lines | ||
| 902 | 902 | |
| 903 | 903 | } |
| 904 | 904 | |
| 905 | −void enc1_stream_encoder_reset_fifo( | |
| 906 | − struct stream_encoder *enc) | |
| 907 | −{ | |
| 908 | − struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); | |
| 909 | − | |
| 910 | − /* set DIG_START to 0x1 to reset FIFO */ | |
| 911 | − REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); | |
| 912 | − udelay(100); | |
| 913 | − | |
| 914 | − /* write 0 to take the FIFO out of reset */ | |
| 915 | − REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); | |
| 916 | −} | |
| 917 | − | |
| 918 | 905 | void enc1_stream_encoder_dp_blank( |
| 919 | 906 | struct dc_link *link, |
| 920 | 907 | struct stream_encoder *enc) |
| @@ -1600,8 +1587,6 @@ static const struct stream_encoder_funcs dcn10_str_enc_funcs = { · 679 unmodified lines | ||
| 1600 | 1587 | enc1_stream_encoder_send_immediate_sdp_message, |
| 1601 | 1588 | .stop_dp_info_packets = |
| 1602 | 1589 | enc1_stream_encoder_stop_dp_info_packets, |
| 1603 | − .reset_fifo = | |
| 1604 | − enc1_stream_encoder_reset_fifo, | |
| 1605 | 1590 | .dp_blank = |
| 1606 | 1591 | enc1_stream_encoder_dp_blank, |
| 1607 | 1592 | .dp_unblank = |
| @@ -626,9 +626,6 @@ void enc1_stream_encoder_send_immediate_sdp_message( · 625 unmodified lines | ||
| 626 | 626 | void enc1_stream_encoder_stop_dp_info_packets( |
| 627 | 627 | struct stream_encoder *enc); |
| 628 | 628 | |
| 629 | −void enc1_stream_encoder_reset_fifo( | |
| 630 | − struct stream_encoder *enc); | |
| 631 | − | |
| 632 | 629 | void enc1_stream_encoder_dp_blank( |
| 633 | 630 | struct dc_link *link, |
| 634 | 631 | struct stream_encoder *enc); |
| @@ -593,8 +593,6 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = { · 592 unmodified lines | ||
| 593 | 593 | enc1_stream_encoder_send_immediate_sdp_message, |
| 594 | 594 | .stop_dp_info_packets = |
| 595 | 595 | enc1_stream_encoder_stop_dp_info_packets, |
| 596 | − .reset_fifo = | |
| 597 | − enc1_stream_encoder_reset_fifo, | |
| 598 | 596 | .dp_blank = |
| 599 | 597 | enc1_stream_encoder_dp_blank, |
| 600 | 598 | .dp_unblank = |
| @@ -789,8 +789,6 @@ static const struct stream_encoder_funcs dcn30_str_enc_funcs = { · 788 unmodified lines | ||
| 789 | 789 | enc3_stream_encoder_update_dp_info_packets, |
| 790 | 790 | .stop_dp_info_packets = |
| 791 | 791 | enc1_stream_encoder_stop_dp_info_packets, |
| 792 | − .reset_fifo = | |
| 793 | − enc1_stream_encoder_reset_fifo, | |
| 794 | 792 | .dp_blank = |
| 795 | 793 | enc1_stream_encoder_dp_blank, |
| 796 | 794 | .dp_unblank = |
| @@ -164,10 +164,6 @@ struct stream_encoder_funcs { · 163 unmodified lines | ||
| 164 | 164 | void (*stop_dp_info_packets)( |
| 165 | 165 | struct stream_encoder *enc); |
| 166 | 166 | |
| 167 | − void (*reset_fifo)( | |
| 168 | − struct stream_encoder *enc | |
| 169 | − ); | |
| 170 | − | |
| 171 | 167 | void (*dp_blank)( |
| 172 | 168 | struct dc_link *link, |
| 173 | 169 | struct stream_encoder *enc); |
| @@ -3696,14 +3696,14 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, · 3695 unmodified lines | ||
| 3696 | 3696 | |
| 3697 | 3697 | static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) |
| 3698 | 3698 | { |
| 3699 | − struct smu_table_context *table_context = &smu->smu_table; | |
| 3700 | − PPTable_t *smc_pptable = table_context->driver_pptable; | |
| 3699 | + uint16_t *mgpu_fan_boost_limit_rpm; | |
| 3701 | 3700 | |
| 3701 | + GET_PPTABLE_MEMBER(MGpuFanBoostLimitRpm, &mgpu_fan_boost_limit_rpm); | |
| 3702 | 3702 | /* |
| 3703 | 3703 | * Skip the MGpuFanBoost setting for those ASICs |
| 3704 | 3704 | * which do not support it |
| 3705 | 3705 | */ |
| 3706 | − if (!smc_pptable->MGpuFanBoostLimitRpm) | |
| 3706 | + if (*mgpu_fan_boost_limit_rpm == 0) | |
| 3707 | 3707 | return 0; |
| 3708 | 3708 | |
| 3709 | 3709 | return smu_cmn_send_smc_msg_with_param(smu, |
| @@ -959,6 +959,9 @@ static int check_overlay_dst(struct intel_overlay *overlay, · 958 unmodified lines | ||
| 959 | 959 | const struct intel_crtc_state *pipe_config = |
| 960 | 960 | overlay->crtc->config; |
| 961 | 961 | |
| 962 | + if (rec->dst_height == 0 || rec->dst_width == 0) | |
| 963 | + return -EINVAL; | |
| 964 | + | |
| 962 | 965 | if (rec->dst_x < pipe_config->pipe_src_w && |
| 963 | 966 | rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w && |
| 964 | 967 | rec->dst_y < pipe_config->pipe_src_h && |
| @@ -345,10 +345,11 @@ static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port) · 344 unmodified lines | ||
| 345 | 345 | static bool adl_tc_phy_status_complete(struct intel_digital_port *dig_port) |
| 346 | 346 | { |
| 347 | 347 | struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); |
| 348 | + enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); | |
| 348 | 349 | struct intel_uncore *uncore = &i915->uncore; |
| 349 | 350 | u32 val; |
| 350 | 351 | |
| 351 | − val = intel_uncore_read(uncore, TCSS_DDI_STATUS(dig_port->tc_phy_fia_idx)); | |
| 352 | + val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port)); | |
| 352 | 353 | if (val == 0xffffffff) { |
| 353 | 354 | drm_dbg_kms(&i915->drm, |
| 354 | 355 | "Port %s: PHY in TCCOLD, assuming not complete\n", |
| @@ -2505,9 +2505,14 @@ static int eb_pin_timeline(struct i915_execbuffer *eb, struct intel_context *ce, · 2504 unmodified lines | ||
| 2505 | 2505 | timeout) < 0) { |
| 2506 | 2506 | i915_request_put(rq); |
| 2507 | 2507 | |
| 2508 | − tl = intel_context_timeline_lock(ce); | |
| 2508 | + /* | |
| 2509 | + * Error path, cannot use intel_context_timeline_lock as | |
| 2510 | + * that is user interruptable and this clean up step | |
| 2511 | + * must be done. | |
| 2512 | + */ | |
| 2513 | + mutex_lock(&ce->timeline->mutex); | |
| 2509 | 2514 | intel_context_exit(ce); |
| 2510 | − intel_context_timeline_unlock(tl); | |
| 2515 | + mutex_unlock(&ce->timeline->mutex); | |
| 2511 | 2516 | |
| 2512 | 2517 | if (nonblock) |
| 2513 | 2518 | return -EWOULDBLOCK; |
| @@ -206,6 +206,11 @@ struct intel_guc { · 205 unmodified lines | ||
| 206 | 206 | * context usage for overflows. |
| 207 | 207 | */ |
| 208 | 208 | struct delayed_work work; |
| 209 | + | |
| 210 | + /** | |
| 211 | + * @shift: Right shift value for the gpm timestamp | |
| 212 | + */ | |
| 213 | + u32 shift; | |
| 209 | 214 | } timestamp; |
| 210 | 215 | |
| 211 | 216 | #ifdef CONFIG_DRM_I915_SELFTEST |
| @@ -1113,6 +1113,19 @@ __extend_last_switch(struct intel_guc *guc, u64 *prev_start, u32 new_start) · 1112 unmodified lines | ||
| 1113 | 1113 | if (new_start == lower_32_bits(*prev_start)) |
| 1114 | 1114 | return; |
| 1115 | 1115 | |
| 1116 | + /* | |
| 1117 | + * When gt is unparked, we update the gt timestamp and start the ping | |
| 1118 | + * worker that updates the gt_stamp every POLL_TIME_CLKS. As long as gt | |
| 1119 | + * is unparked, all switched in contexts will have a start time that is | |
| 1120 | + * within +/- POLL_TIME_CLKS of the most recent gt_stamp. | |
| 1121 | + * | |
| 1122 | + * If neither gt_stamp nor new_start has rolled over, then the | |
| 1123 | + * gt_stamp_hi does not need to be adjusted, however if one of them has | |
| 1124 | + * rolled over, we need to adjust gt_stamp_hi accordingly. | |
| 1125 | + * | |
| 1126 | + * The below conditions address the cases of new_start rollover and | |
| 1127 | + * gt_stamp_last rollover respectively. | |
| 1128 | + */ | |
| 1116 | 1129 | if (new_start < gt_stamp_last && |
| 1117 | 1130 | (new_start - gt_stamp_last) <= POLL_TIME_CLKS) |
| 1118 | 1131 | gt_stamp_hi++; |
| @@ -1124,17 +1137,45 @@ __extend_last_switch(struct intel_guc *guc, u64 *prev_start, u32 new_start) · 5 unmodified lines | ||
| 1124 | 1137 | *prev_start = ((u64)gt_stamp_hi << 32) | new_start; |
| 1125 | 1138 | } |
| 1126 | 1139 | |
| 1127 | −static void guc_update_engine_gt_clks(struct intel_engine_cs *engine) | |
| 1140 | +/* | |
| 1141 | + * GuC updates shared memory and KMD reads it. Since this is not synchronized, | |
| 1142 | + * we run into a race where the value read is inconsistent. Sometimes the | |
| 1143 | + * inconsistency is in reading the upper MSB bytes of the last_in value when | |
| 1144 | + * this race occurs. 2 types of cases are seen - upper 8 bits are zero and upper | |
| 1145 | + * 24 bits are zero. Since these are non-zero values, it is non-trivial to | |
| 1146 | + * determine validity of these values. Instead we read the values multiple times | |
| 1147 | + * until they are consistent. In test runs, 3 attempts results in consistent | |
| 1148 | + * values. The upper bound is set to 6 attempts and may need to be tuned as per | |
| 1149 | + * any new occurences. | |
| 1150 | + */ | |
| 1151 | +static void __get_engine_usage_record(struct intel_engine_cs *engine, | |
| 1152 | + u32 *last_in, u32 *id, u32 *total) | |
| 1128 | 1153 | { |
| 1129 | 1154 | struct guc_engine_usage_record *rec = intel_guc_engine_usage(engine); |
| 1155 | + int i = 0; | |
| 1156 | + | |
| 1157 | + do { | |
| 1158 | + *last_in = READ_ONCE(rec->last_switch_in_stamp); | |
| 1159 | + *id = READ_ONCE(rec->current_context_index); | |
| 1160 | + *total = READ_ONCE(rec->total_runtime); | |
| 1161 | + | |
| 1162 | + if (READ_ONCE(rec->last_switch_in_stamp) == *last_in && | |
| 1163 | + READ_ONCE(rec->current_context_index) == *id && | |
| 1164 | + READ_ONCE(rec->total_runtime) == *total) | |
| 1165 | + break; | |
| 1166 | + } while (++i < 6); | |
| 1167 | +} | |
| 1168 | + | |
| 1169 | +static void guc_update_engine_gt_clks(struct intel_engine_cs *engine) | |
| 1170 | +{ | |
| 1130 | 1171 | struct intel_engine_guc_stats *stats = &engine->stats.guc; |
| 1131 | 1172 | struct intel_guc *guc = &engine->gt->uc.guc; |
| 1132 | − u32 last_switch = rec->last_switch_in_stamp; | |
| 1133 | − u32 ctx_id = rec->current_context_index; | |
| 1134 | − u32 total = rec->total_runtime; | |
| 1173 | + u32 last_switch, ctx_id, total; | |
| 1135 | 1174 | |
| 1136 | 1175 | lockdep_assert_held(&guc->timestamp.lock); |
| 1137 | 1176 | |
| 1177 | + __get_engine_usage_record(engine, &last_switch, &ctx_id, &total); | |
| 1178 | + | |
| 1138 | 1179 | stats->running = ctx_id != ~0U && last_switch; |
| 1139 | 1180 | if (stats->running) |
| 1140 | 1181 | __extend_last_switch(guc, &stats->start_gt_clk, last_switch); |
| @@ -1149,23 +1190,51 @@ static void guc_update_engine_gt_clks(struct intel_engine_cs *engine) · 8 unmodified lines | ||
| 1149 | 1190 | } |
| 1150 | 1191 | } |
| 1151 | 1192 | |
| 1152 | −static void guc_update_pm_timestamp(struct intel_guc *guc, | |
| 1153 | − struct intel_engine_cs *engine, | |
| 1154 | − ktime_t *now) | |
| 1193 | +static u32 gpm_timestamp_shift(struct intel_gt *gt) | |
| 1194 | +{ | |
| 1195 | + intel_wakeref_t wakeref; | |
| 1196 | + u32 reg, shift; | |
| 1197 | + | |
| 1198 | + with_intel_runtime_pm(gt->uncore->rpm, wakeref) | |
| 1199 | + reg = intel_uncore_read(gt->uncore, RPM_CONFIG0); | |
| 1200 | + | |
| 1201 | + shift = (reg & GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >> | |
| 1202 | + GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT; | |
| 1203 | + | |
| 1204 | + return 3 - shift; | |
| 1205 | +} | |
| 1206 | + | |
| 1207 | +static u64 gpm_timestamp(struct intel_gt *gt) | |
| 1208 | +{ | |
| 1209 | + u32 lo, hi, old_hi, loop = 0; | |
| 1210 | + | |
| 1211 | + hi = intel_uncore_read(gt->uncore, MISC_STATUS1); | |
| 1212 | + do { | |
| 1213 | + lo = intel_uncore_read(gt->uncore, MISC_STATUS0); | |
| 1214 | + old_hi = hi; | |
| 1215 | + hi = intel_uncore_read(gt->uncore, MISC_STATUS1); | |
| 1216 | + } while (old_hi != hi && loop++ < 2); | |
| 1217 | + | |
| 1218 | + return ((u64)hi << 32) | lo; | |
| 1219 | +} | |
| 1220 | + | |
| 1221 | +static void guc_update_pm_timestamp(struct intel_guc *guc, ktime_t *now) | |
| 1155 | 1222 | { |
| 1156 | − u32 gt_stamp_now, gt_stamp_hi; | |
| 1223 | + struct intel_gt *gt = guc_to_gt(guc); | |
| 1224 | + u32 gt_stamp_lo, gt_stamp_hi; | |
| 1225 | + u64 gpm_ts; | |
| 1157 | 1226 | |
| 1158 | 1227 | lockdep_assert_held(&guc->timestamp.lock); |
| 1159 | 1228 | |
| 1160 | 1229 | gt_stamp_hi = upper_32_bits(guc->timestamp.gt_stamp); |
| 1161 | − gt_stamp_now = intel_uncore_read(engine->uncore, | |
| 1162 | − RING_TIMESTAMP(engine->mmio_base)); | |
| 1230 | + gpm_ts = gpm_timestamp(gt) >> guc->timestamp.shift; | |
| 1231 | + gt_stamp_lo = lower_32_bits(gpm_ts); | |
| 1163 | 1232 | *now = ktime_get(); |
| 1164 | 1233 | |
| 1165 | − if (gt_stamp_now < lower_32_bits(guc->timestamp.gt_stamp)) | |
| 1234 | + if (gt_stamp_lo < lower_32_bits(guc->timestamp.gt_stamp)) | |
| 1166 | 1235 | gt_stamp_hi++; |
| 1167 | 1236 | |
| 1168 | − guc->timestamp.gt_stamp = ((u64)gt_stamp_hi << 32) | gt_stamp_now; | |
| 1237 | + guc->timestamp.gt_stamp = ((u64)gt_stamp_hi << 32) | gt_stamp_lo; | |
| 1169 | 1238 | } |
| 1170 | 1239 | |
| 1171 | 1240 | /* |
| @@ -1208,8 +1277,12 @@ static ktime_t guc_engine_busyness(struct intel_engine_cs *engine, ktime_t *now) · 36 unmodified lines | ||
| 1208 | 1277 | if (!in_reset && intel_gt_pm_get_if_awake(gt)) { |
| 1209 | 1278 | stats_saved = *stats; |
| 1210 | 1279 | gt_stamp_saved = guc->timestamp.gt_stamp; |
| 1280 | + /* | |
| 1281 | + * Update gt_clks, then gt timestamp to simplify the 'gt_stamp - | |
| 1282 | + * start_gt_clk' calculation below for active engines. | |
| 1283 | + */ | |
| 1211 | 1284 | guc_update_engine_gt_clks(engine); |
| 1212 | − guc_update_pm_timestamp(guc, engine, now); | |
| 1285 | + guc_update_pm_timestamp(guc, now); | |
| 1213 | 1286 | intel_gt_pm_put_async(gt); |
| 1214 | 1287 | if (i915_reset_count(gpu_error) != reset_count) { |
| 1215 | 1288 | *stats = stats_saved; |
| @@ -1241,8 +1314,8 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc) · 25 unmodified lines | ||
| 1241 | 1314 | |
| 1242 | 1315 | spin_lock_irqsave(&guc->timestamp.lock, flags); |
| 1243 | 1316 | |
| 1317 | + guc_update_pm_timestamp(guc, &unused); | |
| 1244 | 1318 | for_each_engine(engine, gt, id) { |
| 1245 | − guc_update_pm_timestamp(guc, engine, &unused); | |
| 1246 | 1319 | guc_update_engine_gt_clks(engine); |
| 1247 | 1320 | engine->stats.guc.prev_total = 0; |
| 1248 | 1321 | } |
| @@ -1259,10 +1332,11 @@ static void __update_guc_busyness_stats(struct intel_guc *guc) · 10 unmodified lines | ||
| 1259 | 1332 | ktime_t unused; |
| 1260 | 1333 | |
| 1261 | 1334 | spin_lock_irqsave(&guc->timestamp.lock, flags); |
| 1262 | − for_each_engine(engine, gt, id) { | |
| 1263 | − guc_update_pm_timestamp(guc, engine, &unused); | |
| 1335 | + | |
| 1336 | + guc_update_pm_timestamp(guc, &unused); | |
| 1337 | + for_each_engine(engine, gt, id) | |
| 1264 | 1338 | guc_update_engine_gt_clks(engine); |
| 1265 | − } | |
| 1339 | + | |
| 1266 | 1340 | spin_unlock_irqrestore(&guc->timestamp.lock, flags); |
| 1267 | 1341 | } |
| 1268 | 1342 | |
| @@ -1335,10 +1409,15 @@ void intel_guc_busyness_park(struct intel_gt *gt) · 66 unmodified lines | ||
| 1335 | 1409 | void intel_guc_busyness_unpark(struct intel_gt *gt) |
| 1336 | 1410 | { |
| 1337 | 1411 | struct intel_guc *guc = >->uc.guc; |
| 1412 | + unsigned long flags; | |
| 1413 | + ktime_t unused; | |
| 1338 | 1414 | |
| 1339 | 1415 | if (!guc_submission_initialized(guc)) |
| 1340 | 1416 | return; |
| 1341 | 1417 | |
| 1418 | + spin_lock_irqsave(&guc->timestamp.lock, flags); | |
| 1419 | + guc_update_pm_timestamp(guc, &unused); | |
| 1420 | + spin_unlock_irqrestore(&guc->timestamp.lock, flags); | |
| 1342 | 1421 | mod_delayed_work(system_highpri_wq, &guc->timestamp.work, |
| 1343 | 1422 | guc->timestamp.ping_delay); |
| 1344 | 1423 | } |
| @@ -1783,6 +1862,7 @@ int intel_guc_submission_init(struct intel_guc *guc) · 438 unmodified lines | ||
| 1783 | 1862 | spin_lock_init(&guc->timestamp.lock); |
| 1784 | 1863 | INIT_DELAYED_WORK(&guc->timestamp.work, guc_timestamp_ping); |
| 1785 | 1864 | guc->timestamp.ping_delay = (POLL_TIME_CLKS / gt->clock_frequency + 1) * HZ; |
| 1865 | + guc->timestamp.shift = gpm_timestamp_shift(gt); | |
| 1786 | 1866 | |
| 1787 | 1867 | return 0; |
| 1788 | 1868 | } |
| @@ -1522,7 +1522,7 @@ capture_engine(struct intel_engine_cs *engine, · 1521 unmodified lines | ||
| 1522 | 1522 | struct i915_request *rq = NULL; |
| 1523 | 1523 | unsigned long flags; |
| 1524 | 1524 | |
| 1525 | − ee = intel_engine_coredump_alloc(engine, GFP_KERNEL); | |
| 1525 | + ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL); | |
| 1526 | 1526 | if (!ee) |
| 1527 | 1527 | return NULL; |
| 1528 | 1528 | |
| @@ -2684,7 +2684,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 2683 unmodified lines | ||
| 2684 | 2684 | #define RING_WAIT (1 << 11) /* gen3+, PRBx_CTL */ |
| 2685 | 2685 | #define RING_WAIT_SEMAPHORE (1 << 10) /* gen6+ */ |
| 2686 | 2686 | |
| 2687 | −#define GUCPMTIMESTAMP _MMIO(0xC3E8) | |
| 2687 | +#define MISC_STATUS0 _MMIO(0xA500) | |
| 2688 | +#define MISC_STATUS1 _MMIO(0xA504) | |
| 2688 | 2689 | |
| 2689 | 2690 | /* There are 16 64-bit CS General Purpose Registers per-engine on Gen8+ */ |
| 2690 | 2691 | #define GEN8_RING_CS_GPR(base, n) _MMIO((base) + 0x600 + (n) * 8) |
| @@ -158,12 +158,6 @@ static void kmb_plane_atomic_disable(struct drm_plane *plane, · 157 unmodified lines | ||
| 158 | 158 | case LAYER_1: |
| 159 | 159 | kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL2_ENABLE; |
| 160 | 160 | break; |
| 161 | − case LAYER_2: | |
| 162 | − kmb->plane_status[plane_id].ctrl = LCD_CTRL_GL1_ENABLE; | |
| 163 | − break; | |
| 164 | − case LAYER_3: | |
| 165 | − kmb->plane_status[plane_id].ctrl = LCD_CTRL_GL2_ENABLE; | |
| 166 | − break; | |
| 167 | 161 | } |
| 168 | 162 | |
| 169 | 163 | kmb->plane_status[plane_id].disable = true; |
| @@ -361,7 +361,11 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, · 360 unmodified lines | ||
| 361 | 361 | bridge_state = |
| 362 | 362 | drm_atomic_get_new_bridge_state(state, |
| 363 | 363 | mxsfb->bridge); |
| 364 | − bus_format = bridge_state->input_bus_cfg.format; | |
| 364 | + if (!bridge_state) | |
| 365 | + bus_format = MEDIA_BUS_FMT_FIXED; | |
| 366 | + else | |
| 367 | + bus_format = bridge_state->input_bus_cfg.format; | |
| 368 | + | |
| 365 | 369 | if (bus_format == MEDIA_BUS_FMT_FIXED) { |
| 366 | 370 | dev_warn_once(drm->dev, |
| 367 | 371 | "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n" |
| @@ -38,7 +38,7 @@ nvbios_addr(struct nvkm_bios *bios, u32 *addr, u8 size) · 37 unmodified lines | ||
| 38 | 38 | *addr += bios->imaged_addr; |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | − if (unlikely(*addr + size >= bios->size)) { | |
| 41 | + if (unlikely(*addr + size > bios->size)) { | |
| 42 | 42 | nvkm_error(&bios->subdev, "OOB %d %08x %08x\n", size, p, *addr); |
| 43 | 43 | return false; |
| 44 | 44 | } |
| @@ -3322,7 +3322,7 @@ static int cm_lap_handler(struct cm_work *work) · 3321 unmodified lines | ||
| 3322 | 3322 | ret = cm_init_av_by_path(param->alternate_path, NULL, &alt_av); |
| 3323 | 3323 | if (ret) { |
| 3324 | 3324 | rdma_destroy_ah_attr(&ah_attr); |
| 3325 | − return -EINVAL; | |
| 3325 | + goto deref; | |
| 3326 | 3326 | } |
| 3327 | 3327 | |
| 3328 | 3328 | spin_lock_irq(&cm_id_priv->lock); |
| @@ -67,8 +67,8 @@ static const char * const cma_events[] = { · 66 unmodified lines | ||
| 67 | 67 | [RDMA_CM_EVENT_TIMEWAIT_EXIT] = "timewait exit", |
| 68 | 68 | }; |
| 69 | 69 | |
| 70 | −static void cma_set_mgid(struct rdma_id_private *id_priv, struct sockaddr *addr, | |
| 71 | − union ib_gid *mgid); | |
| 70 | +static void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid, | |
| 71 | + enum ib_gid_type gid_type); | |
| 72 | 72 | |
| 73 | 73 | const char *__attribute_const__ rdma_event_msg(enum rdma_cm_event_type event) |
| 74 | 74 | { |
| @@ -1846,17 +1846,19 @@ static void destroy_mc(struct rdma_id_private *id_priv, · 1771 unmodified lines | ||
| 1846 | 1846 | if (dev_addr->bound_dev_if) |
| 1847 | 1847 | ndev = dev_get_by_index(dev_addr->net, |
| 1848 | 1848 | dev_addr->bound_dev_if); |
| 1849 | − if (ndev) { | |
| 1849 | + if (ndev && !send_only) { | |
| 1850 | + enum ib_gid_type gid_type; | |
| 1850 | 1851 | union ib_gid mgid; |
| 1851 | 1852 | |
| 1852 | − cma_set_mgid(id_priv, (struct sockaddr *)&mc->addr, | |
| 1853 | − &mgid); | |
| 1854 | − | |
| 1855 | − if (!send_only) | |
| 1856 | − cma_igmp_send(ndev, &mgid, false); | |
| 1857 | − | |
| 1858 | − dev_put(ndev); | |
| 1853 | + gid_type = id_priv->cma_dev->default_gid_type | |
| 1854 | + [id_priv->id.port_num - | |
| 1855 | + rdma_start_port( | |
| 1856 | + id_priv->cma_dev->device)]; | |
| 1857 | + cma_iboe_set_mgid((struct sockaddr *)&mc->addr, &mgid, | |
| 1858 | + gid_type); | |
| 1859 | + cma_igmp_send(ndev, &mgid, false); | |
| 1859 | 1860 | } |
| 1861 | + dev_put(ndev); | |
| 1860 | 1862 | |
| 1861 | 1863 | cancel_work_sync(&mc->iboe_join.work); |
| 1862 | 1864 | } |
| @@ -95,6 +95,7 @@ struct ucma_context { · 94 unmodified lines | ||
| 95 | 95 | u64 uid; |
| 96 | 96 | |
| 97 | 97 | struct list_head list; |
| 98 | + struct list_head mc_list; | |
| 98 | 99 | struct work_struct close_work; |
| 99 | 100 | }; |
| 100 | 101 | |
| @@ -105,6 +106,7 @@ struct ucma_multicast { · 4 unmodified lines | ||
| 105 | 106 | |
| 106 | 107 | u64 uid; |
| 107 | 108 | u8 join_state; |
| 109 | + struct list_head list; | |
| 108 | 110 | struct sockaddr_storage addr; |
| 109 | 111 | }; |
| 110 | 112 | |
| @@ -198,6 +200,7 @@ static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file) · 87 unmodified lines | ||
| 198 | 200 | |
| 199 | 201 | INIT_WORK(&ctx->close_work, ucma_close_id); |
| 200 | 202 | init_completion(&ctx->comp); |
| 203 | + INIT_LIST_HEAD(&ctx->mc_list); | |
| 201 | 204 | /* So list_del() will work if we don't do ucma_finish_ctx() */ |
| 202 | 205 | INIT_LIST_HEAD(&ctx->list); |
| 203 | 206 | ctx->file = file; |
| @@ -484,19 +487,19 @@ err1: · 280 unmodified lines | ||
| 484 | 487 | |
| 485 | 488 | static void ucma_cleanup_multicast(struct ucma_context *ctx) |
| 486 | 489 | { |
| 487 | − struct ucma_multicast *mc; | |
| 488 | − unsigned long index; | |
| 490 | + struct ucma_multicast *mc, *tmp; | |
| 489 | 491 | |
| 490 | − xa_for_each(&multicast_table, index, mc) { | |
| 491 | − if (mc->ctx != ctx) | |
| 492 | − continue; | |
| 492 | + xa_lock(&multicast_table); | |
| 493 | + list_for_each_entry_safe(mc, tmp, &ctx->mc_list, list) { | |
| 494 | + list_del(&mc->list); | |
| 493 | 495 | /* |
| 494 | 496 | * At this point mc->ctx->ref is 0 so the mc cannot leave the |
| 495 | 497 | * lock on the reader and this is enough serialization |
| 496 | 498 | */ |
| 497 | − xa_erase(&multicast_table, index); | |
| 499 | + __xa_erase(&multicast_table, mc->id); | |
| 498 | 500 | kfree(mc); |
| 499 | 501 | } |
| 502 | + xa_unlock(&multicast_table); | |
| 500 | 503 | } |
| 501 | 504 | |
| 502 | 505 | static void ucma_cleanup_mc_events(struct ucma_multicast *mc) |
| @@ -1469,12 +1472,16 @@ static ssize_t ucma_process_join(struct ucma_file *file, · 966 unmodified lines | ||
| 1469 | 1472 | mc->uid = cmd->uid; |
| 1470 | 1473 | memcpy(&mc->addr, addr, cmd->addr_size); |
| 1471 | 1474 | |
| 1472 | − if (xa_alloc(&multicast_table, &mc->id, NULL, xa_limit_32b, | |
| 1475 | + xa_lock(&multicast_table); | |
| 1476 | + if (__xa_alloc(&multicast_table, &mc->id, NULL, xa_limit_32b, | |
| 1473 | 1477 | GFP_KERNEL)) { |
| 1474 | 1478 | ret = -ENOMEM; |
| 1475 | 1479 | goto err_free_mc; |
| 1476 | 1480 | } |
| 1477 | 1481 | |
| 1482 | + list_add_tail(&mc->list, &ctx->mc_list); | |
| 1483 | + xa_unlock(&multicast_table); | |
| 1484 | + | |
| 1478 | 1485 | mutex_lock(&ctx->mutex); |
| 1479 | 1486 | ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *)&mc->addr, |
| 1480 | 1487 | join_state, mc); |
| @@ -1500,8 +1507,11 @@ err_leave_multicast: · 19 unmodified lines | ||
| 1500 | 1507 | mutex_unlock(&ctx->mutex); |
| 1501 | 1508 | ucma_cleanup_mc_events(mc); |
| 1502 | 1509 | err_xa_erase: |
| 1503 | − xa_erase(&multicast_table, mc->id); | |
| 1510 | + xa_lock(&multicast_table); | |
| 1511 | + list_del(&mc->list); | |
| 1512 | + __xa_erase(&multicast_table, mc->id); | |
| 1504 | 1513 | err_free_mc: |
| 1514 | + xa_unlock(&multicast_table); | |
| 1505 | 1515 | kfree(mc); |
| 1506 | 1516 | err_put_ctx: |
| 1507 | 1517 | ucma_put_ctx(ctx); |
| @@ -1569,15 +1579,17 @@ static ssize_t ucma_leave_multicast(struct ucma_file *file, · 61 unmodified lines | ||
| 1569 | 1579 | mc = ERR_PTR(-EINVAL); |
| 1570 | 1580 | else if (!refcount_inc_not_zero(&mc->ctx->ref)) |
| 1571 | 1581 | mc = ERR_PTR(-ENXIO); |
| 1572 | − else | |
| 1573 | − __xa_erase(&multicast_table, mc->id); | |
| 1574 | − xa_unlock(&multicast_table); | |
| 1575 | 1582 | |
| 1576 | 1583 | if (IS_ERR(mc)) { |
| 1584 | + xa_unlock(&multicast_table); | |
| 1577 | 1585 | ret = PTR_ERR(mc); |
| 1578 | 1586 | goto out; |
| 1579 | 1587 | } |
| 1580 | 1588 | |
| 1589 | + list_del(&mc->list); | |
| 1590 | + __xa_erase(&multicast_table, mc->id); | |
| 1591 | + xa_unlock(&multicast_table); | |
| 1592 | + | |
| 1581 | 1593 | mutex_lock(&mc->ctx->mutex); |
| 1582 | 1594 | rdma_leave_multicast(mc->ctx->cm_id, (struct sockaddr *) &mc->addr); |
| 1583 | 1595 | mutex_unlock(&mc->ctx->mutex); |
| @@ -55,7 +55,7 @@ union hfi1_ipoib_flow { · 54 unmodified lines | ||
| 55 | 55 | */ |
| 56 | 56 | struct ipoib_txreq { |
| 57 | 57 | struct sdma_txreq txreq; |
| 58 | − struct hfi1_sdma_header sdma_hdr; | |
| 58 | + struct hfi1_sdma_header *sdma_hdr; | |
| 59 | 59 | int sdma_status; |
| 60 | 60 | int complete; |
| 61 | 61 | struct hfi1_ipoib_dev_priv *priv; |
| @@ -22,26 +22,35 @@ static int hfi1_ipoib_dev_init(struct net_device *dev) · 21 unmodified lines | ||
| 22 | 22 | int ret; |
| 23 | 23 | |
| 24 | 24 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 25 | + if (!dev->tstats) | |
| 26 | + return -ENOMEM; | |
| 25 | 27 | |
| 26 | 28 | ret = priv->netdev_ops->ndo_init(dev); |
| 27 | 29 | if (ret) |
| 28 | − return ret; | |
| 30 | + goto out_ret; | |
| 29 | 31 | |
| 30 | 32 | ret = hfi1_netdev_add_data(priv->dd, |
| 31 | 33 | qpn_from_mac(priv->netdev->dev_addr), |
| 32 | 34 | dev); |
| 33 | 35 | if (ret < 0) { |
| 34 | 36 | priv->netdev_ops->ndo_uninit(dev); |
| 35 | − return ret; | |
| 37 | + goto out_ret; | |
| 36 | 38 | } |
| 37 | 39 | |
| 38 | 40 | return 0; |
| 41 | +out_ret: | |
| 42 | + free_percpu(dev->tstats); | |
| 43 | + dev->tstats = NULL; | |
| 44 | + return ret; | |
| 39 | 45 | } |
| 40 | 46 | |
| 41 | 47 | static void hfi1_ipoib_dev_uninit(struct net_device *dev) |
| 42 | 48 | { |
| 43 | 49 | struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev); |
| 44 | 50 | |
| 51 | + free_percpu(dev->tstats); | |
| 52 | + dev->tstats = NULL; | |
| 53 | + | |
| 45 | 54 | hfi1_netdev_remove_data(priv->dd, qpn_from_mac(priv->netdev->dev_addr)); |
| 46 | 55 | |
| 47 | 56 | priv->netdev_ops->ndo_uninit(dev); |
| @@ -166,12 +175,7 @@ static void hfi1_ipoib_netdev_dtor(struct net_device *dev) · 118 unmodified lines | ||
| 166 | 175 | hfi1_ipoib_rxq_deinit(priv->netdev); |
| 167 | 176 | |
| 168 | 177 | free_percpu(dev->tstats); |
| 169 | −} | |
| 170 | − | |
| 171 | −static void hfi1_ipoib_free_rdma_netdev(struct net_device *dev) | |
| 172 | −{ | |
| 173 | − hfi1_ipoib_netdev_dtor(dev); | |
| 174 | − free_netdev(dev); | |
| 178 | + dev->tstats = NULL; | |
| 175 | 179 | } |
| 176 | 180 | |
| 177 | 181 | static void hfi1_ipoib_set_id(struct net_device *dev, int id) |
| @@ -211,24 +215,23 @@ static int hfi1_ipoib_setup_rn(struct ib_device *device, · 33 unmodified lines | ||
| 211 | 215 | priv->port_num = port_num; |
| 212 | 216 | priv->netdev_ops = netdev->netdev_ops; |
| 213 | 217 | |
| 214 | − netdev->netdev_ops = &hfi1_ipoib_netdev_ops; | |
| 215 | − | |
| 216 | 218 | ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey); |
| 217 | 219 | |
| 218 | 220 | rc = hfi1_ipoib_txreq_init(priv); |
| 219 | 221 | if (rc) { |
| 220 | 222 | dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc); |
| 221 | − hfi1_ipoib_free_rdma_netdev(netdev); | |
| 222 | 223 | return rc; |
| 223 | 224 | } |
| 224 | 225 | |
| 225 | 226 | rc = hfi1_ipoib_rxq_init(netdev); |
| 226 | 227 | if (rc) { |
| 227 | 228 | dd_dev_err(dd, "IPoIB netdev RX init - failed(%d)\n", rc); |
| 228 | − hfi1_ipoib_free_rdma_netdev(netdev); | |
| 229 | + hfi1_ipoib_txreq_deinit(priv); | |
| 229 | 230 | return rc; |
| 230 | 231 | } |
| 231 | 232 | |
| 233 | + netdev->netdev_ops = &hfi1_ipoib_netdev_ops; | |
| 234 | + | |
| 232 | 235 | netdev->priv_destructor = hfi1_ipoib_netdev_dtor; |
| 233 | 236 | netdev->needs_free_netdev = true; |
| 234 | 237 | |
| @@ -122,7 +122,7 @@ static void hfi1_ipoib_free_tx(struct ipoib_txreq *tx, int budget) · 121 unmodified lines | ||
| 122 | 122 | dd_dev_warn(priv->dd, |
| 123 | 123 | "%s: Status = 0x%x pbc 0x%llx txq = %d sde = %d\n", |
| 124 | 124 | __func__, tx->sdma_status, |
| 125 | − le64_to_cpu(tx->sdma_hdr.pbc), tx->txq->q_idx, | |
| 125 | + le64_to_cpu(tx->sdma_hdr->pbc), tx->txq->q_idx, | |
| 126 | 126 | tx->txq->sde->this_idx); |
| 127 | 127 | } |
| 128 | 128 | |
| @@ -231,7 +231,7 @@ static int hfi1_ipoib_build_tx_desc(struct ipoib_txreq *tx, · 102 unmodified lines | ||
| 231 | 231 | { |
| 232 | 232 | struct hfi1_devdata *dd = txp->dd; |
| 233 | 233 | struct sdma_txreq *txreq = &tx->txreq; |
| 234 | − struct hfi1_sdma_header *sdma_hdr = &tx->sdma_hdr; | |
| 234 | + struct hfi1_sdma_header *sdma_hdr = tx->sdma_hdr; | |
| 235 | 235 | u16 pkt_bytes = |
| 236 | 236 | sizeof(sdma_hdr->pbc) + (txp->hdr_dwords << 2) + tx->skb->len; |
| 237 | 237 | int ret; |
| @@ -256,7 +256,7 @@ static void hfi1_ipoib_build_ib_tx_headers(struct ipoib_txreq *tx, · 18 unmodified lines | ||
| 256 | 256 | struct ipoib_txparms *txp) |
| 257 | 257 | { |
| 258 | 258 | struct hfi1_ipoib_dev_priv *priv = tx->txq->priv; |
| 259 | − struct hfi1_sdma_header *sdma_hdr = &tx->sdma_hdr; | |
| 259 | + struct hfi1_sdma_header *sdma_hdr = tx->sdma_hdr; | |
| 260 | 260 | struct sk_buff *skb = tx->skb; |
| 261 | 261 | struct hfi1_pportdata *ppd = ppd_from_ibp(txp->ibp); |
| 262 | 262 | struct rdma_ah_attr *ah_attr = txp->ah_attr; |
| @@ -483,7 +483,7 @@ static int hfi1_ipoib_send_dma_single(struct net_device *dev, · 220 unmodified lines | ||
| 483 | 483 | if (likely(!ret)) { |
| 484 | 484 | tx_ok: |
| 485 | 485 | trace_sdma_output_ibhdr(txq->priv->dd, |
| 486 | − &tx->sdma_hdr.hdr, | |
| 486 | + &tx->sdma_hdr->hdr, | |
| 487 | 487 | ib_is_sc5(txp->flow.sc5)); |
| 488 | 488 | hfi1_ipoib_check_queue_depth(txq); |
| 489 | 489 | return NETDEV_TX_OK; |
| @@ -547,7 +547,7 @@ static int hfi1_ipoib_send_dma_list(struct net_device *dev, · 57 unmodified lines | ||
| 547 | 547 | hfi1_ipoib_check_queue_depth(txq); |
| 548 | 548 | |
| 549 | 549 | trace_sdma_output_ibhdr(txq->priv->dd, |
| 550 | − &tx->sdma_hdr.hdr, | |
| 550 | + &tx->sdma_hdr->hdr, | |
| 551 | 551 | ib_is_sc5(txp->flow.sc5)); |
| 552 | 552 | |
| 553 | 553 | if (!netdev_xmit_more()) |
| @@ -683,7 +683,8 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv) · 129 unmodified lines | ||
| 683 | 683 | { |
| 684 | 684 | struct net_device *dev = priv->netdev; |
| 685 | 685 | u32 tx_ring_size, tx_item_size; |
| 686 | − int i; | |
| 686 | + struct hfi1_ipoib_circ_buf *tx_ring; | |
| 687 | + int i, j; | |
| 687 | 688 | |
| 688 | 689 | /* |
| 689 | 690 | * Ring holds 1 less than tx_ring_size |
| @@ -701,7 +702,9 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv) · 11 unmodified lines | ||
| 701 | 702 | |
| 702 | 703 | for (i = 0; i < dev->num_tx_queues; i++) { |
| 703 | 704 | struct hfi1_ipoib_txq *txq = &priv->txqs[i]; |
| 705 | + struct ipoib_txreq *tx; | |
| 704 | 706 | |
| 707 | + tx_ring = &txq->tx_ring; | |
| 705 | 708 | iowait_init(&txq->wait, |
| 706 | 709 | 0, |
| 707 | 710 | hfi1_ipoib_flush_txq, |
| @@ -725,14 +728,19 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv) · 17 unmodified lines | ||
| 725 | 728 | priv->dd->node); |
| 726 | 729 | |
| 727 | 730 | txq->tx_ring.items = |
| 728 | − kcalloc_node(tx_ring_size, tx_item_size, | |
| 729 | − GFP_KERNEL, priv->dd->node); | |
| 731 | + kvzalloc_node(array_size(tx_ring_size, tx_item_size), | |
| 732 | + GFP_KERNEL, priv->dd->node); | |
| 730 | 733 | if (!txq->tx_ring.items) |
| 731 | 734 | goto free_txqs; |
| 732 | 735 | |
| 733 | 736 | txq->tx_ring.max_items = tx_ring_size; |
| 734 | − txq->tx_ring.shift = ilog2(tx_ring_size); | |
| 737 | + txq->tx_ring.shift = ilog2(tx_item_size); | |
| 735 | 738 | txq->tx_ring.avail = hfi1_ipoib_ring_hwat(txq); |
| 739 | + tx_ring = &txq->tx_ring; | |
| 740 | + for (j = 0; j < tx_ring_size; j++) | |
| 741 | + hfi1_txreq_from_idx(tx_ring, j)->sdma_hdr = | |
| 742 | + kzalloc_node(sizeof(*tx->sdma_hdr), | |
| 743 | + GFP_KERNEL, priv->dd->node); | |
| 736 | 744 | |
| 737 | 745 | netif_tx_napi_add(dev, &txq->napi, |
| 738 | 746 | hfi1_ipoib_poll_tx_ring, |
| @@ -746,7 +754,10 @@ free_txqs: · 7 unmodified lines | ||
| 746 | 754 | struct hfi1_ipoib_txq *txq = &priv->txqs[i]; |
| 747 | 755 | |
| 748 | 756 | netif_napi_del(&txq->napi); |
| 749 | − kfree(txq->tx_ring.items); | |
| 757 | + tx_ring = &txq->tx_ring; | |
| 758 | + for (j = 0; j < tx_ring_size; j++) | |
| 759 | + kfree(hfi1_txreq_from_idx(tx_ring, j)->sdma_hdr); | |
| 760 | + kvfree(tx_ring->items); | |
| 750 | 761 | } |
| 751 | 762 | |
| 752 | 763 | kfree(priv->txqs); |
| @@ -780,17 +791,20 @@ static void hfi1_ipoib_drain_tx_list(struct hfi1_ipoib_txq *txq) · 27 unmodified lines | ||
| 780 | 791 | |
| 781 | 792 | void hfi1_ipoib_txreq_deinit(struct hfi1_ipoib_dev_priv *priv) |
| 782 | 793 | { |
| 783 | − int i; | |
| 794 | + int i, j; | |
| 784 | 795 | |
| 785 | 796 | for (i = 0; i < priv->netdev->num_tx_queues; i++) { |
| 786 | 797 | struct hfi1_ipoib_txq *txq = &priv->txqs[i]; |
| 798 | + struct hfi1_ipoib_circ_buf *tx_ring = &txq->tx_ring; | |
| 787 | 799 | |
| 788 | 800 | iowait_cancel_work(&txq->wait); |
| 789 | 801 | iowait_sdma_drain(&txq->wait); |
| 790 | 802 | hfi1_ipoib_drain_tx_list(txq); |
| 791 | 803 | netif_napi_del(&txq->napi); |
| 792 | 804 | hfi1_ipoib_drain_tx_ring(txq); |
| 793 | − kfree(txq->tx_ring.items); | |
| 805 | + for (j = 0; j < tx_ring->max_items; j++) | |
| 806 | + kfree(hfi1_txreq_from_idx(tx_ring, j)->sdma_hdr); | |
| 807 | + kvfree(tx_ring->items); | |
| 794 | 808 | } |
| 795 | 809 | |
| 796 | 810 | kfree(priv->txqs); |
| @@ -3237,7 +3237,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, · 3236 unmodified lines | ||
| 3237 | 3237 | case MLX4_DEV_EVENT_PORT_MGMT_CHANGE: |
| 3238 | 3238 | ew = kmalloc(sizeof *ew, GFP_ATOMIC); |
| 3239 | 3239 | if (!ew) |
| 3240 | − break; | |
| 3240 | + return; | |
| 3241 | 3241 | |
| 3242 | 3242 | INIT_WORK(&ew->work, handle_port_mgmt_change_event); |
| 3243 | 3243 | memcpy(&ew->ib_eqe, eqe, sizeof *eqe); |
| @@ -3073,6 +3073,8 @@ do_write: · 3072 unmodified lines | ||
| 3073 | 3073 | case IB_WR_ATOMIC_FETCH_AND_ADD: |
| 3074 | 3074 | if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) |
| 3075 | 3075 | goto inv_err; |
| 3076 | + if (unlikely(wqe->atomic_wr.remote_addr & (sizeof(u64) - 1))) | |
| 3077 | + goto inv_err; | |
| 3076 | 3078 | if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64), |
| 3077 | 3079 | wqe->atomic_wr.remote_addr, |
| 3078 | 3080 | wqe->atomic_wr.rkey, |
| @@ -644,14 +644,9 @@ static inline struct siw_sqe *orq_get_current(struct siw_qp *qp) · 643 unmodified lines | ||
| 644 | 644 | return &qp->orq[qp->orq_get % qp->attrs.orq_size]; |
| 645 | 645 | } |
| 646 | 646 | |
| 647 | −static inline struct siw_sqe *orq_get_tail(struct siw_qp *qp) | |
| 648 | −{ | |
| 649 | − return &qp->orq[qp->orq_put % qp->attrs.orq_size]; | |
| 650 | −} | |
| 651 | − | |
| 652 | 647 | static inline struct siw_sqe *orq_get_free(struct siw_qp *qp) |
| 653 | 648 | { |
| 654 | − struct siw_sqe *orq_e = orq_get_tail(qp); | |
| 649 | + struct siw_sqe *orq_e = &qp->orq[qp->orq_put % qp->attrs.orq_size]; | |
| 655 | 650 | |
| 656 | 651 | if (READ_ONCE(orq_e->flags) == 0) |
| 657 | 652 | return orq_e; |
| @@ -1153,11 +1153,12 @@ static int siw_check_tx_fence(struct siw_qp *qp) · 1152 unmodified lines | ||
| 1153 | 1153 | |
| 1154 | 1154 | spin_lock_irqsave(&qp->orq_lock, flags); |
| 1155 | 1155 | |
| 1156 | − rreq = orq_get_current(qp); | |
| 1157 | − | |
| 1158 | 1156 | /* free current orq entry */ |
| 1157 | + rreq = orq_get_current(qp); | |
| 1159 | 1158 | WRITE_ONCE(rreq->flags, 0); |
| 1160 | 1159 | |
| 1160 | + qp->orq_get++; | |
| 1161 | + | |
| 1161 | 1162 | if (qp->tx_ctx.orq_fence) { |
| 1162 | 1163 | if (unlikely(tx_waiting->wr_status != SIW_WR_QUEUED)) { |
| 1163 | 1164 | pr_warn("siw: [QP %u]: fence resume: bad status %d\n", |
| @@ -1165,10 +1166,12 @@ static int siw_check_tx_fence(struct siw_qp *qp) · 1 unmodified line | ||
| 1165 | 1166 | rv = -EPROTO; |
| 1166 | 1167 | goto out; |
| 1167 | 1168 | } |
| 1168 | − /* resume SQ processing */ | |
| 1169 | + /* resume SQ processing, if possible */ | |
| 1169 | 1170 | if (tx_waiting->sqe.opcode == SIW_OP_READ || |
| 1170 | 1171 | tx_waiting->sqe.opcode == SIW_OP_READ_LOCAL_INV) { |
| 1171 | − rreq = orq_get_tail(qp); | |
| 1172 | + | |
| 1173 | + /* SQ processing was stopped because of a full ORQ */ | |
| 1174 | + rreq = orq_get_free(qp); | |
| 1172 | 1175 | if (unlikely(!rreq)) { |
| 1173 | 1176 | pr_warn("siw: [QP %u]: no ORQE\n", qp_id(qp)); |
| 1174 | 1177 | rv = -EPROTO; |
| @@ -1181,15 +1184,14 @@ static int siw_check_tx_fence(struct siw_qp *qp) · 6 unmodified lines | ||
| 1181 | 1184 | resume_tx = 1; |
| 1182 | 1185 | |
| 1183 | 1186 | } else if (siw_orq_empty(qp)) { |
| 1187 | + /* | |
| 1188 | + * SQ processing was stopped by fenced work request. | |
| 1189 | + * Resume since all previous Read's are now completed. | |
| 1190 | + */ | |
| 1184 | 1191 | qp->tx_ctx.orq_fence = 0; |
| 1185 | 1192 | resume_tx = 1; |
| 1186 | − } else { | |
| 1187 | − pr_warn("siw: [QP %u]: fence resume: orq idx: %d:%d\n", | |
| 1188 | − qp_id(qp), qp->orq_get, qp->orq_put); | |
| 1189 | − rv = -EPROTO; | |
| 1190 | 1193 | } |
| 1191 | 1194 | } |
| 1192 | − qp->orq_get++; | |
| 1193 | 1195 | out: |
| 1194 | 1196 | spin_unlock_irqrestore(&qp->orq_lock, flags); |
| 1195 | 1197 | |
| @@ -313,7 +313,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, · 312 unmodified lines | ||
| 313 | 313 | |
| 314 | 314 | if (atomic_inc_return(&sdev->num_qp) > SIW_MAX_QP) { |
| 315 | 315 | siw_dbg(base_dev, "too many QP's\n"); |
| 316 | − return -ENOMEM; | |
| 316 | + rv = -ENOMEM; | |
| 317 | + goto err_atomic; | |
| 317 | 318 | } |
| 318 | 319 | if (attrs->qp_type != IB_QPT_RC) { |
| 319 | 320 | siw_dbg(base_dev, "only RC QP's supported\n"); |
| @@ -615,10 +615,9 @@ static int wm97xx_register_touch(struct wm97xx *wm) · 614 unmodified lines | ||
| 615 | 615 | * extensions) |
| 616 | 616 | */ |
| 617 | 617 | wm->touch_dev = platform_device_alloc("wm97xx-touch", -1); |
| 618 | − if (!wm->touch_dev) { | |
| 619 | − ret = -ENOMEM; | |
| 620 | − goto touch_err; | |
| 621 | − } | |
| 618 | + if (!wm->touch_dev) | |
| 619 | + return -ENOMEM; | |
| 620 | + | |
| 622 | 621 | platform_set_drvdata(wm->touch_dev, wm); |
| 623 | 622 | wm->touch_dev->dev.parent = wm->dev; |
| 624 | 623 | wm->touch_dev->dev.platform_data = pdata; |
| @@ -629,9 +628,6 @@ static int wm97xx_register_touch(struct wm97xx *wm) · 4 unmodified lines | ||
| 629 | 628 | return 0; |
| 630 | 629 | touch_reg_err: |
| 631 | 630 | platform_device_put(wm->touch_dev); |
| 632 | −touch_err: | |
| 633 | − input_unregister_device(wm->input_dev); | |
| 634 | − wm->input_dev = NULL; | |
| 635 | 631 | |
| 636 | 632 | return ret; |
| 637 | 633 | } |
| @@ -639,8 +635,6 @@ touch_err: · 1 unmodified line | ||
| 639 | 635 | static void wm97xx_unregister_touch(struct wm97xx *wm) |
| 640 | 636 | { |
| 641 | 637 | platform_device_unregister(wm->touch_dev); |
| 642 | − input_unregister_device(wm->input_dev); | |
| 643 | − wm->input_dev = NULL; | |
| 644 | 638 | } |
| 645 | 639 | |
| 646 | 640 | static int _wm97xx_probe(struct wm97xx *wm) |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/export.h> |
| 22 | 22 | #include <linux/kmemleak.h> |
| 23 | 23 | #include <linux/cc_platform.h> |
| 24 | +#include <linux/iopoll.h> | |
| 24 | 25 | #include <asm/pci-direct.h> |
| 25 | 26 | #include <asm/iommu.h> |
| 26 | 27 | #include <asm/apic.h> |
| @@ -834,6 +835,7 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) · 807 unmodified lines | ||
| 834 | 835 | status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); |
| 835 | 836 | if (status & (MMIO_STATUS_GALOG_RUN_MASK)) |
| 836 | 837 | break; |
| 838 | + udelay(10); | |
| 837 | 839 | } |
| 838 | 840 | |
| 839 | 841 | if (WARN_ON(i >= LOOP_TIMEOUT)) |
| @@ -569,9 +569,8 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu) · 568 unmodified lines | ||
| 569 | 569 | fn, &intel_ir_domain_ops, |
| 570 | 570 | iommu); |
| 571 | 571 | if (!iommu->ir_domain) { |
| 572 | − irq_domain_free_fwnode(fn); | |
| 573 | 572 | pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id); |
| 574 | − goto out_free_bitmap; | |
| 573 | + goto out_free_fwnode; | |
| 575 | 574 | } |
| 576 | 575 | iommu->ir_msi_domain = |
| 577 | 576 | arch_create_remap_msi_irq_domain(iommu->ir_domain, |
| @@ -595,7 +594,7 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu) · 17 unmodified lines | ||
| 595 | 594 | |
| 596 | 595 | if (dmar_enable_qi(iommu)) { |
| 597 | 596 | pr_err("Failed to enable queued invalidation\n"); |
| 598 | − goto out_free_bitmap; | |
| 597 | + goto out_free_ir_domain; | |
| 599 | 598 | } |
| 600 | 599 | } |
| 601 | 600 | |
| @@ -619,6 +618,14 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu) · 17 unmodified lines | ||
| 619 | 618 | |
| 620 | 619 | return 0; |
| 621 | 620 | |
| 621 | +out_free_ir_domain: | |
| 622 | + if (iommu->ir_msi_domain) | |
| 623 | + irq_domain_remove(iommu->ir_msi_domain); | |
| 624 | + iommu->ir_msi_domain = NULL; | |
| 625 | + irq_domain_remove(iommu->ir_domain); | |
| 626 | + iommu->ir_domain = NULL; | |
| 627 | +out_free_fwnode: | |
| 628 | + irq_domain_free_fwnode(fn); | |
| 622 | 629 | out_free_bitmap: |
| 623 | 630 | bitmap_free(bitmap); |
| 624 | 631 | out_free_pages: |
| @@ -349,6 +349,7 @@ EXPORT_SYMBOL_GPL(ioasid_alloc); · 348 unmodified lines | ||
| 349 | 349 | |
| 350 | 350 | /** |
| 351 | 351 | * ioasid_get - obtain a reference to the IOASID |
| 352 | + * @ioasid: the ID to get | |
| 352 | 353 | */ |
| 353 | 354 | void ioasid_get(ioasid_t ioasid) |
| 354 | 355 | { |
| @@ -207,9 +207,14 @@ static struct dev_iommu *dev_iommu_get(struct device *dev) · 206 unmodified lines | ||
| 207 | 207 | |
| 208 | 208 | static void dev_iommu_free(struct device *dev) |
| 209 | 209 | { |
| 210 | − iommu_fwspec_free(dev); | |
| 211 | − kfree(dev->iommu); | |
| 210 | + struct dev_iommu *param = dev->iommu; | |
| 211 | + | |
| 212 | 212 | dev->iommu = NULL; |
| 213 | + if (param->fwspec) { | |
| 214 | + fwnode_handle_put(param->fwspec->iommu_fwnode); | |
| 215 | + kfree(param->fwspec); | |
| 216 | + } | |
| 217 | + kfree(param); | |
| 213 | 218 | } |
| 214 | 219 | |
| 215 | 220 | static int __iommu_probe_device(struct device *dev, struct list_head *group_list) |
| @@ -980,17 +985,6 @@ static int iommu_group_device_count(struct iommu_group *group) · 764 unmodified lines | ||
| 980 | 985 | return ret; |
| 981 | 986 | } |
| 982 | 987 | |
| 983 | −/** | |
| 984 | − * iommu_group_for_each_dev - iterate over each device in the group | |
| 985 | − * @group: the group | |
| 986 | − * @data: caller opaque data to be passed to callback function | |
| 987 | − * @fn: caller supplied callback function | |
| 988 | − * | |
| 989 | − * This function is called by group users to iterate over group devices. | |
| 990 | − * Callers should hold a reference count to the group during callback. | |
| 991 | − * The group->mutex is held across callbacks, which will block calls to | |
| 992 | − * iommu_group_add/remove_device. | |
| 993 | − */ | |
| 994 | 988 | static int __iommu_group_for_each_dev(struct iommu_group *group, void *data, |
| 995 | 989 | int (*fn)(struct device *, void *)) |
| 996 | 990 | { |
| @@ -1005,7 +999,17 @@ static int __iommu_group_for_each_dev(struct iommu_group *group, void *data, · 8 unmodified lines | ||
| 1005 | 999 | return ret; |
| 1006 | 1000 | } |
| 1007 | 1001 | |
| 1008 | − | |
| 1002 | +/** | |
| 1003 | + * iommu_group_for_each_dev - iterate over each device in the group | |
| 1004 | + * @group: the group | |
| 1005 | + * @data: caller opaque data to be passed to callback function | |
| 1006 | + * @fn: caller supplied callback function | |
| 1007 | + * | |
| 1008 | + * This function is called by group users to iterate over group devices. | |
| 1009 | + * Callers should hold a reference count to the group during callback. | |
| 1010 | + * The group->mutex is held across callbacks, which will block calls to | |
| 1011 | + * iommu_group_add/remove_device. | |
| 1012 | + */ | |
| 1009 | 1013 | int iommu_group_for_each_dev(struct iommu_group *group, void *data, |
| 1010 | 1014 | int (*fn)(struct device *, void *)) |
| 1011 | 1015 | { |
| @@ -3032,6 +3036,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_get_pasid); · 2020 unmodified lines | ||
| 3032 | 3036 | * iommu_sva_bind_device() - Bind a process address space to a device |
| 3033 | 3037 | * @dev: the device |
| 3034 | 3038 | * @mm: the mm to bind, caller must hold a reference to it |
| 3039 | + * @drvdata: opaque data pointer to pass to bind callback | |
| 3035 | 3040 | * |
| 3036 | 3041 | * Create a bond between device and address space, allowing the device to access |
| 3037 | 3042 | * the mm using the returned PASID. If a bond already exists between @device and |
| @@ -1085,7 +1085,7 @@ static __maybe_unused int omap_iommu_runtime_resume(struct device *dev) · 1084 unmodified lines | ||
| 1085 | 1085 | } |
| 1086 | 1086 | |
| 1087 | 1087 | /** |
| 1088 | − * omap_iommu_suspend_prepare - prepare() dev_pm_ops implementation | |
| 1088 | + * omap_iommu_prepare - prepare() dev_pm_ops implementation | |
| 1089 | 1089 | * @dev: iommu device |
| 1090 | 1090 | * |
| 1091 | 1091 | * This function performs the necessary checks to determine if the IOMMU |
| @@ -5869,10 +5869,6 @@ int md_run(struct mddev *mddev) · 5868 unmodified lines | ||
| 5869 | 5869 | nowait = nowait && blk_queue_nowait(bdev_get_queue(rdev->bdev)); |
| 5870 | 5870 | } |
| 5871 | 5871 | |
| 5872 | − /* Set the NOWAIT flags if all underlying devices support it */ | |
| 5873 | − if (nowait) | |
| 5874 | − blk_queue_flag_set(QUEUE_FLAG_NOWAIT, mddev->queue); | |
| 5875 | − | |
| 5876 | 5872 | if (!bioset_initialized(&mddev->bio_set)) { |
| 5877 | 5873 | err = bioset_init(&mddev->bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); |
| 5878 | 5874 | if (err) |
| @@ -6010,6 +6006,10 @@ int md_run(struct mddev *mddev) · 131 unmodified lines | ||
| 6010 | 6006 | else |
| 6011 | 6007 | blk_queue_flag_clear(QUEUE_FLAG_NONROT, mddev->queue); |
| 6012 | 6008 | blk_queue_flag_set(QUEUE_FLAG_IO_STAT, mddev->queue); |
| 6009 | + | |
| 6010 | + /* Set the NOWAIT flags if all underlying devices support it */ | |
| 6011 | + if (nowait) | |
| 6012 | + blk_queue_flag_set(QUEUE_FLAG_NOWAIT, mddev->queue); | |
| 6013 | 6013 | } |
| 6014 | 6014 | if (pers->sync_request) { |
| 6015 | 6015 | if (mddev->kobj.sd && |
| @@ -67,7 +67,7 @@ static const unsigned int sd_au_size[] = { · 66 unmodified lines | ||
| 67 | 67 | __res & __mask; \ |
| 68 | 68 | }) |
| 69 | 69 | |
| 70 | −#define SD_POWEROFF_NOTIFY_TIMEOUT_MS 2000 | |
| 70 | +#define SD_POWEROFF_NOTIFY_TIMEOUT_MS 1000 | |
| 71 | 71 | #define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000 |
| 72 | 72 | |
| 73 | 73 | struct sd_busy_data { |
| @@ -1664,6 +1664,12 @@ static int sd_poweroff_notify(struct mmc_card *card) · 1590 unmodified lines | ||
| 1664 | 1664 | goto out; |
| 1665 | 1665 | } |
| 1666 | 1666 | |
| 1667 | + /* Find out when the command is completed. */ | |
| 1668 | + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, | |
| 1669 | + MMC_BUSY_EXTR_SINGLE); | |
| 1670 | + if (err) | |
| 1671 | + goto out; | |
| 1672 | + | |
| 1667 | 1673 | cb_data.card = card; |
| 1668 | 1674 | cb_data.reg_buf = reg_buf; |
| 1669 | 1675 | err = __mmc_poll_for_busy(card->host, SD_POWEROFF_NOTIFY_TIMEOUT_MS, |
| @@ -705,12 +705,12 @@ static int moxart_remove(struct platform_device *pdev) · 704 unmodified lines | ||
| 705 | 705 | if (!IS_ERR_OR_NULL(host->dma_chan_rx)) |
| 706 | 706 | dma_release_channel(host->dma_chan_rx); |
| 707 | 707 | mmc_remove_host(mmc); |
| 708 | − mmc_free_host(mmc); | |
| 709 | 708 | |
| 710 | 709 | writel(0, host->base + REG_INTERRUPT_MASK); |
| 711 | 710 | writel(0, host->base + REG_POWER_CONTROL); |
| 712 | 711 | writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, |
| 713 | 712 | host->base + REG_CLOCK_CONTROL); |
| 713 | + mmc_free_host(mmc); | |
| 714 | 714 | |
| 715 | 715 | return 0; |
| 716 | 716 | } |
| @@ -524,12 +524,16 @@ static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) · 523 unmodified lines | ||
| 524 | 524 | |
| 525 | 525 | static int esdhc_of_enable_dma(struct sdhci_host *host) |
| 526 | 526 | { |
| 527 | + int ret; | |
| 527 | 528 | u32 value; |
| 528 | 529 | struct device *dev = mmc_dev(host->mmc); |
| 529 | 530 | |
| 530 | 531 | if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || |
| 531 | − of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) | |
| 532 | − dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); | |
| 532 | + of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) { | |
| 533 | + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); | |
| 534 | + if (ret) | |
| 535 | + return ret; | |
| 536 | + } | |
| 533 | 537 | |
| 534 | 538 | value = sdhci_readl(host, ESDHC_DMA_SYSCTL); |
| 535 | 539 | |
| @@ -405,6 +405,9 @@ static int sh_mmcif_dma_slave_config(struct sh_mmcif_host *host, · 404 unmodified lines | ||
| 405 | 405 | struct dma_slave_config cfg = { 0, }; |
| 406 | 406 | |
| 407 | 407 | res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); |
| 408 | + if (!res) | |
| 409 | + return -EINVAL; | |
| 410 | + | |
| 408 | 411 | cfg.direction = direction; |
| 409 | 412 | |
| 410 | 413 | if (direction == DMA_DEV_TO_MEM) { |
| @@ -1021,8 +1021,8 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr) · 1020 unmodified lines | ||
| 1021 | 1021 | if (port->aggregator && |
| 1022 | 1022 | port->aggregator->is_active && |
| 1023 | 1023 | !__port_is_enabled(port)) { |
| 1024 | − | |
| 1025 | 1024 | __enable_port(port); |
| 1025 | + *update_slave_arr = true; | |
| 1026 | 1026 | } |
| 1027 | 1027 | } |
| 1028 | 1028 | break; |
| @@ -1779,6 +1779,7 @@ static void ad_agg_selection_logic(struct aggregator *agg, · 750 unmodified lines | ||
| 1779 | 1779 | port = port->next_port_in_aggregator) { |
| 1780 | 1780 | __enable_port(port); |
| 1781 | 1781 | } |
| 1782 | + *update_slave_arr = true; | |
| 1782 | 1783 | } |
| 1783 | 1784 | } |
| 1784 | 1785 | |
| @@ -621,7 +621,7 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) · 620 unmodified lines | ||
| 621 | 621 | get_device(&priv->master_mii_bus->dev); |
| 622 | 622 | priv->master_mii_dn = dn; |
| 623 | 623 | |
| 624 | − priv->slave_mii_bus = devm_mdiobus_alloc(ds->dev); | |
| 624 | + priv->slave_mii_bus = mdiobus_alloc(); | |
| 625 | 625 | if (!priv->slave_mii_bus) { |
| 626 | 626 | of_node_put(dn); |
| 627 | 627 | return -ENOMEM; |
| @@ -681,8 +681,10 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) · 53 unmodified lines | ||
| 681 | 681 | } |
| 682 | 682 | |
| 683 | 683 | err = mdiobus_register(priv->slave_mii_bus); |
| 684 | − if (err && dn) | |
| 684 | + if (err && dn) { | |
| 685 | + mdiobus_free(priv->slave_mii_bus); | |
| 685 | 686 | of_node_put(dn); |
| 687 | + } | |
| 686 | 688 | |
| 687 | 689 | return err; |
| 688 | 690 | } |
| @@ -690,6 +692,7 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) · 1 unmodified line | ||
| 690 | 692 | static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv *priv) |
| 691 | 693 | { |
| 692 | 694 | mdiobus_unregister(priv->slave_mii_bus); |
| 695 | + mdiobus_free(priv->slave_mii_bus); | |
| 693 | 696 | of_node_put(priv->master_mii_dn); |
| 694 | 697 | } |
| 695 | 698 | |
| @@ -498,8 +498,9 @@ static int gswip_mdio_rd(struct mii_bus *bus, int addr, int reg) · 497 unmodified lines | ||
| 498 | 498 | static int gswip_mdio(struct gswip_priv *priv, struct device_node *mdio_np) |
| 499 | 499 | { |
| 500 | 500 | struct dsa_switch *ds = priv->ds; |
| 501 | + int err; | |
| 501 | 502 | |
| 502 | − ds->slave_mii_bus = devm_mdiobus_alloc(priv->dev); | |
| 503 | + ds->slave_mii_bus = mdiobus_alloc(); | |
| 503 | 504 | if (!ds->slave_mii_bus) |
| 504 | 505 | return -ENOMEM; |
| 505 | 506 | |
| @@ -512,7 +513,11 @@ static int gswip_mdio(struct gswip_priv *priv, struct device_node *mdio_np) · 6 unmodified lines | ||
| 512 | 513 | ds->slave_mii_bus->parent = priv->dev; |
| 513 | 514 | ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask; |
| 514 | 515 | |
| 515 | − return of_mdiobus_register(ds->slave_mii_bus, mdio_np); | |
| 516 | + err = of_mdiobus_register(ds->slave_mii_bus, mdio_np); | |
| 517 | + if (err) | |
| 518 | + mdiobus_free(ds->slave_mii_bus); | |
| 519 | + | |
| 520 | + return err; | |
| 516 | 521 | } |
| 517 | 522 | |
| 518 | 523 | static int gswip_pce_table_entry_read(struct gswip_priv *priv, |
| @@ -2145,8 +2150,10 @@ disable_switch: · 1626 unmodified lines | ||
| 2145 | 2150 | gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB); |
| 2146 | 2151 | dsa_unregister_switch(priv->ds); |
| 2147 | 2152 | mdio_bus: |
| 2148 | − if (mdio_np) | |
| 2153 | + if (mdio_np) { | |
| 2149 | 2154 | mdiobus_unregister(priv->ds->slave_mii_bus); |
| 2155 | + mdiobus_free(priv->ds->slave_mii_bus); | |
| 2156 | + } | |
| 2150 | 2157 | put_mdio_node: |
| 2151 | 2158 | of_node_put(mdio_np); |
| 2152 | 2159 | for (i = 0; i < priv->num_gphy_fw; i++) |
| @@ -2169,6 +2176,7 @@ static int gswip_remove(struct platform_device *pdev) · 16 unmodified lines | ||
| 2169 | 2176 | |
| 2170 | 2177 | if (priv->ds->slave_mii_bus) { |
| 2171 | 2178 | mdiobus_unregister(priv->ds->slave_mii_bus); |
| 2179 | + mdiobus_free(priv->ds->slave_mii_bus); | |
| 2172 | 2180 | of_node_put(priv->ds->slave_mii_bus->dev.of_node); |
| 2173 | 2181 | } |
| 2174 | 2182 | |
| @@ -2074,7 +2074,7 @@ mt7530_setup_mdio(struct mt7530_priv *priv) · 2073 unmodified lines | ||
| 2074 | 2074 | if (priv->irq) |
| 2075 | 2075 | mt7530_setup_mdio_irq(priv); |
| 2076 | 2076 | |
| 2077 | − ret = mdiobus_register(bus); | |
| 2077 | + ret = devm_mdiobus_register(dev, bus); | |
| 2078 | 2078 | if (ret) { |
| 2079 | 2079 | dev_err(dev, "failed to register MDIO bus: %d\n", ret); |
| 2080 | 2080 | if (priv->irq) |
| @@ -3566,7 +3566,7 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, · 3565 unmodified lines | ||
| 3566 | 3566 | return err; |
| 3567 | 3567 | } |
| 3568 | 3568 | |
| 3569 | − bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*mdio_bus)); | |
| 3569 | + bus = mdiobus_alloc_size(sizeof(*mdio_bus)); | |
| 3570 | 3570 | if (!bus) |
| 3571 | 3571 | return -ENOMEM; |
| 3572 | 3572 | |
| @@ -3591,14 +3591,14 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, · 18 unmodified lines | ||
| 3591 | 3591 | if (!external) { |
| 3592 | 3592 | err = mv88e6xxx_g2_irq_mdio_setup(chip, bus); |
| 3593 | 3593 | if (err) |
| 3594 | − return err; | |
| 3594 | + goto out; | |
| 3595 | 3595 | } |
| 3596 | 3596 | |
| 3597 | 3597 | err = of_mdiobus_register(bus, np); |
| 3598 | 3598 | if (err) { |
| 3599 | 3599 | dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err); |
| 3600 | 3600 | mv88e6xxx_g2_irq_mdio_free(chip, bus); |
| 3601 | − return err; | |
| 3601 | + goto out; | |
| 3602 | 3602 | } |
| 3603 | 3603 | |
| 3604 | 3604 | if (external) |
| @@ -3607,21 +3607,26 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, · 2 unmodified lines | ||
| 3607 | 3607 | list_add(&mdio_bus->list, &chip->mdios); |
| 3608 | 3608 | |
| 3609 | 3609 | return 0; |
| 3610 | + | |
| 3611 | +out: | |
| 3612 | + mdiobus_free(bus); | |
| 3613 | + return err; | |
| 3610 | 3614 | } |
| 3611 | 3615 | |
| 3612 | 3616 | static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip) |
| 3613 | 3617 | |
| 3614 | 3618 | { |
| 3615 | − struct mv88e6xxx_mdio_bus *mdio_bus; | |
| 3619 | + struct mv88e6xxx_mdio_bus *mdio_bus, *p; | |
| 3616 | 3620 | struct mii_bus *bus; |
| 3617 | 3621 | |
| 3618 | − list_for_each_entry(mdio_bus, &chip->mdios, list) { | |
| 3622 | + list_for_each_entry_safe(mdio_bus, p, &chip->mdios, list) { | |
| 3619 | 3623 | bus = mdio_bus->bus; |
| 3620 | 3624 | |
| 3621 | 3625 | if (!mdio_bus->external) |
| 3622 | 3626 | mv88e6xxx_g2_irq_mdio_free(chip, bus); |
| 3623 | 3627 | |
| 3624 | 3628 | mdiobus_unregister(bus); |
| 3629 | + mdiobus_free(bus); | |
| 3625 | 3630 | } |
| 3626 | 3631 | } |
| 3627 | 3632 | |
| @@ -1061,7 +1061,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) · 1060 unmodified lines | ||
| 1061 | 1061 | return PTR_ERR(hw); |
| 1062 | 1062 | } |
| 1063 | 1063 | |
| 1064 | − bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); | |
| 1064 | + bus = mdiobus_alloc_size(sizeof(*mdio_priv)); | |
| 1065 | 1065 | if (!bus) |
| 1066 | 1066 | return -ENOMEM; |
| 1067 | 1067 | |
| @@ -1081,6 +1081,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) · 13 unmodified lines | ||
| 1081 | 1081 | rc = mdiobus_register(bus); |
| 1082 | 1082 | if (rc < 0) { |
| 1083 | 1083 | dev_err(dev, "failed to register MDIO bus\n"); |
| 1084 | + mdiobus_free(bus); | |
| 1084 | 1085 | return rc; |
| 1085 | 1086 | } |
| 1086 | 1087 | |
| @@ -1132,6 +1133,7 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot) · 45 unmodified lines | ||
| 1132 | 1133 | lynx_pcs_destroy(phylink_pcs); |
| 1133 | 1134 | } |
| 1134 | 1135 | mdiobus_unregister(felix->imdio); |
| 1136 | + mdiobus_free(felix->imdio); | |
| 1135 | 1137 | } |
| 1136 | 1138 | |
| 1137 | 1139 | static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, |
| @@ -1029,7 +1029,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) · 1028 unmodified lines | ||
| 1029 | 1029 | } |
| 1030 | 1030 | |
| 1031 | 1031 | /* Needed in order to initialize the bus mutex lock */ |
| 1032 | − rc = of_mdiobus_register(bus, NULL); | |
| 1032 | + rc = devm_of_mdiobus_register(dev, bus, NULL); | |
| 1033 | 1033 | if (rc < 0) { |
| 1034 | 1034 | dev_err(dev, "failed to register MDIO bus\n"); |
| 1035 | 1035 | return rc; |
| @@ -1083,7 +1083,8 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot) · 47 unmodified lines | ||
| 1083 | 1083 | mdio_device_free(mdio_device); |
| 1084 | 1084 | lynx_pcs_destroy(phylink_pcs); |
| 1085 | 1085 | } |
| 1086 | − mdiobus_unregister(felix->imdio); | |
| 1086 | + | |
| 1087 | + /* mdiobus_unregister and mdiobus_free handled by devres */ | |
| 1087 | 1088 | } |
| 1088 | 1089 | |
| 1089 | 1090 | static const struct felix_info seville_info_vsc9953 = { |
| @@ -378,7 +378,7 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv) · 377 unmodified lines | ||
| 378 | 378 | if (!mnp) |
| 379 | 379 | return -ENODEV; |
| 380 | 380 | |
| 381 | − ret = of_mdiobus_register(mbus, mnp); | |
| 381 | + ret = devm_of_mdiobus_register(dev, mbus, mnp); | |
| 382 | 382 | of_node_put(mnp); |
| 383 | 383 | if (ret) |
| 384 | 384 | return ret; |
| @@ -1066,7 +1066,6 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev) · 681 unmodified lines | ||
| 1066 | 1066 | } |
| 1067 | 1067 | |
| 1068 | 1068 | irq_domain_remove(priv->irqdomain); |
| 1069 | − mdiobus_unregister(priv->mbus); | |
| 1070 | 1069 | dsa_unregister_switch(&priv->ds); |
| 1071 | 1070 | |
| 1072 | 1071 | reset_control_assert(priv->sw_reset); |
| @@ -425,6 +425,9 @@ static void xgbe_pci_remove(struct pci_dev *pdev) · 424 unmodified lines | ||
| 425 | 425 | |
| 426 | 426 | pci_free_irq_vectors(pdata->pcidev); |
| 427 | 427 | |
| 428 | + /* Disable all interrupts in the hardware */ | |
| 429 | + XP_IOWRITE(pdata, XP_INT_EN, 0x0); | |
| 430 | + | |
| 428 | 431 | xgbe_free_pdata(pdata); |
| 429 | 432 | } |
| 430 | 433 | |
| @@ -4765,7 +4765,7 @@ static int macb_probe(struct platform_device *pdev) · 4764 unmodified lines | ||
| 4765 | 4765 | |
| 4766 | 4766 | #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT |
| 4767 | 4767 | if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) { |
| 4768 | − dma_set_mask(&pdev->dev, DMA_BIT_MASK(44)); | |
| 4768 | + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44)); | |
| 4769 | 4769 | bp->hw_dma_cap |= HW_DMA_CAP_64B; |
| 4770 | 4770 | } |
| 4771 | 4771 | #endif |
| @@ -4733,12 +4733,12 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) · 4732 unmodified lines | ||
| 4733 | 4733 | #ifdef CONFIG_DEBUG_FS |
| 4734 | 4734 | dpaa2_dbg_remove(priv); |
| 4735 | 4735 | #endif |
| 4736 | + | |
| 4737 | + unregister_netdev(net_dev); | |
| 4736 | 4738 | rtnl_lock(); |
| 4737 | 4739 | dpaa2_eth_disconnect_mac(priv); |
| 4738 | 4740 | rtnl_unlock(); |
| 4739 | 4741 | |
| 4740 | − unregister_netdev(net_dev); | |
| 4741 | − | |
| 4742 | 4742 | dpaa2_eth_dl_port_del(priv); |
| 4743 | 4743 | dpaa2_eth_dl_traps_unregister(priv); |
| 4744 | 4744 | dpaa2_eth_dl_free(priv); |
| @@ -609,6 +609,7 @@ static bool gve_rx(struct gve_rx_ring *rx, netdev_features_t feat, · 608 unmodified lines | ||
| 609 | 609 | |
| 610 | 610 | *packet_size_bytes = skb->len + (skb->protocol ? ETH_HLEN : 0); |
| 611 | 611 | *work_done = work_cnt; |
| 612 | + skb_record_rx_queue(skb, rx->q_num); | |
| 612 | 613 | if (skb_is_nonlinear(skb)) |
| 613 | 614 | napi_gro_frags(napi); |
| 614 | 615 | else |
| @@ -110,6 +110,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter, · 109 unmodified lines | ||
| 110 | 110 | struct ibmvnic_sub_crq_queue *tx_scrq); |
| 111 | 111 | static void free_long_term_buff(struct ibmvnic_adapter *adapter, |
| 112 | 112 | struct ibmvnic_long_term_buff *ltb); |
| 113 | +static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter); | |
| 113 | 114 | |
| 114 | 115 | struct ibmvnic_stat { |
| 115 | 116 | char name[ETH_GSTRING_LEN]; |
| @@ -1424,7 +1425,7 @@ static int __ibmvnic_open(struct net_device *netdev) · 1308 unmodified lines | ||
| 1424 | 1425 | rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP); |
| 1425 | 1426 | if (rc) { |
| 1426 | 1427 | ibmvnic_napi_disable(adapter); |
| 1427 | − release_resources(adapter); | |
| 1428 | + ibmvnic_disable_irqs(adapter); | |
| 1428 | 1429 | return rc; |
| 1429 | 1430 | } |
| 1430 | 1431 | |
| @@ -1474,9 +1475,6 @@ static int ibmvnic_open(struct net_device *netdev) · 43 unmodified lines | ||
| 1474 | 1475 | rc = init_resources(adapter); |
| 1475 | 1476 | if (rc) { |
| 1476 | 1477 | netdev_err(netdev, "failed to initialize resources\n"); |
| 1477 | − release_resources(adapter); | |
| 1478 | − release_rx_pools(adapter); | |
| 1479 | − release_tx_pools(adapter); | |
| 1480 | 1478 | goto out; |
| 1481 | 1479 | } |
| 1482 | 1480 | } |
| @@ -1493,6 +1491,13 @@ out: · 10 unmodified lines | ||
| 1493 | 1491 | adapter->state = VNIC_OPEN; |
| 1494 | 1492 | rc = 0; |
| 1495 | 1493 | } |
| 1494 | + | |
| 1495 | + if (rc) { | |
| 1496 | + release_resources(adapter); | |
| 1497 | + release_rx_pools(adapter); | |
| 1498 | + release_tx_pools(adapter); | |
| 1499 | + } | |
| 1500 | + | |
| 1496 | 1501 | return rc; |
| 1497 | 1502 | } |
| 1498 | 1503 | |
| @@ -487,6 +487,7 @@ enum ice_pf_flags { · 486 unmodified lines | ||
| 487 | 487 | ICE_FLAG_MDD_AUTO_RESET_VF, |
| 488 | 488 | ICE_FLAG_VF_VLAN_PRUNING, |
| 489 | 489 | ICE_FLAG_LINK_LENIENT_MODE_ENA, |
| 490 | + ICE_FLAG_PLUG_AUX_DEV, | |
| 490 | 491 | ICE_PF_FLAGS_NBITS /* must be last */ |
| 491 | 492 | }; |
| 492 | 493 | |
| @@ -891,7 +892,7 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf) · 398 unmodified lines | ||
| 891 | 892 | if (pf->hw.func_caps.common_cap.rdma && pf->num_rdma_msix) { |
| 892 | 893 | set_bit(ICE_FLAG_RDMA_ENA, pf->flags); |
| 893 | 894 | set_bit(ICE_FLAG_AUX_ENA, pf->flags); |
| 894 | − ice_plug_aux_dev(pf); | |
| 895 | + set_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags); | |
| 895 | 896 | } |
| 896 | 897 | } |
| 897 | 898 | |
| @@ -3381,7 +3381,8 @@ ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg, · 3380 unmodified lines | ||
| 3381 | 3381 | !ice_fw_supports_report_dflt_cfg(hw)) { |
| 3382 | 3382 | struct ice_link_default_override_tlv tlv; |
| 3383 | 3383 | |
| 3384 | − if (ice_get_link_default_override(&tlv, pi)) | |
| 3384 | + status = ice_get_link_default_override(&tlv, pi); | |
| 3385 | + if (status) | |
| 3385 | 3386 | goto out; |
| 3386 | 3387 | |
| 3387 | 3388 | if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) && |
| @@ -204,17 +204,39 @@ ice_lag_unlink(struct ice_lag *lag, · 203 unmodified lines | ||
| 204 | 204 | lag->upper_netdev = NULL; |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | − if (lag->peer_netdev) { | |
| 208 | − dev_put(lag->peer_netdev); | |
| 209 | − lag->peer_netdev = NULL; | |
| 210 | − } | |
| 211 | − | |
| 207 | + lag->peer_netdev = NULL; | |
| 212 | 208 | ice_set_sriov_cap(pf); |
| 213 | 209 | ice_set_rdma_cap(pf); |
| 214 | 210 | lag->bonded = false; |
| 215 | 211 | lag->role = ICE_LAG_NONE; |
| 216 | 212 | } |
| 217 | 213 | |
| 214 | +/** | |
| 215 | + * ice_lag_unregister - handle netdev unregister events | |
| 216 | + * @lag: LAG info struct | |
| 217 | + * @netdev: netdev reporting the event | |
| 218 | + */ | |
| 219 | +static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev) | |
| 220 | +{ | |
| 221 | + struct ice_pf *pf = lag->pf; | |
| 222 | + | |
| 223 | + /* check to see if this event is for this netdev | |
| 224 | + * check that we are in an aggregate | |
| 225 | + */ | |
| 226 | + if (netdev != lag->netdev || !lag->bonded) | |
| 227 | + return; | |
| 228 | + | |
| 229 | + if (lag->upper_netdev) { | |
| 230 | + dev_put(lag->upper_netdev); | |
| 231 | + lag->upper_netdev = NULL; | |
| 232 | + ice_set_sriov_cap(pf); | |
| 233 | + ice_set_rdma_cap(pf); | |
| 234 | + } | |
| 235 | + /* perform some cleanup in case we come back */ | |
| 236 | + lag->bonded = false; | |
| 237 | + lag->role = ICE_LAG_NONE; | |
| 238 | +} | |
| 239 | + | |
| 218 | 240 | /** |
| 219 | 241 | * ice_lag_changeupper_event - handle LAG changeupper event |
| 220 | 242 | * @lag: LAG info struct |
| @@ -307,7 +329,7 @@ ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event, · 86 unmodified lines | ||
| 307 | 329 | ice_lag_info_event(lag, ptr); |
| 308 | 330 | break; |
| 309 | 331 | case NETDEV_UNREGISTER: |
| 310 | − ice_lag_unlink(lag, ptr); | |
| 332 | + ice_lag_unregister(lag, netdev); | |
| 311 | 333 | break; |
| 312 | 334 | default: |
| 313 | 335 | break; |
| @@ -570,6 +570,7 @@ struct ice_tx_ctx_desc { · 569 unmodified lines | ||
| 570 | 570 | (0x3FFFFULL << ICE_TXD_CTX_QW1_TSO_LEN_S) |
| 571 | 571 | |
| 572 | 572 | #define ICE_TXD_CTX_QW1_MSS_S 50 |
| 573 | +#define ICE_TXD_CTX_MIN_MSS 64 | |
| 573 | 574 | |
| 574 | 575 | #define ICE_TXD_CTX_QW1_VSI_S 50 |
| 575 | 576 | #define ICE_TXD_CTX_QW1_VSI_M (0x3FFULL << ICE_TXD_CTX_QW1_VSI_S) |
| @@ -2256,6 +2256,9 @@ static void ice_service_task(struct work_struct *work) · 2255 unmodified lines | ||
| 2256 | 2256 | return; |
| 2257 | 2257 | } |
| 2258 | 2258 | |
| 2259 | + if (test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) | |
| 2260 | + ice_plug_aux_dev(pf); | |
| 2261 | + | |
| 2259 | 2262 | ice_clean_adminq_subtask(pf); |
| 2260 | 2263 | ice_check_media_subtask(pf); |
| 2261 | 2264 | ice_check_for_hang_subtask(pf); |
| @@ -8724,6 +8727,7 @@ ice_features_check(struct sk_buff *skb, · 6462 unmodified lines | ||
| 8724 | 8727 | struct net_device __always_unused *netdev, |
| 8725 | 8728 | netdev_features_t features) |
| 8726 | 8729 | { |
| 8730 | + bool gso = skb_is_gso(skb); | |
| 8727 | 8731 | size_t len; |
| 8728 | 8732 | |
| 8729 | 8733 | /* No point in doing any of this if neither checksum nor GSO are |
| @@ -8736,24 +8740,32 @@ ice_features_check(struct sk_buff *skb, · 6 unmodified lines | ||
| 8736 | 8740 | /* We cannot support GSO if the MSS is going to be less than |
| 8737 | 8741 | * 64 bytes. If it is then we need to drop support for GSO. |
| 8738 | 8742 | */ |
| 8739 | − if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64)) | |
| 8743 | + if (gso && (skb_shinfo(skb)->gso_size < ICE_TXD_CTX_MIN_MSS)) | |
| 8740 | 8744 | features &= ~NETIF_F_GSO_MASK; |
| 8741 | 8745 | |
| 8742 | − len = skb_network_header(skb) - skb->data; | |
| 8746 | + len = skb_network_offset(skb); | |
| 8743 | 8747 | if (len > ICE_TXD_MACLEN_MAX || len & 0x1) |
| 8744 | 8748 | goto out_rm_features; |
| 8745 | 8749 | |
| 8746 | − len = skb_transport_header(skb) - skb_network_header(skb); | |
| 8750 | + len = skb_network_header_len(skb); | |
| 8747 | 8751 | if (len > ICE_TXD_IPLEN_MAX || len & 0x1) |
| 8748 | 8752 | goto out_rm_features; |
| 8749 | 8753 | |
| 8750 | 8754 | if (skb->encapsulation) { |
| 8751 | − len = skb_inner_network_header(skb) - skb_transport_header(skb); | |
| 8752 | − if (len > ICE_TXD_L4LEN_MAX || len & 0x1) | |
| 8753 | − goto out_rm_features; | |
| 8755 | + /* this must work for VXLAN frames AND IPIP/SIT frames, and in | |
| 8756 | + * the case of IPIP frames, the transport header pointer is | |
| 8757 | + * after the inner header! So check to make sure that this | |
| 8758 | + * is a GRE or UDP_TUNNEL frame before doing that math. | |
| 8759 | + */ | |
| 8760 | + if (gso && (skb_shinfo(skb)->gso_type & | |
| 8761 | + (SKB_GSO_GRE | SKB_GSO_UDP_TUNNEL))) { | |
| 8762 | + len = skb_inner_network_header(skb) - | |
| 8763 | + skb_transport_header(skb); | |
| 8764 | + if (len > ICE_TXD_L4LEN_MAX || len & 0x1) | |
| 8765 | + goto out_rm_features; | |
| 8766 | + } | |
| 8754 | 8767 | |
| 8755 | − len = skb_inner_transport_header(skb) - | |
| 8756 | − skb_inner_network_header(skb); | |
| 8768 | + len = skb_inner_network_header_len(skb); | |
| 8757 | 8769 | if (len > ICE_TXD_IPLEN_MAX || len & 0x1) |
| 8758 | 8770 | goto out_rm_features; |
| 8759 | 8771 | } |
| @@ -1984,14 +1984,15 @@ static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter, · 1983 unmodified lines | ||
| 1984 | 1984 | if (adapter->flags & IXGBEVF_FLAGS_LEGACY_RX) |
| 1985 | 1985 | return; |
| 1986 | 1986 | |
| 1987 | − set_ring_build_skb_enabled(rx_ring); | |
| 1987 | + if (PAGE_SIZE < 8192) | |
| 1988 | + if (max_frame > IXGBEVF_MAX_FRAME_BUILD_SKB) | |
| 1989 | + set_ring_uses_large_buffer(rx_ring); | |
| 1988 | 1990 | |
| 1989 | − if (PAGE_SIZE < 8192) { | |
| 1990 | − if (max_frame <= IXGBEVF_MAX_FRAME_BUILD_SKB) | |
| 1991 | − return; | |
| 1991 | + /* 82599 can't rely on RXDCTL.RLPML to restrict the size of the frame */ | |
| 1992 | + if (adapter->hw.mac.type == ixgbe_mac_82599_vf && !ring_uses_large_buffer(rx_ring)) | |
| 1993 | + return; | |
| 1992 | 1994 | |
| 1993 | − set_ring_uses_large_buffer(rx_ring); | |
| 1994 | − } | |
| 1995 | + set_ring_build_skb_enabled(rx_ring); | |
| 1995 | 1996 | } |
| 1996 | 1997 | |
| 1997 | 1998 | /** |
| @@ -17,7 +17,7 @@ if NET_VENDOR_LITEX · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | config LITEX_LITEETH |
| 19 | 19 | tristate "LiteX Ethernet support" |
| 20 | − depends on OF | |
| 20 | + depends on OF && HAS_IOMEM | |
| 21 | 21 | help |
| 22 | 22 | If you wish to compile a kernel for hardware with a LiteX LiteEth |
| 23 | 23 | device then you should answer Y to this. |
| @@ -1103,7 +1103,7 @@ void sparx5_get_stats64(struct net_device *ndev, · 1102 unmodified lines | ||
| 1103 | 1103 | stats->tx_carrier_errors = portstats[spx5_stats_tx_csense_cnt]; |
| 1104 | 1104 | stats->tx_window_errors = portstats[spx5_stats_tx_late_coll_cnt]; |
| 1105 | 1105 | stats->rx_dropped = portstats[spx5_stats_ana_ac_port_stat_lsb_cnt]; |
| 1106 | − for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx, ++stats) | |
| 1106 | + for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx) | |
| 1107 | 1107 | stats->rx_dropped += portstats[spx5_stats_green_p0_rx_port_drop |
| 1108 | 1108 | + idx]; |
| 1109 | 1109 | stats->tx_dropped = portstats[spx5_stats_tx_local_drop]; |
| @@ -1432,6 +1432,8 @@ static void · 1431 unmodified lines | ||
| 1432 | 1432 | ocelot_populate_ipv4_ptp_event_trap_key(struct ocelot_vcap_filter *trap) |
| 1433 | 1433 | { |
| 1434 | 1434 | trap->key_type = OCELOT_VCAP_KEY_IPV4; |
| 1435 | + trap->key.ipv4.proto.value[0] = IPPROTO_UDP; | |
| 1436 | + trap->key.ipv4.proto.mask[0] = 0xff; | |
| 1435 | 1437 | trap->key.ipv4.dport.value = PTP_EV_PORT; |
| 1436 | 1438 | trap->key.ipv4.dport.mask = 0xffff; |
| 1437 | 1439 | } |
| @@ -1440,6 +1442,8 @@ static void · 2 unmodified lines | ||
| 1440 | 1442 | ocelot_populate_ipv6_ptp_event_trap_key(struct ocelot_vcap_filter *trap) |
| 1441 | 1443 | { |
| 1442 | 1444 | trap->key_type = OCELOT_VCAP_KEY_IPV6; |
| 1445 | + trap->key.ipv4.proto.value[0] = IPPROTO_UDP; | |
| 1446 | + trap->key.ipv4.proto.mask[0] = 0xff; | |
| 1443 | 1447 | trap->key.ipv6.dport.value = PTP_EV_PORT; |
| 1444 | 1448 | trap->key.ipv6.dport.mask = 0xffff; |
| 1445 | 1449 | } |
| @@ -1448,6 +1452,8 @@ static void · 2 unmodified lines | ||
| 1448 | 1452 | ocelot_populate_ipv4_ptp_general_trap_key(struct ocelot_vcap_filter *trap) |
| 1449 | 1453 | { |
| 1450 | 1454 | trap->key_type = OCELOT_VCAP_KEY_IPV4; |
| 1455 | + trap->key.ipv4.proto.value[0] = IPPROTO_UDP; | |
| 1456 | + trap->key.ipv4.proto.mask[0] = 0xff; | |
| 1451 | 1457 | trap->key.ipv4.dport.value = PTP_GEN_PORT; |
| 1452 | 1458 | trap->key.ipv4.dport.mask = 0xffff; |
| 1453 | 1459 | } |
| @@ -1456,6 +1462,8 @@ static void · 2 unmodified lines | ||
| 1456 | 1462 | ocelot_populate_ipv6_ptp_general_trap_key(struct ocelot_vcap_filter *trap) |
| 1457 | 1463 | { |
| 1458 | 1464 | trap->key_type = OCELOT_VCAP_KEY_IPV6; |
| 1465 | + trap->key.ipv4.proto.value[0] = IPPROTO_UDP; | |
| 1466 | + trap->key.ipv4.proto.mask[0] = 0xff; | |
| 1459 | 1467 | trap->key.ipv6.dport.value = PTP_GEN_PORT; |
| 1460 | 1468 | trap->key.ipv6.dport.mask = 0xffff; |
| 1461 | 1469 | } |
| @@ -1737,12 +1745,11 @@ void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data) · 275 unmodified lines | ||
| 1737 | 1745 | } |
| 1738 | 1746 | EXPORT_SYMBOL(ocelot_get_strings); |
| 1739 | 1747 | |
| 1748 | +/* Caller must hold &ocelot->stats_lock */ | |
| 1740 | 1749 | static void ocelot_update_stats(struct ocelot *ocelot) |
| 1741 | 1750 | { |
| 1742 | 1751 | int i, j; |
| 1743 | 1752 | |
| 1744 | − mutex_lock(&ocelot->stats_lock); | |
| 1745 | − | |
| 1746 | 1753 | for (i = 0; i < ocelot->num_phys_ports; i++) { |
| 1747 | 1754 | /* Configure the port to read the stats from */ |
| 1748 | 1755 | ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(i), SYS_STAT_CFG); |
| @@ -1761,8 +1768,6 @@ static void ocelot_update_stats(struct ocelot *ocelot) · 12 unmodified lines | ||
| 1761 | 1768 | ~(u64)U32_MAX) + val; |
| 1762 | 1769 | } |
| 1763 | 1770 | } |
| 1764 | − | |
| 1765 | − mutex_unlock(&ocelot->stats_lock); | |
| 1766 | 1771 | } |
| 1767 | 1772 | |
| 1768 | 1773 | static void ocelot_check_stats_work(struct work_struct *work) |
| @@ -1771,7 +1776,9 @@ static void ocelot_check_stats_work(struct work_struct *work) · 2 unmodified lines | ||
| 1771 | 1776 | struct ocelot *ocelot = container_of(del_work, struct ocelot, |
| 1772 | 1777 | stats_work); |
| 1773 | 1778 | |
| 1779 | + mutex_lock(&ocelot->stats_lock); | |
| 1774 | 1780 | ocelot_update_stats(ocelot); |
| 1781 | + mutex_unlock(&ocelot->stats_lock); | |
| 1775 | 1782 | |
| 1776 | 1783 | queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, |
| 1777 | 1784 | OCELOT_STATS_CHECK_DELAY); |
| @@ -1781,12 +1788,16 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data) · 3 unmodified lines | ||
| 1781 | 1788 | { |
| 1782 | 1789 | int i; |
| 1783 | 1790 | |
| 1791 | + mutex_lock(&ocelot->stats_lock); | |
| 1792 | + | |
| 1784 | 1793 | /* check and update now */ |
| 1785 | 1794 | ocelot_update_stats(ocelot); |
| 1786 | 1795 | |
| 1787 | 1796 | /* Copy all counters */ |
| 1788 | 1797 | for (i = 0; i < ocelot->num_stats; i++) |
| 1789 | 1798 | *data++ = ocelot->stats[port * ocelot->num_stats + i]; |
| 1799 | + | |
| 1800 | + mutex_unlock(&ocelot->stats_lock); | |
| 1790 | 1801 | } |
| 1791 | 1802 | EXPORT_SYMBOL(ocelot_get_ethtool_stats); |
| 1792 | 1803 | |
| @@ -1011,6 +1011,7 @@ nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, · 1010 unmodified lines | ||
| 1011 | 1011 | struct nfp_flower_repr_priv *repr_priv; |
| 1012 | 1012 | struct nfp_tun_offloaded_mac *entry; |
| 1013 | 1013 | struct nfp_repr *repr; |
| 1014 | + u16 nfp_mac_idx; | |
| 1014 | 1015 | int ida_idx; |
| 1015 | 1016 | |
| 1016 | 1017 | entry = nfp_tunnel_lookup_offloaded_macs(app, mac); |
| @@ -1029,8 +1030,6 @@ nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, · 12 unmodified lines | ||
| 1029 | 1030 | entry->bridge_count--; |
| 1030 | 1031 | |
| 1031 | 1032 | if (!entry->bridge_count && entry->ref_count) { |
| 1032 | − u16 nfp_mac_idx; | |
| 1033 | − | |
| 1034 | 1033 | nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; |
| 1035 | 1034 | if (__nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, |
| 1036 | 1035 | false)) { |
| @@ -1046,7 +1045,6 @@ nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, · 9 unmodified lines | ||
| 1046 | 1045 | |
| 1047 | 1046 | /* If MAC is now used by 1 repr set the offloaded MAC index to port. */ |
| 1048 | 1047 | if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) { |
| 1049 | − u16 nfp_mac_idx; | |
| 1050 | 1048 | int port, err; |
| 1051 | 1049 | |
| 1052 | 1050 | repr_priv = list_first_entry(&entry->repr_list, |
| @@ -1074,8 +1072,14 @@ nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, · 21 unmodified lines | ||
| 1074 | 1072 | WARN_ON_ONCE(rhashtable_remove_fast(&priv->tun.offloaded_macs, |
| 1075 | 1073 | &entry->ht_node, |
| 1076 | 1074 | offloaded_macs_params)); |
| 1075 | + | |
| 1076 | + if (nfp_flower_is_supported_bridge(netdev)) | |
| 1077 | + nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; | |
| 1078 | + else | |
| 1079 | + nfp_mac_idx = entry->index; | |
| 1080 | + | |
| 1077 | 1081 | /* If MAC has global ID then extract and free the ida entry. */ |
| 1078 | − if (nfp_tunnel_is_mac_idx_global(entry->index)) { | |
| 1082 | + if (nfp_tunnel_is_mac_idx_global(nfp_mac_idx)) { | |
| 1079 | 1083 | ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index); |
| 1080 | 1084 | ida_simple_remove(&priv->tun.mac_off_ids, ida_idx); |
| 1081 | 1085 | } |
| @@ -148,6 +148,7 @@ static const struct of_device_id aspeed_mdio_of_match[] = { · 147 unmodified lines | ||
| 148 | 148 | { .compatible = "aspeed,ast2600-mdio", }, |
| 149 | 149 | { }, |
| 150 | 150 | }; |
| 151 | +MODULE_DEVICE_TABLE(of, aspeed_mdio_of_match); | |
| 151 | 152 | |
| 152 | 153 | static struct platform_driver aspeed_mdio_driver = { |
| 153 | 154 | .driver = { |
| @@ -553,9 +553,9 @@ static int m88e1121_config_aneg_rgmii_delays(struct phy_device *phydev) · 552 unmodified lines | ||
| 553 | 553 | else |
| 554 | 554 | mscr = 0; |
| 555 | 555 | |
| 556 | − return phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE, | |
| 557 | − MII_88E1121_PHY_MSCR_REG, | |
| 558 | − MII_88E1121_PHY_MSCR_DELAY_MASK, mscr); | |
| 556 | + return phy_modify_paged_changed(phydev, MII_MARVELL_MSCR_PAGE, | |
| 557 | + MII_88E1121_PHY_MSCR_REG, | |
| 558 | + MII_88E1121_PHY_MSCR_DELAY_MASK, mscr); | |
| 559 | 559 | } |
| 560 | 560 | |
| 561 | 561 | static int m88e1121_config_aneg(struct phy_device *phydev) |
| @@ -569,11 +569,13 @@ static int m88e1121_config_aneg(struct phy_device *phydev) · 7 unmodified lines | ||
| 569 | 569 | return err; |
| 570 | 570 | } |
| 571 | 571 | |
| 572 | + changed = err; | |
| 573 | + | |
| 572 | 574 | err = marvell_set_polarity(phydev, phydev->mdix_ctrl); |
| 573 | 575 | if (err < 0) |
| 574 | 576 | return err; |
| 575 | 577 | |
| 576 | − changed = err; | |
| 578 | + changed |= err; | |
| 577 | 579 | |
| 578 | 580 | err = genphy_config_aneg(phydev); |
| 579 | 581 | if (err < 0) |
| @@ -1213,16 +1215,15 @@ static int m88e1118_config_aneg(struct phy_device *phydev) · 633 unmodified lines | ||
| 1213 | 1215 | { |
| 1214 | 1216 | int err; |
| 1215 | 1217 | |
| 1216 | − err = genphy_soft_reset(phydev); | |
| 1218 | + err = marvell_set_polarity(phydev, phydev->mdix_ctrl); | |
| 1217 | 1219 | if (err < 0) |
| 1218 | 1220 | return err; |
| 1219 | 1221 | |
| 1220 | − err = marvell_set_polarity(phydev, phydev->mdix_ctrl); | |
| 1222 | + err = genphy_config_aneg(phydev); | |
| 1221 | 1223 | if (err < 0) |
| 1222 | 1224 | return err; |
| 1223 | 1225 | |
| 1224 | − err = genphy_config_aneg(phydev); | |
| 1225 | − return 0; | |
| 1226 | + return genphy_soft_reset(phydev); | |
| 1226 | 1227 | } |
| 1227 | 1228 | |
| 1228 | 1229 | static int m88e1118_config_init(struct phy_device *phydev) |
| @@ -1400,6 +1400,8 @@ static const struct usb_device_id products[] = { · 1399 unmodified lines | ||
| 1400 | 1400 | {QMI_FIXED_INTF(0x413c, 0x81d7, 0)}, /* Dell Wireless 5821e */ |
| 1401 | 1401 | {QMI_FIXED_INTF(0x413c, 0x81d7, 1)}, /* Dell Wireless 5821e preproduction config */ |
| 1402 | 1402 | {QMI_FIXED_INTF(0x413c, 0x81e0, 0)}, /* Dell Wireless 5821e with eSIM support*/ |
| 1403 | + {QMI_FIXED_INTF(0x413c, 0x81e4, 0)}, /* Dell Wireless 5829e with eSIM support*/ | |
| 1404 | + {QMI_FIXED_INTF(0x413c, 0x81e6, 0)}, /* Dell Wireless 5829e */ | |
| 1403 | 1405 | {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ |
| 1404 | 1406 | {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ |
| 1405 | 1407 | {QMI_QUIRK_SET_DTR(0x22de, 0x9051, 2)}, /* Hucom Wireless HM-211S/K */ |
| @@ -265,9 +265,10 @@ static void __veth_xdp_flush(struct veth_rq *rq) · 264 unmodified lines | ||
| 265 | 265 | { |
| 266 | 266 | /* Write ptr_ring before reading rx_notify_masked */ |
| 267 | 267 | smp_mb(); |
| 268 | − if (!rq->rx_notify_masked) { | |
| 269 | − rq->rx_notify_masked = true; | |
| 270 | − napi_schedule(&rq->xdp_napi); | |
| 268 | + if (!READ_ONCE(rq->rx_notify_masked) && | |
| 269 | + napi_schedule_prep(&rq->xdp_napi)) { | |
| 270 | + WRITE_ONCE(rq->rx_notify_masked, true); | |
| 271 | + __napi_schedule(&rq->xdp_napi); | |
| 271 | 272 | } |
| 272 | 273 | } |
| 273 | 274 | |
| @@ -912,8 +913,10 @@ static int veth_poll(struct napi_struct *napi, int budget) · 638 unmodified lines | ||
| 912 | 913 | /* Write rx_notify_masked before reading ptr_ring */ |
| 913 | 914 | smp_store_mb(rq->rx_notify_masked, false); |
| 914 | 915 | if (unlikely(!__ptr_ring_empty(&rq->xdp_ring))) { |
| 915 | − rq->rx_notify_masked = true; | |
| 916 | − napi_schedule(&rq->xdp_napi); | |
| 916 | + if (napi_schedule_prep(&rq->xdp_napi)) { | |
| 917 | + WRITE_ONCE(rq->rx_notify_masked, true); | |
| 918 | + __napi_schedule(&rq->xdp_napi); | |
| 919 | + } | |
| 917 | 920 | } |
| 918 | 921 | } |
| 919 | 922 | |
| @@ -4253,7 +4253,14 @@ static void nvme_async_event_work(struct work_struct *work) · 4252 unmodified lines | ||
| 4253 | 4253 | container_of(work, struct nvme_ctrl, async_event_work); |
| 4254 | 4254 | |
| 4255 | 4255 | nvme_aen_uevent(ctrl); |
| 4256 | − ctrl->ops->submit_async_event(ctrl); | |
| 4256 | + | |
| 4257 | + /* | |
| 4258 | + * The transport drivers must guarantee AER submission here is safe by | |
| 4259 | + * flushing ctrl async_event_work after changing the controller state | |
| 4260 | + * from LIVE and before freeing the admin queue. | |
| 4261 | + */ | |
| 4262 | + if (ctrl->state == NVME_CTRL_LIVE) | |
| 4263 | + ctrl->ops->submit_async_event(ctrl); | |
| 4257 | 4264 | } |
| 4258 | 4265 | |
| 4259 | 4266 | static bool nvme_ctrl_pp_status(struct nvme_ctrl *ctrl) |
| @@ -170,6 +170,7 @@ nvmf_ctlr_matches_baseopts(struct nvme_ctrl *ctrl, · 169 unmodified lines | ||
| 170 | 170 | struct nvmf_ctrl_options *opts) |
| 171 | 171 | { |
| 172 | 172 | if (ctrl->state == NVME_CTRL_DELETING || |
| 173 | + ctrl->state == NVME_CTRL_DELETING_NOIO || | |
| 173 | 174 | ctrl->state == NVME_CTRL_DEAD || |
| 174 | 175 | strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) || |
| 175 | 176 | strcmp(opts->host->nqn, ctrl->opts->host->nqn) || |
| @@ -1200,6 +1200,7 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work) · 1199 unmodified lines | ||
| 1200 | 1200 | struct nvme_rdma_ctrl, err_work); |
| 1201 | 1201 | |
| 1202 | 1202 | nvme_stop_keep_alive(&ctrl->ctrl); |
| 1203 | + flush_work(&ctrl->ctrl.async_event_work); | |
| 1203 | 1204 | nvme_rdma_teardown_io_queues(ctrl, false); |
| 1204 | 1205 | nvme_start_queues(&ctrl->ctrl); |
| 1205 | 1206 | nvme_rdma_teardown_admin_queue(ctrl, false); |
| @@ -2096,6 +2096,7 @@ static void nvme_tcp_error_recovery_work(struct work_struct *work) · 2095 unmodified lines | ||
| 2096 | 2096 | struct nvme_ctrl *ctrl = &tcp_ctrl->ctrl; |
| 2097 | 2097 | |
| 2098 | 2098 | nvme_stop_keep_alive(ctrl); |
| 2099 | + flush_work(&ctrl->async_event_work); | |
| 2099 | 2100 | nvme_tcp_teardown_io_queues(ctrl, false); |
| 2100 | 2101 | /* unquiesce to fail fast pending requests */ |
| 2101 | 2102 | nvme_start_queues(ctrl); |
| @@ -356,8 +356,8 @@ static int j721e_pcie_probe(struct platform_device *pdev) · 355 unmodified lines | ||
| 356 | 356 | const struct j721e_pcie_data *data; |
| 357 | 357 | struct cdns_pcie *cdns_pcie; |
| 358 | 358 | struct j721e_pcie *pcie; |
| 359 | − struct cdns_pcie_rc *rc; | |
| 360 | − struct cdns_pcie_ep *ep; | |
| 359 | + struct cdns_pcie_rc *rc = NULL; | |
| 360 | + struct cdns_pcie_ep *ep = NULL; | |
| 361 | 361 | struct gpio_desc *gpiod; |
| 362 | 362 | void __iomem *base; |
| 363 | 363 | struct clk *clk; |
| @@ -376,6 +376,46 @@ static int j721e_pcie_probe(struct platform_device *pdev) · 12 unmodified lines | ||
| 376 | 376 | if (!pcie) |
| 377 | 377 | return -ENOMEM; |
| 378 | 378 | |
| 379 | + switch (mode) { | |
| 380 | + case PCI_MODE_RC: | |
| 381 | + if (!IS_ENABLED(CONFIG_PCIE_CADENCE_HOST)) | |
| 382 | + return -ENODEV; | |
| 383 | + | |
| 384 | + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc)); | |
| 385 | + if (!bridge) | |
| 386 | + return -ENOMEM; | |
| 387 | + | |
| 388 | + if (!data->byte_access_allowed) | |
| 389 | + bridge->ops = &cdns_ti_pcie_host_ops; | |
| 390 | + rc = pci_host_bridge_priv(bridge); | |
| 391 | + rc->quirk_retrain_flag = data->quirk_retrain_flag; | |
| 392 | + rc->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag; | |
| 393 | + | |
| 394 | + cdns_pcie = &rc->pcie; | |
| 395 | + cdns_pcie->dev = dev; | |
| 396 | + cdns_pcie->ops = &j721e_pcie_ops; | |
| 397 | + pcie->cdns_pcie = cdns_pcie; | |
| 398 | + break; | |
| 399 | + case PCI_MODE_EP: | |
| 400 | + if (!IS_ENABLED(CONFIG_PCIE_CADENCE_EP)) | |
| 401 | + return -ENODEV; | |
| 402 | + | |
| 403 | + ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); | |
| 404 | + if (!ep) | |
| 405 | + return -ENOMEM; | |
| 406 | + | |
| 407 | + ep->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag; | |
| 408 | + | |
| 409 | + cdns_pcie = &ep->pcie; | |
| 410 | + cdns_pcie->dev = dev; | |
| 411 | + cdns_pcie->ops = &j721e_pcie_ops; | |
| 412 | + pcie->cdns_pcie = cdns_pcie; | |
| 413 | + break; | |
| 414 | + default: | |
| 415 | + dev_err(dev, "INVALID device type %d\n", mode); | |
| 416 | + return 0; | |
| 417 | + } | |
| 418 | + | |
| 379 | 419 | pcie->mode = mode; |
| 380 | 420 | pcie->linkdown_irq_regfield = data->linkdown_irq_regfield; |
| 381 | 421 | |
| @@ -426,28 +466,6 @@ static int j721e_pcie_probe(struct platform_device *pdev) · 44 unmodified lines | ||
| 426 | 466 | |
| 427 | 467 | switch (mode) { |
| 428 | 468 | case PCI_MODE_RC: |
| 429 | − if (!IS_ENABLED(CONFIG_PCIE_CADENCE_HOST)) { | |
| 430 | − ret = -ENODEV; | |
| 431 | − goto err_get_sync; | |
| 432 | − } | |
| 433 | − | |
| 434 | − bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc)); | |
| 435 | − if (!bridge) { | |
| 436 | − ret = -ENOMEM; | |
| 437 | − goto err_get_sync; | |
| 438 | − } | |
| 439 | − | |
| 440 | − if (!data->byte_access_allowed) | |
| 441 | − bridge->ops = &cdns_ti_pcie_host_ops; | |
| 442 | − rc = pci_host_bridge_priv(bridge); | |
| 443 | − rc->quirk_retrain_flag = data->quirk_retrain_flag; | |
| 444 | − rc->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag; | |
| 445 | − | |
| 446 | − cdns_pcie = &rc->pcie; | |
| 447 | − cdns_pcie->dev = dev; | |
| 448 | − cdns_pcie->ops = &j721e_pcie_ops; | |
| 449 | − pcie->cdns_pcie = cdns_pcie; | |
| 450 | − | |
| 451 | 469 | gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); |
| 452 | 470 | if (IS_ERR(gpiod)) { |
| 453 | 471 | ret = PTR_ERR(gpiod); |
| @@ -497,23 +515,6 @@ static int j721e_pcie_probe(struct platform_device *pdev) · 43 unmodified lines | ||
| 497 | 515 | |
| 498 | 516 | break; |
| 499 | 517 | case PCI_MODE_EP: |
| 500 | − if (!IS_ENABLED(CONFIG_PCIE_CADENCE_EP)) { | |
| 501 | − ret = -ENODEV; | |
| 502 | − goto err_get_sync; | |
| 503 | − } | |
| 504 | − | |
| 505 | − ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); | |
| 506 | − if (!ep) { | |
| 507 | − ret = -ENOMEM; | |
| 508 | − goto err_get_sync; | |
| 509 | − } | |
| 510 | − ep->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag; | |
| 511 | − | |
| 512 | − cdns_pcie = &ep->pcie; | |
| 513 | − cdns_pcie->dev = dev; | |
| 514 | − cdns_pcie->ops = &j721e_pcie_ops; | |
| 515 | − pcie->cdns_pcie = cdns_pcie; | |
| 516 | − | |
| 517 | 518 | ret = cdns_pcie_init_phy(dev, cdns_pcie); |
| 518 | 519 | if (ret) { |
| 519 | 520 | dev_err(dev, "Failed to init phy\n"); |
| @@ -525,8 +526,6 @@ static int j721e_pcie_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 525 | 526 | goto err_pcie_setup; |
| 526 | 527 | |
| 527 | 528 | break; |
| 528 | − default: | |
| 529 | − dev_err(dev, "INVALID device type %d\n", mode); | |
| 530 | 529 | } |
| 531 | 530 | |
| 532 | 531 | return 0; |
| @@ -756,22 +756,28 @@ static int __exit kirin_pcie_remove(struct platform_device *pdev) · 755 unmodified lines | ||
| 756 | 756 | return 0; |
| 757 | 757 | } |
| 758 | 758 | |
| 759 | +struct kirin_pcie_data { | |
| 760 | + enum pcie_kirin_phy_type phy_type; | |
| 761 | +}; | |
| 762 | + | |
| 763 | +static const struct kirin_pcie_data kirin_960_data = { | |
| 764 | + .phy_type = PCIE_KIRIN_INTERNAL_PHY, | |
| 765 | +}; | |
| 766 | + | |
| 767 | +static const struct kirin_pcie_data kirin_970_data = { | |
| 768 | + .phy_type = PCIE_KIRIN_EXTERNAL_PHY, | |
| 769 | +}; | |
| 770 | + | |
| 759 | 771 | static const struct of_device_id kirin_pcie_match[] = { |
| 760 | − { | |
| 761 | − .compatible = "hisilicon,kirin960-pcie", | |
| 762 | − .data = (void *)PCIE_KIRIN_INTERNAL_PHY | |
| 763 | − }, | |
| 764 | − { | |
| 765 | − .compatible = "hisilicon,kirin970-pcie", | |
| 766 | − .data = (void *)PCIE_KIRIN_EXTERNAL_PHY | |
| 767 | − }, | |
| 772 | + { .compatible = "hisilicon,kirin960-pcie", .data = &kirin_960_data }, | |
| 773 | + { .compatible = "hisilicon,kirin970-pcie", .data = &kirin_970_data }, | |
| 768 | 774 | {}, |
| 769 | 775 | }; |
| 770 | 776 | |
| 771 | 777 | static int kirin_pcie_probe(struct platform_device *pdev) |
| 772 | 778 | { |
| 773 | − enum pcie_kirin_phy_type phy_type; | |
| 774 | 779 | struct device *dev = &pdev->dev; |
| 780 | + const struct kirin_pcie_data *data; | |
| 775 | 781 | struct kirin_pcie *kirin_pcie; |
| 776 | 782 | struct dw_pcie *pci; |
| 777 | 783 | int ret; |
| @@ -781,13 +787,12 @@ static int kirin_pcie_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 781 | 787 | return -EINVAL; |
| 782 | 788 | } |
| 783 | 789 | |
| 784 | − phy_type = (long)of_device_get_match_data(dev); | |
| 785 | − if (!phy_type) { | |
| 790 | + data = of_device_get_match_data(dev); | |
| 791 | + if (!data) { | |
| 786 | 792 | dev_err(dev, "OF data missing\n"); |
| 787 | 793 | return -EINVAL; |
| 788 | 794 | } |
| 789 | 795 | |
| 790 | − | |
| 791 | 796 | kirin_pcie = devm_kzalloc(dev, sizeof(struct kirin_pcie), GFP_KERNEL); |
| 792 | 797 | if (!kirin_pcie) |
| 793 | 798 | return -ENOMEM; |
| @@ -800,7 +805,7 @@ static int kirin_pcie_probe(struct platform_device *pdev) · 6 unmodified lines | ||
| 800 | 805 | pci->ops = &kirin_dw_pcie_ops; |
| 801 | 806 | pci->pp.ops = &kirin_pcie_host_ops; |
| 802 | 807 | kirin_pcie->pci = pci; |
| 803 | − kirin_pcie->type = phy_type; | |
| 808 | + kirin_pcie->type = data->phy_type; | |
| 804 | 809 | |
| 805 | 810 | ret = kirin_pcie_get_resource(kirin_pcie, pdev); |
| 806 | 811 | if (ret) |
| @@ -1111,7 +1111,8 @@ const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr) · 1110 unmodified lines | ||
| 1111 | 1111 | if (!desc) |
| 1112 | 1112 | return cpu_possible_mask; |
| 1113 | 1113 | |
| 1114 | − if (WARN_ON_ONCE(!desc->affinity)) | |
| 1114 | + /* MSI[X] interrupts can be allocated without affinity descriptor */ | |
| 1115 | + if (!desc->affinity) | |
| 1115 | 1116 | return NULL; |
| 1116 | 1117 | |
| 1117 | 1118 | /* |
| @@ -508,7 +508,8 @@ static int bnx2fc_l2_rcv_thread(void *arg) · 507 unmodified lines | ||
| 508 | 508 | |
| 509 | 509 | static void bnx2fc_recv_frame(struct sk_buff *skb) |
| 510 | 510 | { |
| 511 | − u32 fr_len; | |
| 511 | + u64 crc_err; | |
| 512 | + u32 fr_len, fr_crc; | |
| 512 | 513 | struct fc_lport *lport; |
| 513 | 514 | struct fcoe_rcv_info *fr; |
| 514 | 515 | struct fc_stats *stats; |
| @@ -542,6 +543,11 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) · 27 unmodified lines | ||
| 542 | 543 | skb_pull(skb, sizeof(struct fcoe_hdr)); |
| 543 | 544 | fr_len = skb->len - sizeof(struct fcoe_crc_eof); |
| 544 | 545 | |
| 546 | + stats = per_cpu_ptr(lport->stats, get_cpu()); | |
| 547 | + stats->RxFrames++; | |
| 548 | + stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; | |
| 549 | + put_cpu(); | |
| 550 | + | |
| 545 | 551 | fp = (struct fc_frame *)skb; |
| 546 | 552 | fc_frame_init(fp); |
| 547 | 553 | fr_dev(fp) = lport; |
| @@ -624,16 +630,15 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) · 76 unmodified lines | ||
| 624 | 630 | return; |
| 625 | 631 | } |
| 626 | 632 | |
| 627 | − stats = per_cpu_ptr(lport->stats, smp_processor_id()); | |
| 628 | − stats->RxFrames++; | |
| 629 | − stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; | |
| 633 | + fr_crc = le32_to_cpu(fr_crc(fp)); | |
| 630 | 634 | |
| 631 | − if (le32_to_cpu(fr_crc(fp)) != | |
| 632 | − ~crc32(~0, skb->data, fr_len)) { | |
| 633 | − if (stats->InvalidCRCCount < 5) | |
| 635 | + if (unlikely(fr_crc != ~crc32(~0, skb->data, fr_len))) { | |
| 636 | + stats = per_cpu_ptr(lport->stats, get_cpu()); | |
| 637 | + crc_err = (stats->InvalidCRCCount++); | |
| 638 | + put_cpu(); | |
| 639 | + if (crc_err < 5) | |
| 634 | 640 | printk(KERN_WARNING PFX "dropping frame with " |
| 635 | 641 | "CRC error\n"); |
| 636 | − stats->InvalidCRCCount++; | |
| 637 | 642 | kfree_skb(skb); |
| 638 | 643 | return; |
| 639 | 644 | } |
| @@ -400,8 +400,7 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba, · 399 unmodified lines | ||
| 400 | 400 | struct hisi_sas_slot *slot, |
| 401 | 401 | struct hisi_sas_dq *dq, |
| 402 | 402 | struct hisi_sas_device *sas_dev, |
| 403 | − struct hisi_sas_internal_abort *abort, | |
| 404 | − struct hisi_sas_tmf_task *tmf) | |
| 403 | + struct hisi_sas_internal_abort *abort) | |
| 405 | 404 | { |
| 406 | 405 | struct hisi_sas_cmd_hdr *cmd_hdr_base; |
| 407 | 406 | int dlvry_queue_slot, dlvry_queue; |
| @@ -427,8 +426,6 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba, · 19 unmodified lines | ||
| 427 | 426 | cmd_hdr_base = hisi_hba->cmd_hdr[dlvry_queue]; |
| 428 | 427 | slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot]; |
| 429 | 428 | |
| 430 | − slot->tmf = tmf; | |
| 431 | − slot->is_internal = tmf; | |
| 432 | 429 | task->lldd_task = slot; |
| 433 | 430 | |
| 434 | 431 | memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr)); |
| @@ -587,7 +584,7 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags, · 152 unmodified lines | ||
| 587 | 584 | slot->is_internal = tmf; |
| 588 | 585 | |
| 589 | 586 | /* protect task_prep and start_delivery sequence */ |
| 590 | − hisi_sas_task_deliver(hisi_hba, slot, dq, sas_dev, NULL, tmf); | |
| 587 | + hisi_sas_task_deliver(hisi_hba, slot, dq, sas_dev, NULL); | |
| 591 | 588 | |
| 592 | 589 | return 0; |
| 593 | 590 | |
| @@ -1380,12 +1377,13 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) · 786 unmodified lines | ||
| 1380 | 1377 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); |
| 1381 | 1378 | struct device *dev = hisi_hba->dev; |
| 1382 | 1379 | int s = sizeof(struct host_to_dev_fis); |
| 1380 | + struct hisi_sas_tmf_task tmf = {}; | |
| 1383 | 1381 | |
| 1384 | 1382 | ata_for_each_link(link, ap, EDGE) { |
| 1385 | 1383 | int pmp = sata_srst_pmp(link); |
| 1386 | 1384 | |
| 1387 | 1385 | hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis); |
| 1388 | − rc = hisi_sas_exec_internal_tmf_task(device, fis, s, NULL); | |
| 1386 | + rc = hisi_sas_exec_internal_tmf_task(device, fis, s, &tmf); | |
| 1389 | 1387 | if (rc != TMF_RESP_FUNC_COMPLETE) |
| 1390 | 1388 | break; |
| 1391 | 1389 | } |
| @@ -1396,7 +1394,7 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) · 4 unmodified lines | ||
| 1396 | 1394 | |
| 1397 | 1395 | hisi_sas_fill_ata_reset_cmd(link->device, 0, pmp, fis); |
| 1398 | 1396 | rc = hisi_sas_exec_internal_tmf_task(device, fis, |
| 1399 | − s, NULL); | |
| 1397 | + s, &tmf); | |
| 1400 | 1398 | if (rc != TMF_RESP_FUNC_COMPLETE) |
| 1401 | 1399 | dev_err(dev, "ata disk %016llx de-reset failed\n", |
| 1402 | 1400 | SAS_ADDR(device->sas_addr)); |
| @@ -2067,7 +2065,7 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, · 664 unmodified lines | ||
| 2067 | 2065 | slot->port = port; |
| 2068 | 2066 | slot->is_internal = true; |
| 2069 | 2067 | |
| 2070 | − hisi_sas_task_deliver(hisi_hba, slot, dq, sas_dev, abort, NULL); | |
| 2068 | + hisi_sas_task_deliver(hisi_hba, slot, dq, sas_dev, abort); | |
| 2071 | 2069 | |
| 2072 | 2070 | return 0; |
| 2073 | 2071 | |
| @@ -2692,7 +2692,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) · 2691 unmodified lines | ||
| 2692 | 2692 | u32 tag = le32_to_cpu(psataPayload->tag); |
| 2693 | 2693 | u32 port_id = le32_to_cpu(psataPayload->port_id); |
| 2694 | 2694 | u32 dev_id = le32_to_cpu(psataPayload->device_id); |
| 2695 | − unsigned long flags; | |
| 2696 | 2695 | |
| 2697 | 2696 | if (event) |
| 2698 | 2697 | pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event); |
| @@ -2724,8 +2723,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) · 25 unmodified lines | ||
| 2724 | 2723 | ts->resp = SAS_TASK_COMPLETE; |
| 2725 | 2724 | ts->stat = SAS_DATA_OVERRUN; |
| 2726 | 2725 | ts->residual = 0; |
| 2727 | − if (pm8001_dev) | |
| 2728 | − atomic_dec(&pm8001_dev->running_req); | |
| 2729 | 2726 | break; |
| 2730 | 2727 | case IO_XFER_ERROR_BREAK: |
| 2731 | 2728 | pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); |
| @@ -2767,7 +2764,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) · 35 unmodified lines | ||
| 2767 | 2764 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); |
| 2768 | 2765 | ts->resp = SAS_TASK_COMPLETE; |
| 2769 | 2766 | ts->stat = SAS_QUEUE_FULL; |
| 2770 | − pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); | |
| 2771 | 2767 | return; |
| 2772 | 2768 | } |
| 2773 | 2769 | break; |
| @@ -2853,20 +2849,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) · 79 unmodified lines | ||
| 2853 | 2849 | ts->stat = SAS_OPEN_TO; |
| 2854 | 2850 | break; |
| 2855 | 2851 | } |
| 2856 | − spin_lock_irqsave(&t->task_state_lock, flags); | |
| 2857 | − t->task_state_flags &= ~SAS_TASK_STATE_PENDING; | |
| 2858 | − t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | |
| 2859 | − t->task_state_flags |= SAS_TASK_STATE_DONE; | |
| 2860 | − if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { | |
| 2861 | − spin_unlock_irqrestore(&t->task_state_lock, flags); | |
| 2862 | − pm8001_dbg(pm8001_ha, FAIL, | |
| 2863 | − "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", | |
| 2864 | − t, event, ts->resp, ts->stat); | |
| 2865 | − pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | |
| 2866 | − } else { | |
| 2867 | − spin_unlock_irqrestore(&t->task_state_lock, flags); | |
| 2868 | − pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); | |
| 2869 | − } | |
| 2870 | 2852 | } |
| 2871 | 2853 | |
| 2872 | 2854 | /*See the comments for mpi_ssp_completion */ |
| @@ -769,8 +769,13 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, · 768 unmodified lines | ||
| 769 | 769 | res = -TMF_RESP_FUNC_FAILED; |
| 770 | 770 | /* Even TMF timed out, return direct. */ |
| 771 | 771 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { |
| 772 | + struct pm8001_ccb_info *ccb = task->lldd_task; | |
| 773 | + | |
| 772 | 774 | pm8001_dbg(pm8001_ha, FAIL, "TMF task[%x]timeout.\n", |
| 773 | 775 | tmf->tmf); |
| 776 | + | |
| 777 | + if (ccb) | |
| 778 | + ccb->task = NULL; | |
| 774 | 779 | goto ex_err; |
| 775 | 780 | } |
| 776 | 781 | |
| @@ -2185,9 +2185,9 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) · 2184 unmodified lines | ||
| 2185 | 2185 | pm8001_dbg(pm8001_ha, FAIL, |
| 2186 | 2186 | "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", |
| 2187 | 2187 | t, status, ts->resp, ts->stat); |
| 2188 | + pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | |
| 2188 | 2189 | if (t->slow_task) |
| 2189 | 2190 | complete(&t->slow_task->completion); |
| 2190 | − pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | |
| 2191 | 2191 | } else { |
| 2192 | 2192 | spin_unlock_irqrestore(&t->task_state_lock, flags); |
| 2193 | 2193 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
| @@ -2794,9 +2794,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, · 600 unmodified lines | ||
| 2794 | 2794 | pm8001_dbg(pm8001_ha, FAIL, |
| 2795 | 2795 | "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", |
| 2796 | 2796 | t, status, ts->resp, ts->stat); |
| 2797 | + pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | |
| 2797 | 2798 | if (t->slow_task) |
| 2798 | 2799 | complete(&t->slow_task->completion); |
| 2799 | − pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | |
| 2800 | 2800 | } else { |
| 2801 | 2801 | spin_unlock_irqrestore(&t->task_state_lock, flags); |
| 2802 | 2802 | spin_unlock_irqrestore(&circularQ->oq_lock, |
| @@ -2821,7 +2821,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, · 18 unmodified lines | ||
| 2821 | 2821 | u32 tag = le32_to_cpu(psataPayload->tag); |
| 2822 | 2822 | u32 port_id = le32_to_cpu(psataPayload->port_id); |
| 2823 | 2823 | u32 dev_id = le32_to_cpu(psataPayload->device_id); |
| 2824 | − unsigned long flags; | |
| 2825 | 2824 | |
| 2826 | 2825 | if (event) |
| 2827 | 2826 | pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event); |
| @@ -2854,8 +2853,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, · 26 unmodified lines | ||
| 2854 | 2853 | ts->resp = SAS_TASK_COMPLETE; |
| 2855 | 2854 | ts->stat = SAS_DATA_OVERRUN; |
| 2856 | 2855 | ts->residual = 0; |
| 2857 | − if (pm8001_dev) | |
| 2858 | − atomic_dec(&pm8001_dev->running_req); | |
| 2859 | 2856 | break; |
| 2860 | 2857 | case IO_XFER_ERROR_BREAK: |
| 2861 | 2858 | pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); |
| @@ -2904,11 +2901,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, · 42 unmodified lines | ||
| 2904 | 2901 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); |
| 2905 | 2902 | ts->resp = SAS_TASK_COMPLETE; |
| 2906 | 2903 | ts->stat = SAS_QUEUE_FULL; |
| 2907 | − spin_unlock_irqrestore(&circularQ->oq_lock, | |
| 2908 | − circularQ->lock_flags); | |
| 2909 | − pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); | |
| 2910 | − spin_lock_irqsave(&circularQ->oq_lock, | |
| 2911 | − circularQ->lock_flags); | |
| 2912 | 2904 | return; |
| 2913 | 2905 | } |
| 2914 | 2906 | break; |
| @@ -3008,24 +3000,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, · 93 unmodified lines | ||
| 3008 | 3000 | ts->stat = SAS_OPEN_TO; |
| 3009 | 3001 | break; |
| 3010 | 3002 | } |
| 3011 | − spin_lock_irqsave(&t->task_state_lock, flags); | |
| 3012 | − t->task_state_flags &= ~SAS_TASK_STATE_PENDING; | |
| 3013 | − t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | |
| 3014 | − t->task_state_flags |= SAS_TASK_STATE_DONE; | |
| 3015 | − if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { | |
| 3016 | − spin_unlock_irqrestore(&t->task_state_lock, flags); | |
| 3017 | − pm8001_dbg(pm8001_ha, FAIL, | |
| 3018 | − "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", | |
| 3019 | − t, event, ts->resp, ts->stat); | |
| 3020 | − pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | |
| 3021 | − } else { | |
| 3022 | − spin_unlock_irqrestore(&t->task_state_lock, flags); | |
| 3023 | − spin_unlock_irqrestore(&circularQ->oq_lock, | |
| 3024 | − circularQ->lock_flags); | |
| 3025 | − pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); | |
| 3026 | − spin_lock_irqsave(&circularQ->oq_lock, | |
| 3027 | − circularQ->lock_flags); | |
| 3028 | − } | |
| 3029 | 3003 | } |
| 3030 | 3004 | |
| 3031 | 3005 | /*See the comments for mpi_ssp_completion */ |
| @@ -3931,6 +3905,7 @@ static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha, · 899 unmodified lines | ||
| 3931 | 3905 | /** |
| 3932 | 3906 | * process_one_iomb - process one outbound Queue memory block |
| 3933 | 3907 | * @pm8001_ha: our hba card information |
| 3908 | + * @circularQ: outbound circular queue | |
| 3934 | 3909 | * @piomb: IO message buffer |
| 3935 | 3910 | */ |
| 3936 | 3911 | static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, |
| @@ -214,6 +214,48 @@ static void scsi_unlock_floptical(struct scsi_device *sdev, · 213 unmodified lines | ||
| 214 | 214 | SCSI_TIMEOUT, 3, NULL); |
| 215 | 215 | } |
| 216 | 216 | |
| 217 | +static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev, | |
| 218 | + unsigned int depth) | |
| 219 | +{ | |
| 220 | + int new_shift = sbitmap_calculate_shift(depth); | |
| 221 | + bool need_alloc = !sdev->budget_map.map; | |
| 222 | + bool need_free = false; | |
| 223 | + int ret; | |
| 224 | + struct sbitmap sb_backup; | |
| 225 | + | |
| 226 | + /* | |
| 227 | + * realloc if new shift is calculated, which is caused by setting | |
| 228 | + * up one new default queue depth after calling ->slave_configure | |
| 229 | + */ | |
| 230 | + if (!need_alloc && new_shift != sdev->budget_map.shift) | |
| 231 | + need_alloc = need_free = true; | |
| 232 | + | |
| 233 | + if (!need_alloc) | |
| 234 | + return 0; | |
| 235 | + | |
| 236 | + /* | |
| 237 | + * Request queue has to be frozen for reallocating budget map, | |
| 238 | + * and here disk isn't added yet, so freezing is pretty fast | |
| 239 | + */ | |
| 240 | + if (need_free) { | |
| 241 | + blk_mq_freeze_queue(sdev->request_queue); | |
| 242 | + sb_backup = sdev->budget_map; | |
| 243 | + } | |
| 244 | + ret = sbitmap_init_node(&sdev->budget_map, | |
| 245 | + scsi_device_max_queue_depth(sdev), | |
| 246 | + new_shift, GFP_KERNEL, | |
| 247 | + sdev->request_queue->node, false, true); | |
| 248 | + if (need_free) { | |
| 249 | + if (ret) | |
| 250 | + sdev->budget_map = sb_backup; | |
| 251 | + else | |
| 252 | + sbitmap_free(&sb_backup); | |
| 253 | + ret = 0; | |
| 254 | + blk_mq_unfreeze_queue(sdev->request_queue); | |
| 255 | + } | |
| 256 | + return ret; | |
| 257 | +} | |
| 258 | + | |
| 217 | 259 | /** |
| 218 | 260 | * scsi_alloc_sdev - allocate and setup a scsi_Device |
| 219 | 261 | * @starget: which target to allocate a &scsi_device for |
| @@ -306,11 +348,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, · 86 unmodified lines | ||
| 306 | 348 | * default device queue depth to figure out sbitmap shift |
| 307 | 349 | * since we use this queue depth most of times. |
| 308 | 350 | */ |
| 309 | − if (sbitmap_init_node(&sdev->budget_map, | |
| 310 | − scsi_device_max_queue_depth(sdev), | |
| 311 | − sbitmap_calculate_shift(depth), | |
| 312 | − GFP_KERNEL, sdev->request_queue->node, | |
| 313 | − false, true)) { | |
| 351 | + if (scsi_realloc_sdev_budget_map(sdev, depth)) { | |
| 314 | 352 | put_device(&starget->dev); |
| 315 | 353 | kfree(sdev); |
| 316 | 354 | goto out; |
| @@ -1017,6 +1055,13 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, · 700 unmodified lines | ||
| 1017 | 1055 | } |
| 1018 | 1056 | return SCSI_SCAN_NO_RESPONSE; |
| 1019 | 1057 | } |
| 1058 | + | |
| 1059 | + /* | |
| 1060 | + * The queue_depth is often changed in ->slave_configure. | |
| 1061 | + * Set up budget map again since memory consumption of | |
| 1062 | + * the map depends on actual queue depth. | |
| 1063 | + */ | |
| 1064 | + scsi_realloc_sdev_budget_map(sdev, sdev->queue_depth); | |
| 1020 | 1065 | } |
| 1021 | 1066 | |
| 1022 | 1067 | if (sdev->scsi_level >= SCSI_3) |
| @@ -78,6 +78,26 @@ config FRAMEBUFFER_CONSOLE · 77 unmodified lines | ||
| 78 | 78 | help |
| 79 | 79 | Low-level framebuffer-based console driver. |
| 80 | 80 | |
| 81 | +config FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION | |
| 82 | + bool "Enable legacy fbcon hardware acceleration code" | |
| 83 | + depends on FRAMEBUFFER_CONSOLE | |
| 84 | + default y if PARISC | |
| 85 | + default n | |
| 86 | + help | |
| 87 | + This option enables the fbcon (framebuffer text-based) hardware | |
| 88 | + acceleration for graphics drivers which were written for the fbdev | |
| 89 | + graphics interface. | |
| 90 | + | |
| 91 | + On modern machines, on mainstream machines (like x86-64) or when | |
| 92 | + using a modern Linux distribution those fbdev drivers usually aren't used. | |
| 93 | + So enabling this option wouldn't have any effect, which is why you want | |
| 94 | + to disable this option on such newer machines. | |
| 95 | + | |
| 96 | + If you compile this kernel for older machines which still require the | |
| 97 | + fbdev drivers, you may want to say Y. | |
| 98 | + | |
| 99 | + If unsure, select n. | |
| 100 | + | |
| 81 | 101 | config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY |
| 82 | 102 | bool "Map the console to the primary display device" |
| 83 | 103 | depends on FRAMEBUFFER_CONSOLE |
| @@ -43,6 +43,21 @@ static void update_attr(u8 *dst, u8 *src, int attribute, · 42 unmodified lines | ||
| 43 | 43 | } |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | +static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |
| 47 | + int sx, int dy, int dx, int height, int width) | |
| 48 | +{ | |
| 49 | + struct fb_copyarea area; | |
| 50 | + | |
| 51 | + area.sx = sx * vc->vc_font.width; | |
| 52 | + area.sy = sy * vc->vc_font.height; | |
| 53 | + area.dx = dx * vc->vc_font.width; | |
| 54 | + area.dy = dy * vc->vc_font.height; | |
| 55 | + area.height = height * vc->vc_font.height; | |
| 56 | + area.width = width * vc->vc_font.width; | |
| 57 | + | |
| 58 | + info->fbops->fb_copyarea(info, &area); | |
| 59 | +} | |
| 60 | + | |
| 46 | 61 | static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 47 | 62 | int sx, int height, int width) |
| 48 | 63 | { |
| @@ -378,6 +393,7 @@ static int bit_update_start(struct fb_info *info) · 329 unmodified lines | ||
| 378 | 393 | |
| 379 | 394 | void fbcon_set_bitops(struct fbcon_ops *ops) |
| 380 | 395 | { |
| 396 | + ops->bmove = bit_bmove; | |
| 381 | 397 | ops->clear = bit_clear; |
| 382 | 398 | ops->putcs = bit_putcs; |
| 383 | 399 | ops->clear_margins = bit_clear_margins; |
| @@ -173,6 +173,8 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, · 172 unmodified lines | ||
| 173 | 173 | int count, int ypos, int xpos); |
| 174 | 174 | static void fbcon_clear_margins(struct vc_data *vc, int bottom_only); |
| 175 | 175 | static void fbcon_cursor(struct vc_data *vc, int mode); |
| 176 | +static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, | |
| 177 | + int height, int width); | |
| 176 | 178 | static int fbcon_switch(struct vc_data *vc); |
| 177 | 179 | static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch); |
| 178 | 180 | static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table); |
| @@ -180,8 +182,16 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table); · 1 unmodified line | ||
| 180 | 182 | /* |
| 181 | 183 | * Internal routines |
| 182 | 184 | */ |
| 185 | +static __inline__ void ywrap_up(struct vc_data *vc, int count); | |
| 186 | +static __inline__ void ywrap_down(struct vc_data *vc, int count); | |
| 187 | +static __inline__ void ypan_up(struct vc_data *vc, int count); | |
| 188 | +static __inline__ void ypan_down(struct vc_data *vc, int count); | |
| 189 | +static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx, | |
| 190 | + int dy, int dx, int height, int width, u_int y_break); | |
| 183 | 191 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, |
| 184 | 192 | int unit); |
| 193 | +static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, | |
| 194 | + int line, int count, int dy); | |
| 185 | 195 | static void fbcon_modechanged(struct fb_info *info); |
| 186 | 196 | static void fbcon_set_all_vcs(struct fb_info *info); |
| 187 | 197 | static void fbcon_start(void); |
| @@ -1015,7 +1025,7 @@ static void fbcon_init(struct vc_data *vc, int init) · 827 unmodified lines | ||
| 1015 | 1025 | struct vc_data *svc = *default_mode; |
| 1016 | 1026 | struct fbcon_display *t, *p = &fb_display[vc->vc_num]; |
| 1017 | 1027 | int logo = 1, new_rows, new_cols, rows, cols; |
| 1018 | − int ret; | |
| 1028 | + int cap, ret; | |
| 1019 | 1029 | |
| 1020 | 1030 | if (WARN_ON(info_idx == -1)) |
| 1021 | 1031 | return; |
| @@ -1024,6 +1034,7 @@ static void fbcon_init(struct vc_data *vc, int init) · 2 unmodified lines | ||
| 1024 | 1034 | con2fb_map[vc->vc_num] = info_idx; |
| 1025 | 1035 | |
| 1026 | 1036 | info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1037 | + cap = info->flags; | |
| 1027 | 1038 | |
| 1028 | 1039 | if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET) |
| 1029 | 1040 | logo_shown = FBCON_LOGO_DONTSHOW; |
| @@ -1125,6 +1136,14 @@ static void fbcon_init(struct vc_data *vc, int init) · 95 unmodified lines | ||
| 1125 | 1136 | |
| 1126 | 1137 | ops->graphics = 0; |
| 1127 | 1138 | |
| 1139 | +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION | |
| 1140 | + if ((cap & FBINFO_HWACCEL_COPYAREA) && | |
| 1141 | + !(cap & FBINFO_HWACCEL_DISABLED)) | |
| 1142 | + p->scrollmode = SCROLL_MOVE; | |
| 1143 | + else /* default to something safe */ | |
| 1144 | + p->scrollmode = SCROLL_REDRAW; | |
| 1145 | +#endif | |
| 1146 | + | |
| 1128 | 1147 | /* |
| 1129 | 1148 | * ++guenther: console.c:vc_allocate() relies on initializing |
| 1130 | 1149 | * vc_{cols,rows}, but we must not set those if we are only |
| @@ -1211,13 +1230,14 @@ finished: · 80 unmodified lines | ||
| 1211 | 1230 | * This system is now divided into two levels because of complications |
| 1212 | 1231 | * caused by hardware scrolling. Top level functions: |
| 1213 | 1232 | * |
| 1214 | − * fbcon_clear(), fbcon_putc(), fbcon_clear_margins() | |
| 1233 | + * fbcon_bmove(), fbcon_clear(), fbcon_putc(), fbcon_clear_margins() | |
| 1215 | 1234 | * |
| 1216 | 1235 | * handles y values in range [0, scr_height-1] that correspond to real |
| 1217 | 1236 | * screen positions. y_wrap shift means that first line of bitmap may be |
| 1218 | 1237 | * anywhere on this display. These functions convert lineoffsets to |
| 1219 | 1238 | * bitmap offsets and deal with the wrap-around case by splitting blits. |
| 1220 | 1239 | * |
| 1240 | + * fbcon_bmove_physical_8() -- These functions fast implementations | |
| 1221 | 1241 | * fbcon_clear_physical_8() -- of original fbcon_XXX fns. |
| 1222 | 1242 | * fbcon_putc_physical_8() -- (font width != 8) may be added later |
| 1223 | 1243 | * |
| @@ -1390,6 +1410,224 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, · 166 unmodified lines | ||
| 1390 | 1410 | } |
| 1391 | 1411 | } |
| 1392 | 1412 | |
| 1413 | +static __inline__ void ywrap_up(struct vc_data *vc, int count) | |
| 1414 | +{ | |
| 1415 | + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | |
| 1416 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 1417 | + struct fbcon_display *p = &fb_display[vc->vc_num]; | |
| 1418 | + | |
| 1419 | + p->yscroll += count; | |
| 1420 | + if (p->yscroll >= p->vrows) /* Deal with wrap */ | |
| 1421 | + p->yscroll -= p->vrows; | |
| 1422 | + ops->var.xoffset = 0; | |
| 1423 | + ops->var.yoffset = p->yscroll * vc->vc_font.height; | |
| 1424 | + ops->var.vmode |= FB_VMODE_YWRAP; | |
| 1425 | + ops->update_start(info); | |
| 1426 | + scrollback_max += count; | |
| 1427 | + if (scrollback_max > scrollback_phys_max) | |
| 1428 | + scrollback_max = scrollback_phys_max; | |
| 1429 | + scrollback_current = 0; | |
| 1430 | +} | |
| 1431 | + | |
| 1432 | +static __inline__ void ywrap_down(struct vc_data *vc, int count) | |
| 1433 | +{ | |
| 1434 | + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | |
| 1435 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 1436 | + struct fbcon_display *p = &fb_display[vc->vc_num]; | |
| 1437 | + | |
| 1438 | + p->yscroll -= count; | |
| 1439 | + if (p->yscroll < 0) /* Deal with wrap */ | |
| 1440 | + p->yscroll += p->vrows; | |
| 1441 | + ops->var.xoffset = 0; | |
| 1442 | + ops->var.yoffset = p->yscroll * vc->vc_font.height; | |
| 1443 | + ops->var.vmode |= FB_VMODE_YWRAP; | |
| 1444 | + ops->update_start(info); | |
| 1445 | + scrollback_max -= count; | |
| 1446 | + if (scrollback_max < 0) | |
| 1447 | + scrollback_max = 0; | |
| 1448 | + scrollback_current = 0; | |
| 1449 | +} | |
| 1450 | + | |
| 1451 | +static __inline__ void ypan_up(struct vc_data *vc, int count) | |
| 1452 | +{ | |
| 1453 | + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | |
| 1454 | + struct fbcon_display *p = &fb_display[vc->vc_num]; | |
| 1455 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 1456 | + | |
| 1457 | + p->yscroll += count; | |
| 1458 | + if (p->yscroll > p->vrows - vc->vc_rows) { | |
| 1459 | + ops->bmove(vc, info, p->vrows - vc->vc_rows, | |
| 1460 | + 0, 0, 0, vc->vc_rows, vc->vc_cols); | |
| 1461 | + p->yscroll -= p->vrows - vc->vc_rows; | |
| 1462 | + } | |
| 1463 | + | |
| 1464 | + ops->var.xoffset = 0; | |
| 1465 | + ops->var.yoffset = p->yscroll * vc->vc_font.height; | |
| 1466 | + ops->var.vmode &= ~FB_VMODE_YWRAP; | |
| 1467 | + ops->update_start(info); | |
| 1468 | + fbcon_clear_margins(vc, 1); | |
| 1469 | + scrollback_max += count; | |
| 1470 | + if (scrollback_max > scrollback_phys_max) | |
| 1471 | + scrollback_max = scrollback_phys_max; | |
| 1472 | + scrollback_current = 0; | |
| 1473 | +} | |
| 1474 | + | |
| 1475 | +static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) | |
| 1476 | +{ | |
| 1477 | + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | |
| 1478 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 1479 | + struct fbcon_display *p = &fb_display[vc->vc_num]; | |
| 1480 | + | |
| 1481 | + p->yscroll += count; | |
| 1482 | + | |
| 1483 | + if (p->yscroll > p->vrows - vc->vc_rows) { | |
| 1484 | + p->yscroll -= p->vrows - vc->vc_rows; | |
| 1485 | + fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t); | |
| 1486 | + } | |
| 1487 | + | |
| 1488 | + ops->var.xoffset = 0; | |
| 1489 | + ops->var.yoffset = p->yscroll * vc->vc_font.height; | |
| 1490 | + ops->var.vmode &= ~FB_VMODE_YWRAP; | |
| 1491 | + ops->update_start(info); | |
| 1492 | + fbcon_clear_margins(vc, 1); | |
| 1493 | + scrollback_max += count; | |
| 1494 | + if (scrollback_max > scrollback_phys_max) | |
| 1495 | + scrollback_max = scrollback_phys_max; | |
| 1496 | + scrollback_current = 0; | |
| 1497 | +} | |
| 1498 | + | |
| 1499 | +static __inline__ void ypan_down(struct vc_data *vc, int count) | |
| 1500 | +{ | |
| 1501 | + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | |
| 1502 | + struct fbcon_display *p = &fb_display[vc->vc_num]; | |
| 1503 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 1504 | + | |
| 1505 | + p->yscroll -= count; | |
| 1506 | + if (p->yscroll < 0) { | |
| 1507 | + ops->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows, | |
| 1508 | + 0, vc->vc_rows, vc->vc_cols); | |
| 1509 | + p->yscroll += p->vrows - vc->vc_rows; | |
| 1510 | + } | |
| 1511 | + | |
| 1512 | + ops->var.xoffset = 0; | |
| 1513 | + ops->var.yoffset = p->yscroll * vc->vc_font.height; | |
| 1514 | + ops->var.vmode &= ~FB_VMODE_YWRAP; | |
| 1515 | + ops->update_start(info); | |
| 1516 | + fbcon_clear_margins(vc, 1); | |
| 1517 | + scrollback_max -= count; | |
| 1518 | + if (scrollback_max < 0) | |
| 1519 | + scrollback_max = 0; | |
| 1520 | + scrollback_current = 0; | |
| 1521 | +} | |
| 1522 | + | |
| 1523 | +static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) | |
| 1524 | +{ | |
| 1525 | + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | |
| 1526 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 1527 | + struct fbcon_display *p = &fb_display[vc->vc_num]; | |
| 1528 | + | |
| 1529 | + p->yscroll -= count; | |
| 1530 | + | |
| 1531 | + if (p->yscroll < 0) { | |
| 1532 | + p->yscroll += p->vrows - vc->vc_rows; | |
| 1533 | + fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count); | |
| 1534 | + } | |
| 1535 | + | |
| 1536 | + ops->var.xoffset = 0; | |
| 1537 | + ops->var.yoffset = p->yscroll * vc->vc_font.height; | |
| 1538 | + ops->var.vmode &= ~FB_VMODE_YWRAP; | |
| 1539 | + ops->update_start(info); | |
| 1540 | + fbcon_clear_margins(vc, 1); | |
| 1541 | + scrollback_max -= count; | |
| 1542 | + if (scrollback_max < 0) | |
| 1543 | + scrollback_max = 0; | |
| 1544 | + scrollback_current = 0; | |
| 1545 | +} | |
| 1546 | + | |
| 1547 | +static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, | |
| 1548 | + int line, int count, int dy) | |
| 1549 | +{ | |
| 1550 | + unsigned short *s = (unsigned short *) | |
| 1551 | + (vc->vc_origin + vc->vc_size_row * line); | |
| 1552 | + | |
| 1553 | + while (count--) { | |
| 1554 | + unsigned short *start = s; | |
| 1555 | + unsigned short *le = advance_row(s, 1); | |
| 1556 | + unsigned short c; | |
| 1557 | + int x = 0; | |
| 1558 | + unsigned short attr = 1; | |
| 1559 | + | |
| 1560 | + do { | |
| 1561 | + c = scr_readw(s); | |
| 1562 | + if (attr != (c & 0xff00)) { | |
| 1563 | + attr = c & 0xff00; | |
| 1564 | + if (s > start) { | |
| 1565 | + fbcon_putcs(vc, start, s - start, | |
| 1566 | + dy, x); | |
| 1567 | + x += s - start; | |
| 1568 | + start = s; | |
| 1569 | + } | |
| 1570 | + } | |
| 1571 | + console_conditional_schedule(); | |
| 1572 | + s++; | |
| 1573 | + } while (s < le); | |
| 1574 | + if (s > start) | |
| 1575 | + fbcon_putcs(vc, start, s - start, dy, x); | |
| 1576 | + console_conditional_schedule(); | |
| 1577 | + dy++; | |
| 1578 | + } | |
| 1579 | +} | |
| 1580 | + | |
| 1581 | +static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, | |
| 1582 | + struct fbcon_display *p, int line, int count, int ycount) | |
| 1583 | +{ | |
| 1584 | + int offset = ycount * vc->vc_cols; | |
| 1585 | + unsigned short *d = (unsigned short *) | |
| 1586 | + (vc->vc_origin + vc->vc_size_row * line); | |
| 1587 | + unsigned short *s = d + offset; | |
| 1588 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 1589 | + | |
| 1590 | + while (count--) { | |
| 1591 | + unsigned short *start = s; | |
| 1592 | + unsigned short *le = advance_row(s, 1); | |
| 1593 | + unsigned short c; | |
| 1594 | + int x = 0; | |
| 1595 | + | |
| 1596 | + do { | |
| 1597 | + c = scr_readw(s); | |
| 1598 | + | |
| 1599 | + if (c == scr_readw(d)) { | |
| 1600 | + if (s > start) { | |
| 1601 | + ops->bmove(vc, info, line + ycount, x, | |
| 1602 | + line, x, 1, s-start); | |
| 1603 | + x += s - start + 1; | |
| 1604 | + start = s + 1; | |
| 1605 | + } else { | |
| 1606 | + x++; | |
| 1607 | + start++; | |
| 1608 | + } | |
| 1609 | + } | |
| 1610 | + | |
| 1611 | + scr_writew(c, d); | |
| 1612 | + console_conditional_schedule(); | |
| 1613 | + s++; | |
| 1614 | + d++; | |
| 1615 | + } while (s < le); | |
| 1616 | + if (s > start) | |
| 1617 | + ops->bmove(vc, info, line + ycount, x, line, x, 1, | |
| 1618 | + s-start); | |
| 1619 | + console_conditional_schedule(); | |
| 1620 | + if (ycount > 0) | |
| 1621 | + line++; | |
| 1622 | + else { | |
| 1623 | + line--; | |
| 1624 | + /* NOTE: We subtract two lines from these pointers */ | |
| 1625 | + s -= vc->vc_size_row; | |
| 1626 | + d -= vc->vc_size_row; | |
| 1627 | + } | |
| 1628 | + } | |
| 1629 | +} | |
| 1630 | + | |
| 1393 | 1631 | static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p, |
| 1394 | 1632 | int line, int count, int offset) |
| 1395 | 1633 | { |
| @@ -1450,6 +1688,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 54 unmodified lines | ||
| 1450 | 1688 | { |
| 1451 | 1689 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1452 | 1690 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1691 | + int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; | |
| 1453 | 1692 | |
| 1454 | 1693 | if (fbcon_is_inactive(vc, info)) |
| 1455 | 1694 | return true; |
| @@ -1466,32 +1705,291 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 10 unmodified lines | ||
| 1466 | 1705 | case SM_UP: |
| 1467 | 1706 | if (count > vc->vc_rows) /* Maximum realistic size */ |
| 1468 | 1707 | count = vc->vc_rows; |
| 1469 | − fbcon_redraw(vc, p, t, b - t - count, | |
| 1470 | − count * vc->vc_cols); | |
| 1471 | − fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1472 | − scr_memsetw((unsigned short *) (vc->vc_origin + | |
| 1473 | − vc->vc_size_row * | |
| 1474 | − (b - count)), | |
| 1475 | − vc->vc_video_erase_char, | |
| 1476 | − vc->vc_size_row * count); | |
| 1477 | − return true; | |
| 1708 | + if (logo_shown >= 0) | |
| 1709 | + goto redraw_up; | |
| 1710 | + switch (fb_scrollmode(p)) { | |
| 1711 | + case SCROLL_MOVE: | |
| 1712 | + fbcon_redraw_blit(vc, info, p, t, b - t - count, | |
| 1713 | + count); | |
| 1714 | + fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1715 | + scr_memsetw((unsigned short *) (vc->vc_origin + | |
| 1716 | + vc->vc_size_row * | |
| 1717 | + (b - count)), | |
| 1718 | + vc->vc_video_erase_char, | |
| 1719 | + vc->vc_size_row * count); | |
| 1720 | + return true; | |
| 1721 | + | |
| 1722 | + case SCROLL_WRAP_MOVE: | |
| 1723 | + if (b - t - count > 3 * vc->vc_rows >> 2) { | |
| 1724 | + if (t > 0) | |
| 1725 | + fbcon_bmove(vc, 0, 0, count, 0, t, | |
| 1726 | + vc->vc_cols); | |
| 1727 | + ywrap_up(vc, count); | |
| 1728 | + if (vc->vc_rows - b > 0) | |
| 1729 | + fbcon_bmove(vc, b - count, 0, b, 0, | |
| 1730 | + vc->vc_rows - b, | |
| 1731 | + vc->vc_cols); | |
| 1732 | + } else if (info->flags & FBINFO_READS_FAST) | |
| 1733 | + fbcon_bmove(vc, t + count, 0, t, 0, | |
| 1734 | + b - t - count, vc->vc_cols); | |
| 1735 | + else | |
| 1736 | + goto redraw_up; | |
| 1737 | + fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1738 | + break; | |
| 1739 | + | |
| 1740 | + case SCROLL_PAN_REDRAW: | |
| 1741 | + if ((p->yscroll + count <= | |
| 1742 | + 2 * (p->vrows - vc->vc_rows)) | |
| 1743 | + && ((!scroll_partial && (b - t == vc->vc_rows)) | |
| 1744 | + || (scroll_partial | |
| 1745 | + && (b - t - count > | |
| 1746 | + 3 * vc->vc_rows >> 2)))) { | |
| 1747 | + if (t > 0) | |
| 1748 | + fbcon_redraw_move(vc, p, 0, t, count); | |
| 1749 | + ypan_up_redraw(vc, t, count); | |
| 1750 | + if (vc->vc_rows - b > 0) | |
| 1751 | + fbcon_redraw_move(vc, p, b, | |
| 1752 | + vc->vc_rows - b, b); | |
| 1753 | + } else | |
| 1754 | + fbcon_redraw_move(vc, p, t + count, b - t - count, t); | |
| 1755 | + fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1756 | + break; | |
| 1757 | + | |
| 1758 | + case SCROLL_PAN_MOVE: | |
| 1759 | + if ((p->yscroll + count <= | |
| 1760 | + 2 * (p->vrows - vc->vc_rows)) | |
| 1761 | + && ((!scroll_partial && (b - t == vc->vc_rows)) | |
| 1762 | + || (scroll_partial | |
| 1763 | + && (b - t - count > | |
| 1764 | + 3 * vc->vc_rows >> 2)))) { | |
| 1765 | + if (t > 0) | |
| 1766 | + fbcon_bmove(vc, 0, 0, count, 0, t, | |
| 1767 | + vc->vc_cols); | |
| 1768 | + ypan_up(vc, count); | |
| 1769 | + if (vc->vc_rows - b > 0) | |
| 1770 | + fbcon_bmove(vc, b - count, 0, b, 0, | |
| 1771 | + vc->vc_rows - b, | |
| 1772 | + vc->vc_cols); | |
| 1773 | + } else if (info->flags & FBINFO_READS_FAST) | |
| 1774 | + fbcon_bmove(vc, t + count, 0, t, 0, | |
| 1775 | + b - t - count, vc->vc_cols); | |
| 1776 | + else | |
| 1777 | + goto redraw_up; | |
| 1778 | + fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1779 | + break; | |
| 1780 | + | |
| 1781 | + case SCROLL_REDRAW: | |
| 1782 | + redraw_up: | |
| 1783 | + fbcon_redraw(vc, p, t, b - t - count, | |
| 1784 | + count * vc->vc_cols); | |
| 1785 | + fbcon_clear(vc, b - count, 0, count, vc->vc_cols); | |
| 1786 | + scr_memsetw((unsigned short *) (vc->vc_origin + | |
| 1787 | + vc->vc_size_row * | |
| 1788 | + (b - count)), | |
| 1789 | + vc->vc_video_erase_char, | |
| 1790 | + vc->vc_size_row * count); | |
| 1791 | + return true; | |
| 1792 | + } | |
| 1793 | + break; | |
| 1478 | 1794 | |
| 1479 | 1795 | case SM_DOWN: |
| 1480 | 1796 | if (count > vc->vc_rows) /* Maximum realistic size */ |
| 1481 | 1797 | count = vc->vc_rows; |
| 1482 | − fbcon_redraw(vc, p, b - 1, b - t - count, | |
| 1483 | − -count * vc->vc_cols); | |
| 1484 | − fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1485 | − scr_memsetw((unsigned short *) (vc->vc_origin + | |
| 1486 | − vc->vc_size_row * | |
| 1487 | − t), | |
| 1488 | − vc->vc_video_erase_char, | |
| 1489 | − vc->vc_size_row * count); | |
| 1490 | − return true; | |
| 1798 | + if (logo_shown >= 0) | |
| 1799 | + goto redraw_down; | |
| 1800 | + switch (fb_scrollmode(p)) { | |
| 1801 | + case SCROLL_MOVE: | |
| 1802 | + fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, | |
| 1803 | + -count); | |
| 1804 | + fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1805 | + scr_memsetw((unsigned short *) (vc->vc_origin + | |
| 1806 | + vc->vc_size_row * | |
| 1807 | + t), | |
| 1808 | + vc->vc_video_erase_char, | |
| 1809 | + vc->vc_size_row * count); | |
| 1810 | + return true; | |
| 1811 | + | |
| 1812 | + case SCROLL_WRAP_MOVE: | |
| 1813 | + if (b - t - count > 3 * vc->vc_rows >> 2) { | |
| 1814 | + if (vc->vc_rows - b > 0) | |
| 1815 | + fbcon_bmove(vc, b, 0, b - count, 0, | |
| 1816 | + vc->vc_rows - b, | |
| 1817 | + vc->vc_cols); | |
| 1818 | + ywrap_down(vc, count); | |
| 1819 | + if (t > 0) | |
| 1820 | + fbcon_bmove(vc, count, 0, 0, 0, t, | |
| 1821 | + vc->vc_cols); | |
| 1822 | + } else if (info->flags & FBINFO_READS_FAST) | |
| 1823 | + fbcon_bmove(vc, t, 0, t + count, 0, | |
| 1824 | + b - t - count, vc->vc_cols); | |
| 1825 | + else | |
| 1826 | + goto redraw_down; | |
| 1827 | + fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1828 | + break; | |
| 1829 | + | |
| 1830 | + case SCROLL_PAN_MOVE: | |
| 1831 | + if ((count - p->yscroll <= p->vrows - vc->vc_rows) | |
| 1832 | + && ((!scroll_partial && (b - t == vc->vc_rows)) | |
| 1833 | + || (scroll_partial | |
| 1834 | + && (b - t - count > | |
| 1835 | + 3 * vc->vc_rows >> 2)))) { | |
| 1836 | + if (vc->vc_rows - b > 0) | |
| 1837 | + fbcon_bmove(vc, b, 0, b - count, 0, | |
| 1838 | + vc->vc_rows - b, | |
| 1839 | + vc->vc_cols); | |
| 1840 | + ypan_down(vc, count); | |
| 1841 | + if (t > 0) | |
| 1842 | + fbcon_bmove(vc, count, 0, 0, 0, t, | |
| 1843 | + vc->vc_cols); | |
| 1844 | + } else if (info->flags & FBINFO_READS_FAST) | |
| 1845 | + fbcon_bmove(vc, t, 0, t + count, 0, | |
| 1846 | + b - t - count, vc->vc_cols); | |
| 1847 | + else | |
| 1848 | + goto redraw_down; | |
| 1849 | + fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1850 | + break; | |
| 1851 | + | |
| 1852 | + case SCROLL_PAN_REDRAW: | |
| 1853 | + if ((count - p->yscroll <= p->vrows - vc->vc_rows) | |
| 1854 | + && ((!scroll_partial && (b - t == vc->vc_rows)) | |
| 1855 | + || (scroll_partial | |
| 1856 | + && (b - t - count > | |
| 1857 | + 3 * vc->vc_rows >> 2)))) { | |
| 1858 | + if (vc->vc_rows - b > 0) | |
| 1859 | + fbcon_redraw_move(vc, p, b, vc->vc_rows - b, | |
| 1860 | + b - count); | |
| 1861 | + ypan_down_redraw(vc, t, count); | |
| 1862 | + if (t > 0) | |
| 1863 | + fbcon_redraw_move(vc, p, count, t, 0); | |
| 1864 | + } else | |
| 1865 | + fbcon_redraw_move(vc, p, t, b - t - count, t + count); | |
| 1866 | + fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1867 | + break; | |
| 1868 | + | |
| 1869 | + case SCROLL_REDRAW: | |
| 1870 | + redraw_down: | |
| 1871 | + fbcon_redraw(vc, p, b - 1, b - t - count, | |
| 1872 | + -count * vc->vc_cols); | |
| 1873 | + fbcon_clear(vc, t, 0, count, vc->vc_cols); | |
| 1874 | + scr_memsetw((unsigned short *) (vc->vc_origin + | |
| 1875 | + vc->vc_size_row * | |
| 1876 | + t), | |
| 1877 | + vc->vc_video_erase_char, | |
| 1878 | + vc->vc_size_row * count); | |
| 1879 | + return true; | |
| 1880 | + } | |
| 1491 | 1881 | } |
| 1492 | 1882 | return false; |
| 1493 | 1883 | } |
| 1494 | 1884 | |
| 1885 | + | |
| 1886 | +static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, | |
| 1887 | + int height, int width) | |
| 1888 | +{ | |
| 1889 | + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | |
| 1890 | + struct fbcon_display *p = &fb_display[vc->vc_num]; | |
| 1891 | + | |
| 1892 | + if (fbcon_is_inactive(vc, info)) | |
| 1893 | + return; | |
| 1894 | + | |
| 1895 | + if (!width || !height) | |
| 1896 | + return; | |
| 1897 | + | |
| 1898 | + /* Split blits that cross physical y_wrap case. | |
| 1899 | + * Pathological case involves 4 blits, better to use recursive | |
| 1900 | + * code rather than unrolled case | |
| 1901 | + * | |
| 1902 | + * Recursive invocations don't need to erase the cursor over and | |
| 1903 | + * over again, so we use fbcon_bmove_rec() | |
| 1904 | + */ | |
| 1905 | + fbcon_bmove_rec(vc, p, sy, sx, dy, dx, height, width, | |
| 1906 | + p->vrows - p->yscroll); | |
| 1907 | +} | |
| 1908 | + | |
| 1909 | +static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx, | |
| 1910 | + int dy, int dx, int height, int width, u_int y_break) | |
| 1911 | +{ | |
| 1912 | + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | |
| 1913 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 1914 | + u_int b; | |
| 1915 | + | |
| 1916 | + if (sy < y_break && sy + height > y_break) { | |
| 1917 | + b = y_break - sy; | |
| 1918 | + if (dy < sy) { /* Avoid trashing self */ | |
| 1919 | + fbcon_bmove_rec(vc, p, sy, sx, dy, dx, b, width, | |
| 1920 | + y_break); | |
| 1921 | + fbcon_bmove_rec(vc, p, sy + b, sx, dy + b, dx, | |
| 1922 | + height - b, width, y_break); | |
| 1923 | + } else { | |
| 1924 | + fbcon_bmove_rec(vc, p, sy + b, sx, dy + b, dx, | |
| 1925 | + height - b, width, y_break); | |
| 1926 | + fbcon_bmove_rec(vc, p, sy, sx, dy, dx, b, width, | |
| 1927 | + y_break); | |
| 1928 | + } | |
| 1929 | + return; | |
| 1930 | + } | |
| 1931 | + | |
| 1932 | + if (dy < y_break && dy + height > y_break) { | |
| 1933 | + b = y_break - dy; | |
| 1934 | + if (dy < sy) { /* Avoid trashing self */ | |
| 1935 | + fbcon_bmove_rec(vc, p, sy, sx, dy, dx, b, width, | |
| 1936 | + y_break); | |
| 1937 | + fbcon_bmove_rec(vc, p, sy + b, sx, dy + b, dx, | |
| 1938 | + height - b, width, y_break); | |
| 1939 | + } else { | |
| 1940 | + fbcon_bmove_rec(vc, p, sy + b, sx, dy + b, dx, | |
| 1941 | + height - b, width, y_break); | |
| 1942 | + fbcon_bmove_rec(vc, p, sy, sx, dy, dx, b, width, | |
| 1943 | + y_break); | |
| 1944 | + } | |
| 1945 | + return; | |
| 1946 | + } | |
| 1947 | + ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, | |
| 1948 | + height, width); | |
| 1949 | +} | |
| 1950 | + | |
| 1951 | +static void updatescrollmode_accel(struct fbcon_display *p, | |
| 1952 | + struct fb_info *info, | |
| 1953 | + struct vc_data *vc) | |
| 1954 | +{ | |
| 1955 | +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION | |
| 1956 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 1957 | + int cap = info->flags; | |
| 1958 | + u16 t = 0; | |
| 1959 | + int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep, | |
| 1960 | + info->fix.xpanstep); | |
| 1961 | + int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t); | |
| 1962 | + int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); | |
| 1963 | + int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual, | |
| 1964 | + info->var.xres_virtual); | |
| 1965 | + int good_pan = (cap & FBINFO_HWACCEL_YPAN) && | |
| 1966 | + divides(ypan, vc->vc_font.height) && vyres > yres; | |
| 1967 | + int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) && | |
| 1968 | + divides(ywrap, vc->vc_font.height) && | |
| 1969 | + divides(vc->vc_font.height, vyres) && | |
| 1970 | + divides(vc->vc_font.height, yres); | |
| 1971 | + int reading_fast = cap & FBINFO_READS_FAST; | |
| 1972 | + int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && | |
| 1973 | + !(cap & FBINFO_HWACCEL_DISABLED); | |
| 1974 | + int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && | |
| 1975 | + !(cap & FBINFO_HWACCEL_DISABLED); | |
| 1976 | + | |
| 1977 | + if (good_wrap || good_pan) { | |
| 1978 | + if (reading_fast || fast_copyarea) | |
| 1979 | + p->scrollmode = good_wrap ? | |
| 1980 | + SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; | |
| 1981 | + else | |
| 1982 | + p->scrollmode = good_wrap ? SCROLL_REDRAW : | |
| 1983 | + SCROLL_PAN_REDRAW; | |
| 1984 | + } else { | |
| 1985 | + if (reading_fast || (fast_copyarea && !fast_imageblit)) | |
| 1986 | + p->scrollmode = SCROLL_MOVE; | |
| 1987 | + else | |
| 1988 | + p->scrollmode = SCROLL_REDRAW; | |
| 1989 | + } | |
| 1990 | +#endif | |
| 1991 | +} | |
| 1992 | + | |
| 1495 | 1993 | static void updatescrollmode(struct fbcon_display *p, |
| 1496 | 1994 | struct fb_info *info, |
| 1497 | 1995 | struct vc_data *vc) |
| @@ -1507,6 +2005,9 @@ static void updatescrollmode(struct fbcon_display *p, · 9 unmodified lines | ||
| 1507 | 2005 | p->vrows -= (yres - (fh * vc->vc_rows)) / fh; |
| 1508 | 2006 | if ((yres % fh) && (vyres % fh < yres % fh)) |
| 1509 | 2007 | p->vrows--; |
| 2008 | + | |
| 2009 | + /* update scrollmode in case hardware acceleration is used */ | |
| 2010 | + updatescrollmode_accel(p, info, vc); | |
| 1510 | 2011 | } |
| 1511 | 2012 | |
| 1512 | 2013 | #define PITCH(w) (((w) + 7) >> 3) |
| @@ -1664,7 +2165,21 @@ static int fbcon_switch(struct vc_data *vc) · 151 unmodified lines | ||
| 1664 | 2165 | |
| 1665 | 2166 | updatescrollmode(p, info, vc); |
| 1666 | 2167 | |
| 1667 | − scrollback_phys_max = 0; | |
| 2168 | + switch (fb_scrollmode(p)) { | |
| 2169 | + case SCROLL_WRAP_MOVE: | |
| 2170 | + scrollback_phys_max = p->vrows - vc->vc_rows; | |
| 2171 | + break; | |
| 2172 | + case SCROLL_PAN_MOVE: | |
| 2173 | + case SCROLL_PAN_REDRAW: | |
| 2174 | + scrollback_phys_max = p->vrows - 2 * vc->vc_rows; | |
| 2175 | + if (scrollback_phys_max < 0) | |
| 2176 | + scrollback_phys_max = 0; | |
| 2177 | + break; | |
| 2178 | + default: | |
| 2179 | + scrollback_phys_max = 0; | |
| 2180 | + break; | |
| 2181 | + } | |
| 2182 | + | |
| 1668 | 2183 | scrollback_max = 0; |
| 1669 | 2184 | scrollback_current = 0; |
| 1670 | 2185 | |
| @@ -29,6 +29,9 @@ struct fbcon_display { · 28 unmodified lines | ||
| 29 | 29 | /* Filled in by the low-level console driver */ |
| 30 | 30 | const u_char *fontdata; |
| 31 | 31 | int userfont; /* != 0 if fontdata kmalloc()ed */ |
| 32 | +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION | |
| 33 | + u_short scrollmode; /* Scroll Method, use fb_scrollmode() */ | |
| 34 | +#endif | |
| 32 | 35 | u_short inverse; /* != 0 text black on white as default */ |
| 33 | 36 | short yscroll; /* Hardware scrolling */ |
| 34 | 37 | int vrows; /* number of virtual rows */ |
| @@ -51,6 +54,8 @@ struct fbcon_display { · 16 unmodified lines | ||
| 51 | 54 | }; |
| 52 | 55 | |
| 53 | 56 | struct fbcon_ops { |
| 57 | + void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, | |
| 58 | + int sx, int dy, int dx, int height, int width); | |
| 54 | 59 | void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, |
| 55 | 60 | int sx, int height, int width); |
| 56 | 61 | void (*putcs)(struct vc_data *vc, struct fb_info *info, |
| @@ -149,6 +154,73 @@ static inline int attr_col_ec(int shift, struct vc_data *vc, · 92 unmodified lines | ||
| 149 | 154 | #define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) |
| 150 | 155 | #define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) |
| 151 | 156 | |
| 157 | + /* | |
| 158 | + * Scroll Method | |
| 159 | + */ | |
| 160 | + | |
| 161 | +/* There are several methods fbcon can use to move text around the screen: | |
| 162 | + * | |
| 163 | + * Operation Pan Wrap | |
| 164 | + *--------------------------------------------- | |
| 165 | + * SCROLL_MOVE copyarea No No | |
| 166 | + * SCROLL_PAN_MOVE copyarea Yes No | |
| 167 | + * SCROLL_WRAP_MOVE copyarea No Yes | |
| 168 | + * SCROLL_REDRAW imageblit No No | |
| 169 | + * SCROLL_PAN_REDRAW imageblit Yes No | |
| 170 | + * SCROLL_WRAP_REDRAW imageblit No Yes | |
| 171 | + * | |
| 172 | + * (SCROLL_WRAP_REDRAW is not implemented yet) | |
| 173 | + * | |
| 174 | + * In general, fbcon will choose the best scrolling | |
| 175 | + * method based on the rule below: | |
| 176 | + * | |
| 177 | + * Pan/Wrap > accel imageblit > accel copyarea > | |
| 178 | + * soft imageblit > (soft copyarea) | |
| 179 | + * | |
| 180 | + * Exception to the rule: Pan + accel copyarea is | |
| 181 | + * preferred over Pan + accel imageblit. | |
| 182 | + * | |
| 183 | + * The above is typical for PCI/AGP cards. Unless | |
| 184 | + * overridden, fbcon will never use soft copyarea. | |
| 185 | + * | |
| 186 | + * If you need to override the above rule, set the | |
| 187 | + * appropriate flags in fb_info->flags. For example, | |
| 188 | + * to prefer copyarea over imageblit, set | |
| 189 | + * FBINFO_READS_FAST. | |
| 190 | + * | |
| 191 | + * Other notes: | |
| 192 | + * + use the hardware engine to move the text | |
| 193 | + * (hw-accelerated copyarea() and fillrect()) | |
| 194 | + * + use hardware-supported panning on a large virtual screen | |
| 195 | + * + amifb can not only pan, but also wrap the display by N lines | |
| 196 | + * (i.e. visible line i = physical line (i+N) % yres). | |
| 197 | + * + read what's already rendered on the screen and | |
| 198 | + * write it in a different place (this is cfb_copyarea()) | |
| 199 | + * + re-render the text to the screen | |
| 200 | + * | |
| 201 | + * Whether to use wrapping or panning can only be figured out at | |
| 202 | + * runtime (when we know whether our font height is a multiple | |
| 203 | + * of the pan/wrap step) | |
| 204 | + * | |
| 205 | + */ | |
| 206 | + | |
| 207 | +#define SCROLL_MOVE 0x001 | |
| 208 | +#define SCROLL_PAN_MOVE 0x002 | |
| 209 | +#define SCROLL_WRAP_MOVE 0x003 | |
| 210 | +#define SCROLL_REDRAW 0x004 | |
| 211 | +#define SCROLL_PAN_REDRAW 0x005 | |
| 212 | + | |
| 213 | +static inline u_short fb_scrollmode(struct fbcon_display *fb) | |
| 214 | +{ | |
| 215 | +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION | |
| 216 | + return fb->scrollmode; | |
| 217 | +#else | |
| 218 | + /* hardcoded to SCROLL_REDRAW if acceleration was disabled. */ | |
| 219 | + return SCROLL_REDRAW; | |
| 220 | +#endif | |
| 221 | +} | |
| 222 | + | |
| 223 | + | |
| 152 | 224 | #ifdef CONFIG_FB_TILEBLITTING |
| 153 | 225 | extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info); |
| 154 | 226 | #endif |
| @@ -59,12 +59,31 @@ static void ccw_update_attr(u8 *dst, u8 *src, int attribute, · 58 unmodified lines | ||
| 59 | 59 | } |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | + | |
| 63 | +static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |
| 64 | + int sx, int dy, int dx, int height, int width) | |
| 65 | +{ | |
| 66 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 67 | + struct fb_copyarea area; | |
| 68 | + u32 vyres = GETVYRES(ops->p, info); | |
| 69 | + | |
| 70 | + area.sx = sy * vc->vc_font.height; | |
| 71 | + area.sy = vyres - ((sx + width) * vc->vc_font.width); | |
| 72 | + area.dx = dy * vc->vc_font.height; | |
| 73 | + area.dy = vyres - ((dx + width) * vc->vc_font.width); | |
| 74 | + area.width = height * vc->vc_font.height; | |
| 75 | + area.height = width * vc->vc_font.width; | |
| 76 | + | |
| 77 | + info->fbops->fb_copyarea(info, &area); | |
| 78 | +} | |
| 79 | + | |
| 62 | 80 | static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 63 | 81 | int sx, int height, int width) |
| 64 | 82 | { |
| 83 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 65 | 84 | struct fb_fillrect region; |
| 66 | 85 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
| 67 | − u32 vyres = info->var.yres; | |
| 86 | + u32 vyres = GETVYRES(ops->p, info); | |
| 68 | 87 | |
| 69 | 88 | region.color = attr_bgcol_ec(bgshift,vc,info); |
| 70 | 89 | region.dx = sy * vc->vc_font.height; |
| @@ -121,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, · 50 unmodified lines | ||
| 121 | 140 | u32 cnt, pitch, size; |
| 122 | 141 | u32 attribute = get_attribute(info, scr_readw(s)); |
| 123 | 142 | u8 *dst, *buf = NULL; |
| 124 | − u32 vyres = info->var.yres; | |
| 143 | + u32 vyres = GETVYRES(ops->p, info); | |
| 125 | 144 | |
| 126 | 145 | if (!ops->fontbuffer) |
| 127 | 146 | return; |
| @@ -210,7 +229,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 82 unmodified lines | ||
| 210 | 229 | int attribute, use_sw = vc->vc_cursor_type & CUR_SW; |
| 211 | 230 | int err = 1, dx, dy; |
| 212 | 231 | char *src; |
| 213 | − u32 vyres = info->var.yres; | |
| 232 | + u32 vyres = GETVYRES(ops->p, info); | |
| 214 | 233 | |
| 215 | 234 | if (!ops->fontbuffer) |
| 216 | 235 | return; |
| @@ -368,7 +387,7 @@ static int ccw_update_start(struct fb_info *info) · 151 unmodified lines | ||
| 368 | 387 | { |
| 369 | 388 | struct fbcon_ops *ops = info->fbcon_par; |
| 370 | 389 | u32 yoffset; |
| 371 | − u32 vyres = info->var.yres; | |
| 390 | + u32 vyres = GETVYRES(ops->p, info); | |
| 372 | 391 | int err; |
| 373 | 392 | |
| 374 | 393 | yoffset = (vyres - info->var.yres) - ops->var.xoffset; |
| @@ -383,6 +402,7 @@ static int ccw_update_start(struct fb_info *info) · 8 unmodified lines | ||
| 383 | 402 | |
| 384 | 403 | void fbcon_rotate_ccw(struct fbcon_ops *ops) |
| 385 | 404 | { |
| 405 | + ops->bmove = ccw_bmove; | |
| 386 | 406 | ops->clear = ccw_clear; |
| 387 | 407 | ops->putcs = ccw_putcs; |
| 388 | 408 | ops->clear_margins = ccw_clear_margins; |
| @@ -44,12 +44,31 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute, · 43 unmodified lines | ||
| 44 | 44 | } |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | + | |
| 48 | +static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |
| 49 | + int sx, int dy, int dx, int height, int width) | |
| 50 | +{ | |
| 51 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 52 | + struct fb_copyarea area; | |
| 53 | + u32 vxres = GETVXRES(ops->p, info); | |
| 54 | + | |
| 55 | + area.sx = vxres - ((sy + height) * vc->vc_font.height); | |
| 56 | + area.sy = sx * vc->vc_font.width; | |
| 57 | + area.dx = vxres - ((dy + height) * vc->vc_font.height); | |
| 58 | + area.dy = dx * vc->vc_font.width; | |
| 59 | + area.width = height * vc->vc_font.height; | |
| 60 | + area.height = width * vc->vc_font.width; | |
| 61 | + | |
| 62 | + info->fbops->fb_copyarea(info, &area); | |
| 63 | +} | |
| 64 | + | |
| 47 | 65 | static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 48 | 66 | int sx, int height, int width) |
| 49 | 67 | { |
| 68 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 50 | 69 | struct fb_fillrect region; |
| 51 | 70 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
| 52 | − u32 vxres = info->var.xres; | |
| 71 | + u32 vxres = GETVXRES(ops->p, info); | |
| 53 | 72 | |
| 54 | 73 | region.color = attr_bgcol_ec(bgshift,vc,info); |
| 55 | 74 | region.dx = vxres - ((sy + height) * vc->vc_font.height); |
| @@ -106,7 +125,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, · 50 unmodified lines | ||
| 106 | 125 | u32 cnt, pitch, size; |
| 107 | 126 | u32 attribute = get_attribute(info, scr_readw(s)); |
| 108 | 127 | u8 *dst, *buf = NULL; |
| 109 | − u32 vxres = info->var.xres; | |
| 128 | + u32 vxres = GETVXRES(ops->p, info); | |
| 110 | 129 | |
| 111 | 130 | if (!ops->fontbuffer) |
| 112 | 131 | return; |
| @@ -193,7 +212,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 80 unmodified lines | ||
| 193 | 212 | int attribute, use_sw = vc->vc_cursor_type & CUR_SW; |
| 194 | 213 | int err = 1, dx, dy; |
| 195 | 214 | char *src; |
| 196 | − u32 vxres = info->var.xres; | |
| 215 | + u32 vxres = GETVXRES(ops->p, info); | |
| 197 | 216 | |
| 198 | 217 | if (!ops->fontbuffer) |
| 199 | 218 | return; |
| @@ -350,7 +369,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 150 unmodified lines | ||
| 350 | 369 | static int cw_update_start(struct fb_info *info) |
| 351 | 370 | { |
| 352 | 371 | struct fbcon_ops *ops = info->fbcon_par; |
| 353 | − u32 vxres = info->var.xres; | |
| 372 | + u32 vxres = GETVXRES(ops->p, info); | |
| 354 | 373 | u32 xoffset; |
| 355 | 374 | int err; |
| 356 | 375 | |
| @@ -366,6 +385,7 @@ static int cw_update_start(struct fb_info *info) · 9 unmodified lines | ||
| 366 | 385 | |
| 367 | 386 | void fbcon_rotate_cw(struct fbcon_ops *ops) |
| 368 | 387 | { |
| 388 | + ops->bmove = cw_bmove; | |
| 369 | 389 | ops->clear = cw_clear; |
| 370 | 390 | ops->putcs = cw_putcs; |
| 371 | 391 | ops->clear_margins = cw_clear_margins; |
| @@ -11,6 +11,15 @@ · 10 unmodified lines | ||
| 11 | 11 | #ifndef _FBCON_ROTATE_H |
| 12 | 12 | #define _FBCON_ROTATE_H |
| 13 | 13 | |
| 14 | +#define GETVYRES(s,i) ({ \ | |
| 15 | + (fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE) ? \ | |
| 16 | + (i)->var.yres : (i)->var.yres_virtual; }) | |
| 17 | + | |
| 18 | +#define GETVXRES(s,i) ({ \ | |
| 19 | + (fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE || !(i)->fix.xpanstep) ? \ | |
| 20 | + (i)->var.xres : (i)->var.xres_virtual; }) | |
| 21 | + | |
| 22 | + | |
| 14 | 23 | static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat) |
| 15 | 24 | { |
| 16 | 25 | u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8; |
| @@ -44,13 +44,33 @@ static void ud_update_attr(u8 *dst, u8 *src, int attribute, · 43 unmodified lines | ||
| 44 | 44 | } |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | + | |
| 48 | +static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |
| 49 | + int sx, int dy, int dx, int height, int width) | |
| 50 | +{ | |
| 51 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 52 | + struct fb_copyarea area; | |
| 53 | + u32 vyres = GETVYRES(ops->p, info); | |
| 54 | + u32 vxres = GETVXRES(ops->p, info); | |
| 55 | + | |
| 56 | + area.sy = vyres - ((sy + height) * vc->vc_font.height); | |
| 57 | + area.sx = vxres - ((sx + width) * vc->vc_font.width); | |
| 58 | + area.dy = vyres - ((dy + height) * vc->vc_font.height); | |
| 59 | + area.dx = vxres - ((dx + width) * vc->vc_font.width); | |
| 60 | + area.height = height * vc->vc_font.height; | |
| 61 | + area.width = width * vc->vc_font.width; | |
| 62 | + | |
| 63 | + info->fbops->fb_copyarea(info, &area); | |
| 64 | +} | |
| 65 | + | |
| 47 | 66 | static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 48 | 67 | int sx, int height, int width) |
| 49 | 68 | { |
| 69 | + struct fbcon_ops *ops = info->fbcon_par; | |
| 50 | 70 | struct fb_fillrect region; |
| 51 | 71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
| 52 | − u32 vyres = info->var.yres; | |
| 53 | − u32 vxres = info->var.xres; | |
| 72 | + u32 vyres = GETVYRES(ops->p, info); | |
| 73 | + u32 vxres = GETVXRES(ops->p, info); | |
| 54 | 74 | |
| 55 | 75 | region.color = attr_bgcol_ec(bgshift,vc,info); |
| 56 | 76 | region.dy = vyres - ((sy + height) * vc->vc_font.height); |
| @@ -142,8 +162,8 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, · 85 unmodified lines | ||
| 142 | 162 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; |
| 143 | 163 | u32 attribute = get_attribute(info, scr_readw(s)); |
| 144 | 164 | u8 *dst, *buf = NULL; |
| 145 | − u32 vyres = info->var.yres; | |
| 146 | − u32 vxres = info->var.xres; | |
| 165 | + u32 vyres = GETVYRES(ops->p, info); | |
| 166 | + u32 vxres = GETVXRES(ops->p, info); | |
| 147 | 167 | |
| 148 | 168 | if (!ops->fontbuffer) |
| 149 | 169 | return; |
| @@ -239,8 +259,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 89 unmodified lines | ||
| 239 | 259 | int attribute, use_sw = vc->vc_cursor_type & CUR_SW; |
| 240 | 260 | int err = 1, dx, dy; |
| 241 | 261 | char *src; |
| 242 | − u32 vyres = info->var.yres; | |
| 243 | − u32 vxres = info->var.xres; | |
| 262 | + u32 vyres = GETVYRES(ops->p, info); | |
| 263 | + u32 vxres = GETVXRES(ops->p, info); | |
| 244 | 264 | |
| 245 | 265 | if (!ops->fontbuffer) |
| 246 | 266 | return; |
| @@ -390,8 +410,8 @@ static int ud_update_start(struct fb_info *info) · 143 unmodified lines | ||
| 390 | 410 | { |
| 391 | 411 | struct fbcon_ops *ops = info->fbcon_par; |
| 392 | 412 | int xoffset, yoffset; |
| 393 | − u32 vyres = info->var.yres; | |
| 394 | − u32 vxres = info->var.xres; | |
| 413 | + u32 vyres = GETVYRES(ops->p, info); | |
| 414 | + u32 vxres = GETVXRES(ops->p, info); | |
| 395 | 415 | int err; |
| 396 | 416 | |
| 397 | 417 | xoffset = vxres - info->var.xres - ops->var.xoffset; |
| @@ -409,6 +429,7 @@ static int ud_update_start(struct fb_info *info) · 11 unmodified lines | ||
| 409 | 429 | |
| 410 | 430 | void fbcon_rotate_ud(struct fbcon_ops *ops) |
| 411 | 431 | { |
| 432 | + ops->bmove = ud_bmove; | |
| 412 | 433 | ops->clear = ud_clear; |
| 413 | 434 | ops->putcs = ud_putcs; |
| 414 | 435 | ops->clear_margins = ud_clear_margins; |
| @@ -16,6 +16,21 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <asm/types.h> |
| 17 | 17 | #include "fbcon.h" |
| 18 | 18 | |
| 19 | +static void tile_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |
| 20 | + int sx, int dy, int dx, int height, int width) | |
| 21 | +{ | |
| 22 | + struct fb_tilearea area; | |
| 23 | + | |
| 24 | + area.sx = sx; | |
| 25 | + area.sy = sy; | |
| 26 | + area.dx = dx; | |
| 27 | + area.dy = dy; | |
| 28 | + area.height = height; | |
| 29 | + area.width = width; | |
| 30 | + | |
| 31 | + info->tileops->fb_tilecopy(info, &area); | |
| 32 | +} | |
| 33 | + | |
| 19 | 34 | static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, |
| 20 | 35 | int sx, int height, int width) |
| 21 | 36 | { |
| @@ -118,6 +133,7 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info) · 96 unmodified lines | ||
| 118 | 133 | struct fb_tilemap map; |
| 119 | 134 | struct fbcon_ops *ops = info->fbcon_par; |
| 120 | 135 | |
| 136 | + ops->bmove = tile_bmove; | |
| 121 | 137 | ops->clear = tile_clear; |
| 122 | 138 | ops->putcs = tile_putcs; |
| 123 | 139 | ops->clear_margins = tile_clear_margins; |
| @@ -505,15 +505,15 @@ void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region) · 504 unmodified lines | ||
| 505 | 505 | } |
| 506 | 506 | |
| 507 | 507 | /** |
| 508 | − * xxxfb_copyarea - OBSOLETE function. | |
| 508 | + * xxxfb_copyarea - REQUIRED function. Can use generic routines if | |
| 509 | + * non acclerated hardware and packed pixel based. | |
| 509 | 510 | * Copies one area of the screen to another area. |
| 510 | − * Will be deleted in a future version | |
| 511 | 511 | * |
| 512 | 512 | * @info: frame buffer structure that represents a single frame buffer |
| 513 | 513 | * @area: Structure providing the data to copy the framebuffer contents |
| 514 | 514 | * from one region to another. |
| 515 | 515 | * |
| 516 | − * This drawing operation copied a rectangular area from one area of the | |
| 516 | + * This drawing operation copies a rectangular area from one area of the | |
| 517 | 517 | * screen to another area. |
| 518 | 518 | */ |
| 519 | 519 | void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) |
| @@ -645,9 +645,9 @@ static const struct fb_ops xxxfb_ops = { · 125 unmodified lines | ||
| 645 | 645 | .fb_setcolreg = xxxfb_setcolreg, |
| 646 | 646 | .fb_blank = xxxfb_blank, |
| 647 | 647 | .fb_pan_display = xxxfb_pan_display, |
| 648 | − .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ | |
| 649 | − .fb_copyarea = xxxfb_copyarea, /* Obsolete */ | |
| 650 | − .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ | |
| 648 | + .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ | |
| 649 | + .fb_copyarea = xxxfb_copyarea, /* Needed !!! */ | |
| 650 | + .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ | |
| 651 | 651 | .fb_cursor = xxxfb_cursor, /* Optional !!! */ |
| 652 | 652 | .fb_sync = xxxfb_sync, |
| 653 | 653 | .fb_ioctl = xxxfb_ioctl, |
| @@ -96,12 +96,8 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) · 95 unmodified lines | ||
| 96 | 96 | dentry, dentry, from_kuid(&init_user_ns, uid), |
| 97 | 97 | any); |
| 98 | 98 | ret = NULL; |
| 99 | − | |
| 100 | − if (d_inode(dentry)) | |
| 101 | − ret = v9fs_fid_find_inode(d_inode(dentry), uid); | |
| 102 | − | |
| 103 | 99 | /* we'll recheck under lock if there's anything to look in */ |
| 104 | − if (!ret && dentry->d_fsdata) { | |
| 100 | + if (dentry->d_fsdata) { | |
| 105 | 101 | struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata; |
| 106 | 102 | |
| 107 | 103 | spin_lock(&dentry->d_lock); |
| @@ -113,6 +109,9 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) · 5 unmodified lines | ||
| 113 | 109 | } |
| 114 | 110 | } |
| 115 | 111 | spin_unlock(&dentry->d_lock); |
| 112 | + } else { | |
| 113 | + if (dentry->d_inode) | |
| 114 | + ret = v9fs_fid_find_inode(dentry->d_inode, uid); | |
| 116 | 115 | } |
| 117 | 116 | |
| 118 | 117 | return ret; |
| @@ -369,8 +369,8 @@ source "fs/ksmbd/Kconfig" · 368 unmodified lines | ||
| 369 | 369 | |
| 370 | 370 | config SMBFS_COMMON |
| 371 | 371 | tristate |
| 372 | − default y if CIFS=y | |
| 373 | − default m if CIFS=m | |
| 372 | + default y if CIFS=y || SMB_SERVER=y | |
| 373 | + default m if CIFS=m || SMB_SERVER=m | |
| 374 | 374 | |
| 375 | 375 | source "fs/coda/Kconfig" |
| 376 | 376 | source "fs/afs/Kconfig" |
| @@ -817,20 +817,16 @@ static struct file_system_type bm_fs_type = { · 816 unmodified lines | ||
| 817 | 817 | }; |
| 818 | 818 | MODULE_ALIAS_FS("binfmt_misc"); |
| 819 | 819 | |
| 820 | −static struct ctl_table_header *binfmt_misc_header; | |
| 821 | − | |
| 822 | 820 | static int __init init_misc_binfmt(void) |
| 823 | 821 | { |
| 824 | 822 | int err = register_filesystem(&bm_fs_type); |
| 825 | 823 | if (!err) |
| 826 | 824 | insert_binfmt(&misc_format); |
| 827 | − binfmt_misc_header = register_sysctl_mount_point("fs/binfmt_misc"); | |
| 828 | − return 0; | |
| 825 | + return err; | |
| 829 | 826 | } |
| 830 | 827 | |
| 831 | 828 | static void __exit exit_misc_binfmt(void) |
| 832 | 829 | { |
| 833 | − unregister_sysctl_table(binfmt_misc_header); | |
| 834 | 830 | unregister_binfmt(&misc_format); |
| 835 | 831 | unregister_filesystem(&bm_fs_type); |
| 836 | 832 | } |
| @@ -124,7 +124,16 @@ void btrfs_put_block_group(struct btrfs_block_group *cache) · 123 unmodified lines | ||
| 124 | 124 | { |
| 125 | 125 | if (refcount_dec_and_test(&cache->refs)) { |
| 126 | 126 | WARN_ON(cache->pinned > 0); |
| 127 | − WARN_ON(cache->reserved > 0); | |
| 127 | + /* | |
| 128 | + * If there was a failure to cleanup a log tree, very likely due | |
| 129 | + * to an IO failure on a writeback attempt of one or more of its | |
| 130 | + * extent buffers, we could not do proper (and cheap) unaccounting | |
| 131 | + * of their reserved space, so don't warn on reserved > 0 in that | |
| 132 | + * case. | |
| 133 | + */ | |
| 134 | + if (!(cache->flags & BTRFS_BLOCK_GROUP_METADATA) || | |
| 135 | + !BTRFS_FS_LOG_CLEANUP_ERROR(cache->fs_info)) | |
| 136 | + WARN_ON(cache->reserved > 0); | |
| 128 | 137 | |
| 129 | 138 | /* |
| 130 | 139 | * A block_group shouldn't be on the discard_list anymore. |
| @@ -2544,6 +2553,19 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache, · 2413 unmodified lines | ||
| 2544 | 2553 | int ret; |
| 2545 | 2554 | bool dirty_bg_running; |
| 2546 | 2555 | |
| 2556 | + /* | |
| 2557 | + * This can only happen when we are doing read-only scrub on read-only | |
| 2558 | + * mount. | |
| 2559 | + * In that case we should not start a new transaction on read-only fs. | |
| 2560 | + * Thus here we skip all chunk allocations. | |
| 2561 | + */ | |
| 2562 | + if (sb_rdonly(fs_info->sb)) { | |
| 2563 | + mutex_lock(&fs_info->ro_block_group_mutex); | |
| 2564 | + ret = inc_block_group_ro(cache, 0); | |
| 2565 | + mutex_unlock(&fs_info->ro_block_group_mutex); | |
| 2566 | + return ret; | |
| 2567 | + } | |
| 2568 | + | |
| 2547 | 2569 | do { |
| 2548 | 2570 | trans = btrfs_join_transaction(root); |
| 2549 | 2571 | if (IS_ERR(trans)) |
| @@ -3974,9 +3996,22 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) · 1424 unmodified lines | ||
| 3974 | 3996 | * important and indicates a real bug if this happens. |
| 3975 | 3997 | */ |
| 3976 | 3998 | if (WARN_ON(space_info->bytes_pinned > 0 || |
| 3977 | − space_info->bytes_reserved > 0 || | |
| 3978 | 3999 | space_info->bytes_may_use > 0)) |
| 3979 | 4000 | btrfs_dump_space_info(info, space_info, 0, 0); |
| 4001 | + | |
| 4002 | + /* | |
| 4003 | + * If there was a failure to cleanup a log tree, very likely due | |
| 4004 | + * to an IO failure on a writeback attempt of one or more of its | |
| 4005 | + * extent buffers, we could not do proper (and cheap) unaccounting | |
| 4006 | + * of their reserved space, so don't warn on bytes_reserved > 0 in | |
| 4007 | + * that case. | |
| 4008 | + */ | |
| 4009 | + if (!(space_info->flags & BTRFS_BLOCK_GROUP_METADATA) || | |
| 4010 | + !BTRFS_FS_LOG_CLEANUP_ERROR(info)) { | |
| 4011 | + if (WARN_ON(space_info->bytes_reserved > 0)) | |
| 4012 | + btrfs_dump_space_info(info, space_info, 0, 0); | |
| 4013 | + } | |
| 4014 | + | |
| 3980 | 4015 | WARN_ON(space_info->reclaim_size > 0); |
| 3981 | 4016 | list_del(&space_info->list); |
| 3982 | 4017 | btrfs_sysfs_remove_space_info(space_info); |
| @@ -145,6 +145,9 @@ enum { · 144 unmodified lines | ||
| 145 | 145 | BTRFS_FS_STATE_DUMMY_FS_INFO, |
| 146 | 146 | |
| 147 | 147 | BTRFS_FS_STATE_NO_CSUMS, |
| 148 | + | |
| 149 | + /* Indicates there was an error cleaning up a log tree. */ | |
| 150 | + BTRFS_FS_STATE_LOG_CLEANUP_ERROR, | |
| 148 | 151 | }; |
| 149 | 152 | |
| 150 | 153 | #define BTRFS_BACKREF_REV_MAX 256 |
| @@ -3593,6 +3596,9 @@ do { \ · 3442 unmodified lines | ||
| 3593 | 3596 | |
| 3594 | 3597 | #define BTRFS_FS_ERROR(fs_info) (unlikely(test_bit(BTRFS_FS_STATE_ERROR, \ |
| 3595 | 3598 | &(fs_info)->fs_state))) |
| 3599 | +#define BTRFS_FS_LOG_CLEANUP_ERROR(fs_info) \ | |
| 3600 | + (unlikely(test_bit(BTRFS_FS_STATE_LOG_CLEANUP_ERROR, \ | |
| 3601 | + &(fs_info)->fs_state))) | |
| 3596 | 3602 | |
| 3597 | 3603 | __printf(5, 6) |
| 3598 | 3604 | __cold |
| @@ -805,10 +805,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, · 804 unmodified lines | ||
| 805 | 805 | goto fail; |
| 806 | 806 | } |
| 807 | 807 | |
| 808 | − spin_lock(&fs_info->trans_lock); | |
| 809 | − list_add(&pending_snapshot->list, | |
| 810 | − &trans->transaction->pending_snapshots); | |
| 811 | − spin_unlock(&fs_info->trans_lock); | |
| 808 | + trans->pending_snapshot = pending_snapshot; | |
| 812 | 809 | |
| 813 | 810 | ret = btrfs_commit_transaction(trans); |
| 814 | 811 | if (ret) |
| @@ -3354,7 +3351,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) · 2539 unmodified lines | ||
| 3354 | 3351 | struct block_device *bdev = NULL; |
| 3355 | 3352 | fmode_t mode; |
| 3356 | 3353 | int ret; |
| 3357 | − bool cancel; | |
| 3354 | + bool cancel = false; | |
| 3358 | 3355 | |
| 3359 | 3356 | if (!capable(CAP_SYS_ADMIN)) |
| 3360 | 3357 | return -EPERM; |
| @@ -1185,9 +1185,24 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) · 1184 unmodified lines | ||
| 1185 | 1185 | struct btrfs_trans_handle *trans = NULL; |
| 1186 | 1186 | int ret = 0; |
| 1187 | 1187 | |
| 1188 | + /* | |
| 1189 | + * We need to have subvol_sem write locked, to prevent races between | |
| 1190 | + * concurrent tasks trying to disable quotas, because we will unlock | |
| 1191 | + * and relock qgroup_ioctl_lock across BTRFS_FS_QUOTA_ENABLED changes. | |
| 1192 | + */ | |
| 1193 | + lockdep_assert_held_write(&fs_info->subvol_sem); | |
| 1194 | + | |
| 1188 | 1195 | mutex_lock(&fs_info->qgroup_ioctl_lock); |
| 1189 | 1196 | if (!fs_info->quota_root) |
| 1190 | 1197 | goto out; |
| 1198 | + | |
| 1199 | + /* | |
| 1200 | + * Request qgroup rescan worker to complete and wait for it. This wait | |
| 1201 | + * must be done before transaction start for quota disable since it may | |
| 1202 | + * deadlock with transaction by the qgroup rescan worker. | |
| 1203 | + */ | |
| 1204 | + clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); | |
| 1205 | + btrfs_qgroup_wait_for_completion(fs_info, false); | |
| 1191 | 1206 | mutex_unlock(&fs_info->qgroup_ioctl_lock); |
| 1192 | 1207 | |
| 1193 | 1208 | /* |
| @@ -1205,14 +1220,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) · 11 unmodified lines | ||
| 1205 | 1220 | if (IS_ERR(trans)) { |
| 1206 | 1221 | ret = PTR_ERR(trans); |
| 1207 | 1222 | trans = NULL; |
| 1223 | + set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); | |
| 1208 | 1224 | goto out; |
| 1209 | 1225 | } |
| 1210 | 1226 | |
| 1211 | 1227 | if (!fs_info->quota_root) |
| 1212 | 1228 | goto out; |
| 1213 | 1229 | |
| 1214 | − clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); | |
| 1215 | − btrfs_qgroup_wait_for_completion(fs_info, false); | |
| 1216 | 1230 | spin_lock(&fs_info->qgroup_lock); |
| 1217 | 1231 | quota_root = fs_info->quota_root; |
| 1218 | 1232 | fs_info->quota_root = NULL; |
| @@ -3383,6 +3397,9 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid, · 2164 unmodified lines | ||
| 3383 | 3397 | btrfs_warn(fs_info, |
| 3384 | 3398 | "qgroup rescan init failed, qgroup is not enabled"); |
| 3385 | 3399 | ret = -EINVAL; |
| 3400 | + } else if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) { | |
| 3401 | + /* Quota disable is in progress */ | |
| 3402 | + ret = -EBUSY; | |
| 3386 | 3403 | } |
| 3387 | 3404 | |
| 3388 | 3405 | if (ret) { |
| @@ -2000,6 +2000,27 @@ static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info) · 1999 unmodified lines | ||
| 2000 | 2000 | btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1); |
| 2001 | 2001 | } |
| 2002 | 2002 | |
| 2003 | +/* | |
| 2004 | + * Add a pending snapshot associated with the given transaction handle to the | |
| 2005 | + * respective handle. This must be called after the transaction commit started | |
| 2006 | + * and while holding fs_info->trans_lock. | |
| 2007 | + * This serves to guarantee a caller of btrfs_commit_transaction() that it can | |
| 2008 | + * safely free the pending snapshot pointer in case btrfs_commit_transaction() | |
| 2009 | + * returns an error. | |
| 2010 | + */ | |
| 2011 | +static void add_pending_snapshot(struct btrfs_trans_handle *trans) | |
| 2012 | +{ | |
| 2013 | + struct btrfs_transaction *cur_trans = trans->transaction; | |
| 2014 | + | |
| 2015 | + if (!trans->pending_snapshot) | |
| 2016 | + return; | |
| 2017 | + | |
| 2018 | + lockdep_assert_held(&trans->fs_info->trans_lock); | |
| 2019 | + ASSERT(cur_trans->state >= TRANS_STATE_COMMIT_START); | |
| 2020 | + | |
| 2021 | + list_add(&trans->pending_snapshot->list, &cur_trans->pending_snapshots); | |
| 2022 | +} | |
| 2023 | + | |
| 2003 | 2024 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans) |
| 2004 | 2025 | { |
| 2005 | 2026 | struct btrfs_fs_info *fs_info = trans->fs_info; |
| @@ -2073,6 +2094,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) · 67 unmodified lines | ||
| 2073 | 2094 | if (cur_trans->state >= TRANS_STATE_COMMIT_START) { |
| 2074 | 2095 | enum btrfs_trans_state want_state = TRANS_STATE_COMPLETED; |
| 2075 | 2096 | |
| 2097 | + add_pending_snapshot(trans); | |
| 2098 | + | |
| 2076 | 2099 | spin_unlock(&fs_info->trans_lock); |
| 2077 | 2100 | refcount_inc(&cur_trans->use_count); |
| 2078 | 2101 | |
| @@ -2163,6 +2186,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) · 84 unmodified lines | ||
| 2163 | 2186 | * COMMIT_DOING so make sure to wait for num_writers to == 1 again. |
| 2164 | 2187 | */ |
| 2165 | 2188 | spin_lock(&fs_info->trans_lock); |
| 2189 | + add_pending_snapshot(trans); | |
| 2166 | 2190 | cur_trans->state = TRANS_STATE_COMMIT_DOING; |
| 2167 | 2191 | spin_unlock(&fs_info->trans_lock); |
| 2168 | 2192 | wait_event(cur_trans->writer_wait, |
| @@ -123,6 +123,8 @@ struct btrfs_trans_handle { · 122 unmodified lines | ||
| 123 | 123 | struct btrfs_transaction *transaction; |
| 124 | 124 | struct btrfs_block_rsv *block_rsv; |
| 125 | 125 | struct btrfs_block_rsv *orig_rsv; |
| 126 | + /* Set by a task that wants to create a snapshot. */ | |
| 127 | + struct btrfs_pending_snapshot *pending_snapshot; | |
| 126 | 128 | refcount_t use_count; |
| 127 | 129 | unsigned int type; |
| 128 | 130 | /* |
| @@ -965,6 +965,7 @@ static int check_dev_item(struct extent_buffer *leaf, · 964 unmodified lines | ||
| 965 | 965 | struct btrfs_key *key, int slot) |
| 966 | 966 | { |
| 967 | 967 | struct btrfs_dev_item *ditem; |
| 968 | + const u32 item_size = btrfs_item_size(leaf, slot); | |
| 968 | 969 | |
| 969 | 970 | if (unlikely(key->objectid != BTRFS_DEV_ITEMS_OBJECTID)) { |
| 970 | 971 | dev_item_err(leaf, slot, |
| @@ -972,6 +973,13 @@ static int check_dev_item(struct extent_buffer *leaf, · 1 unmodified line | ||
| 972 | 973 | key->objectid, BTRFS_DEV_ITEMS_OBJECTID); |
| 973 | 974 | return -EUCLEAN; |
| 974 | 975 | } |
| 976 | + | |
| 977 | + if (unlikely(item_size != sizeof(*ditem))) { | |
| 978 | + dev_item_err(leaf, slot, "invalid item size: has %u expect %zu", | |
| 979 | + item_size, sizeof(*ditem)); | |
| 980 | + return -EUCLEAN; | |
| 981 | + } | |
| 982 | + | |
| 975 | 983 | ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); |
| 976 | 984 | if (unlikely(btrfs_device_id(leaf, ditem) != key->offset)) { |
| 977 | 985 | dev_item_err(leaf, slot, |
| @@ -1007,6 +1015,7 @@ static int check_inode_item(struct extent_buffer *leaf, · 29 unmodified lines | ||
| 1007 | 1015 | struct btrfs_inode_item *iitem; |
| 1008 | 1016 | u64 super_gen = btrfs_super_generation(fs_info->super_copy); |
| 1009 | 1017 | u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777); |
| 1018 | + const u32 item_size = btrfs_item_size(leaf, slot); | |
| 1010 | 1019 | u32 mode; |
| 1011 | 1020 | int ret; |
| 1012 | 1021 | u32 flags; |
| @@ -1016,6 +1025,12 @@ static int check_inode_item(struct extent_buffer *leaf, · 3 unmodified lines | ||
| 1016 | 1025 | if (unlikely(ret < 0)) |
| 1017 | 1026 | return ret; |
| 1018 | 1027 | |
| 1028 | + if (unlikely(item_size != sizeof(*iitem))) { | |
| 1029 | + generic_err(leaf, slot, "invalid item size: has %u expect %zu", | |
| 1030 | + item_size, sizeof(*iitem)); | |
| 1031 | + return -EUCLEAN; | |
| 1032 | + } | |
| 1033 | + | |
| 1019 | 1034 | iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); |
| 1020 | 1035 | |
| 1021 | 1036 | /* Here we use super block generation + 1 to handle log tree */ |
| @@ -3414,6 +3414,29 @@ static void free_log_tree(struct btrfs_trans_handle *trans, · 3413 unmodified lines | ||
| 3414 | 3414 | if (log->node) { |
| 3415 | 3415 | ret = walk_log_tree(trans, log, &wc); |
| 3416 | 3416 | if (ret) { |
| 3417 | + /* | |
| 3418 | + * We weren't able to traverse the entire log tree, the | |
| 3419 | + * typical scenario is getting an -EIO when reading an | |
| 3420 | + * extent buffer of the tree, due to a previous writeback | |
| 3421 | + * failure of it. | |
| 3422 | + */ | |
| 3423 | + set_bit(BTRFS_FS_STATE_LOG_CLEANUP_ERROR, | |
| 3424 | + &log->fs_info->fs_state); | |
| 3425 | + | |
| 3426 | + /* | |
| 3427 | + * Some extent buffers of the log tree may still be dirty | |
| 3428 | + * and not yet written back to storage, because we may | |
| 3429 | + * have updates to a log tree without syncing a log tree, | |
| 3430 | + * such as during rename and link operations. So flush | |
| 3431 | + * them out and wait for their writeback to complete, so | |
| 3432 | + * that we properly cleanup their state and pages. | |
| 3433 | + */ | |
| 3434 | + btrfs_write_marked_extents(log->fs_info, | |
| 3435 | + &log->dirty_log_pages, | |
| 3436 | + EXTENT_DIRTY | EXTENT_NEW); | |
| 3437 | + btrfs_wait_tree_log_extents(log, | |
| 3438 | + EXTENT_DIRTY | EXTENT_NEW); | |
| 3439 | + | |
| 3417 | 3440 | if (trans) |
| 3418 | 3441 | btrfs_abort_transaction(trans, ret); |
| 3419 | 3442 | else |
| @@ -191,6 +191,64 @@ presubmission_error: · 190 unmodified lines | ||
| 191 | 191 | return ret; |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | +/* | |
| 195 | + * Query the occupancy of the cache in a region, returning where the next chunk | |
| 196 | + * of data starts and how long it is. | |
| 197 | + */ | |
| 198 | +static int cachefiles_query_occupancy(struct netfs_cache_resources *cres, | |
| 199 | + loff_t start, size_t len, size_t granularity, | |
| 200 | + loff_t *_data_start, size_t *_data_len) | |
| 201 | +{ | |
| 202 | + struct cachefiles_object *object; | |
| 203 | + struct file *file; | |
| 204 | + loff_t off, off2; | |
| 205 | + | |
| 206 | + *_data_start = -1; | |
| 207 | + *_data_len = 0; | |
| 208 | + | |
| 209 | + if (!fscache_wait_for_operation(cres, FSCACHE_WANT_READ)) | |
| 210 | + return -ENOBUFS; | |
| 211 | + | |
| 212 | + object = cachefiles_cres_object(cres); | |
| 213 | + file = cachefiles_cres_file(cres); | |
| 214 | + granularity = max_t(size_t, object->volume->cache->bsize, granularity); | |
| 215 | + | |
| 216 | + _enter("%pD,%li,%llx,%zx/%llx", | |
| 217 | + file, file_inode(file)->i_ino, start, len, | |
| 218 | + i_size_read(file_inode(file))); | |
| 219 | + | |
| 220 | + off = cachefiles_inject_read_error(); | |
| 221 | + if (off == 0) | |
| 222 | + off = vfs_llseek(file, start, SEEK_DATA); | |
| 223 | + if (off == -ENXIO) | |
| 224 | + return -ENODATA; /* Beyond EOF */ | |
| 225 | + if (off < 0 && off >= (loff_t)-MAX_ERRNO) | |
| 226 | + return -ENOBUFS; /* Error. */ | |
| 227 | + if (round_up(off, granularity) >= start + len) | |
| 228 | + return -ENODATA; /* No data in range */ | |
| 229 | + | |
| 230 | + off2 = cachefiles_inject_read_error(); | |
| 231 | + if (off2 == 0) | |
| 232 | + off2 = vfs_llseek(file, off, SEEK_HOLE); | |
| 233 | + if (off2 == -ENXIO) | |
| 234 | + return -ENODATA; /* Beyond EOF */ | |
| 235 | + if (off2 < 0 && off2 >= (loff_t)-MAX_ERRNO) | |
| 236 | + return -ENOBUFS; /* Error. */ | |
| 237 | + | |
| 238 | + /* Round away partial blocks */ | |
| 239 | + off = round_up(off, granularity); | |
| 240 | + off2 = round_down(off2, granularity); | |
| 241 | + if (off2 <= off) | |
| 242 | + return -ENODATA; | |
| 243 | + | |
| 244 | + *_data_start = off; | |
| 245 | + if (off2 > start + len) | |
| 246 | + *_data_len = len; | |
| 247 | + else | |
| 248 | + *_data_len = off2 - off; | |
| 249 | + return 0; | |
| 250 | +} | |
| 251 | + | |
| 194 | 252 | /* |
| 195 | 253 | * Handle completion of a write to the cache. |
| 196 | 254 | */ |
| @@ -545,6 +603,7 @@ static const struct netfs_cache_ops cachefiles_netfs_cache_ops = { · 348 unmodified lines | ||
| 545 | 603 | .write = cachefiles_write, |
| 546 | 604 | .prepare_read = cachefiles_prepare_read, |
| 547 | 605 | .prepare_write = cachefiles_prepare_write, |
| 606 | + .query_occupancy = cachefiles_query_occupancy, | |
| 548 | 607 | }; |
| 549 | 608 | |
| 550 | 609 | /* |
| @@ -162,7 +162,7 @@ static void cifs_resolve_server(struct work_struct *work) · 161 unmodified lines | ||
| 162 | 162 | mutex_unlock(&server->srv_mutex); |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | −/** | |
| 165 | +/* | |
| 166 | 166 | * Mark all sessions and tcons for reconnect. |
| 167 | 167 | * |
| 168 | 168 | * @server needs to be previously set to CifsNeedReconnect. |
| @@ -1831,13 +1831,9 @@ void cifs_put_smb_ses(struct cifs_ses *ses) · 1662 unmodified lines | ||
| 1831 | 1831 | int i; |
| 1832 | 1832 | |
| 1833 | 1833 | for (i = 1; i < chan_count; i++) { |
| 1834 | − /* | |
| 1835 | − * note: for now, we're okay accessing ses->chans | |
| 1836 | − * without chan_lock. But when chans can go away, we'll | |
| 1837 | − * need to introduce ref counting to make sure that chan | |
| 1838 | − * is not freed from under us. | |
| 1839 | − */ | |
| 1834 | + spin_unlock(&ses->chan_lock); | |
| 1840 | 1835 | cifs_put_tcp_session(ses->chans[i].server, 0); |
| 1836 | + spin_lock(&ses->chan_lock); | |
| 1841 | 1837 | ses->chans[i].server = NULL; |
| 1842 | 1838 | } |
| 1843 | 1839 | } |
| @@ -1981,6 +1977,19 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) · 137 unmodified lines | ||
| 1981 | 1977 | } |
| 1982 | 1978 | } |
| 1983 | 1979 | |
| 1980 | + ctx->workstation_name = kstrdup(ses->workstation_name, GFP_KERNEL); | |
| 1981 | + if (!ctx->workstation_name) { | |
| 1982 | + cifs_dbg(FYI, "Unable to allocate memory for workstation_name\n"); | |
| 1983 | + rc = -ENOMEM; | |
| 1984 | + kfree(ctx->username); | |
| 1985 | + ctx->username = NULL; | |
| 1986 | + kfree_sensitive(ctx->password); | |
| 1987 | + ctx->password = NULL; | |
| 1988 | + kfree(ctx->domainname); | |
| 1989 | + ctx->domainname = NULL; | |
| 1990 | + goto out_key_put; | |
| 1991 | + } | |
| 1992 | + | |
| 1984 | 1993 | out_key_put: |
| 1985 | 1994 | up_read(&key->sem); |
| 1986 | 1995 | key_put(key); |
| @@ -4269,8 +4269,6 @@ cifs_readv_complete(struct work_struct *work) · 4268 unmodified lines | ||
| 4269 | 4269 | for (i = 0; i < rdata->nr_pages; i++) { |
| 4270 | 4270 | struct page *page = rdata->pages[i]; |
| 4271 | 4271 | |
| 4272 | − lru_cache_add(page); | |
| 4273 | − | |
| 4274 | 4272 | if (rdata->result == 0 || |
| 4275 | 4273 | (rdata->result == -EAGAIN && got_bytes)) { |
| 4276 | 4274 | flush_dcache_page(page); |
| @@ -4278,12 +4276,12 @@ cifs_readv_complete(struct work_struct *work) · 1 unmodified line | ||
| 4278 | 4276 | } else |
| 4279 | 4277 | SetPageError(page); |
| 4280 | 4278 | |
| 4281 | − unlock_page(page); | |
| 4282 | − | |
| 4283 | 4279 | if (rdata->result == 0 || |
| 4284 | 4280 | (rdata->result == -EAGAIN && got_bytes)) |
| 4285 | 4281 | cifs_readpage_to_fscache(rdata->mapping->host, page); |
| 4286 | 4282 | |
| 4283 | + unlock_page(page); | |
| 4284 | + | |
| 4287 | 4285 | got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes); |
| 4288 | 4286 | |
| 4289 | 4287 | put_page(page); |
| @@ -4340,7 +4338,6 @@ readpages_fill_pages(struct TCP_Server_Info *server, · 50 unmodified lines | ||
| 4340 | 4338 | * fill them until the writes are flushed. |
| 4341 | 4339 | */ |
| 4342 | 4340 | zero_user(page, 0, PAGE_SIZE); |
| 4343 | − lru_cache_add(page); | |
| 4344 | 4341 | flush_dcache_page(page); |
| 4345 | 4342 | SetPageUptodate(page); |
| 4346 | 4343 | unlock_page(page); |
| @@ -4350,7 +4347,6 @@ readpages_fill_pages(struct TCP_Server_Info *server, · 3 unmodified lines | ||
| 4350 | 4347 | continue; |
| 4351 | 4348 | } else { |
| 4352 | 4349 | /* no need to hold page hostage */ |
| 4353 | − lru_cache_add(page); | |
| 4354 | 4350 | unlock_page(page); |
| 4355 | 4351 | put_page(page); |
| 4356 | 4352 | rdata->pages[i] = NULL; |
| @@ -4393,92 +4389,20 @@ cifs_readpages_copy_into_pages(struct TCP_Server_Info *server, · 36 unmodified lines | ||
| 4393 | 4389 | return readpages_fill_pages(server, rdata, iter, iter->count); |
| 4394 | 4390 | } |
| 4395 | 4391 | |
| 4396 | −static int | |
| 4397 | −readpages_get_pages(struct address_space *mapping, struct list_head *page_list, | |
| 4398 | − unsigned int rsize, struct list_head *tmplist, | |
| 4399 | − unsigned int *nr_pages, loff_t *offset, unsigned int *bytes) | |
| 4400 | −{ | |
| 4401 | − struct page *page, *tpage; | |
| 4402 | − unsigned int expected_index; | |
| 4403 | − int rc; | |
| 4404 | − gfp_t gfp = readahead_gfp_mask(mapping); | |
| 4405 | − | |
| 4406 | − INIT_LIST_HEAD(tmplist); | |
| 4407 | − | |
| 4408 | − page = lru_to_page(page_list); | |
| 4409 | − | |
| 4410 | − /* | |
| 4411 | − * Lock the page and put it in the cache. Since no one else | |
| 4412 | − * should have access to this page, we're safe to simply set | |
| 4413 | − * PG_locked without checking it first. | |
| 4414 | − */ | |
| 4415 | − __SetPageLocked(page); | |
| 4416 | − rc = add_to_page_cache_locked(page, mapping, | |
| 4417 | − page->index, gfp); | |
| 4418 | − | |
| 4419 | − /* give up if we can't stick it in the cache */ | |
| 4420 | − if (rc) { | |
| 4421 | − __ClearPageLocked(page); | |
| 4422 | − return rc; | |
| 4423 | − } | |
| 4424 | − | |
| 4425 | − /* move first page to the tmplist */ | |
| 4426 | − *offset = (loff_t)page->index << PAGE_SHIFT; | |
| 4427 | − *bytes = PAGE_SIZE; | |
| 4428 | − *nr_pages = 1; | |
| 4429 | − list_move_tail(&page->lru, tmplist); | |
| 4430 | − | |
| 4431 | − /* now try and add more pages onto the request */ | |
| 4432 | − expected_index = page->index + 1; | |
| 4433 | − list_for_each_entry_safe_reverse(page, tpage, page_list, lru) { | |
| 4434 | − /* discontinuity ? */ | |
| 4435 | − if (page->index != expected_index) | |
| 4436 | − break; | |
| 4437 | − | |
| 4438 | − /* would this page push the read over the rsize? */ | |
| 4439 | − if (*bytes + PAGE_SIZE > rsize) | |
| 4440 | − break; | |
| 4441 | − | |
| 4442 | − __SetPageLocked(page); | |
| 4443 | − rc = add_to_page_cache_locked(page, mapping, page->index, gfp); | |
| 4444 | − if (rc) { | |
| 4445 | − __ClearPageLocked(page); | |
| 4446 | − break; | |
| 4447 | − } | |
| 4448 | − list_move_tail(&page->lru, tmplist); | |
| 4449 | − (*bytes) += PAGE_SIZE; | |
| 4450 | − expected_index++; | |
| 4451 | − (*nr_pages)++; | |
| 4452 | − } | |
| 4453 | − return rc; | |
| 4454 | −} | |
| 4455 | − | |
| 4456 | −static int cifs_readpages(struct file *file, struct address_space *mapping, | |
| 4457 | − struct list_head *page_list, unsigned num_pages) | |
| 4392 | +static void cifs_readahead(struct readahead_control *ractl) | |
| 4458 | 4393 | { |
| 4459 | 4394 | int rc; |
| 4460 | − int err = 0; | |
| 4461 | − struct list_head tmplist; | |
| 4462 | − struct cifsFileInfo *open_file = file->private_data; | |
| 4463 | − struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); | |
| 4395 | + struct cifsFileInfo *open_file = ractl->file->private_data; | |
| 4396 | + struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(ractl->file); | |
| 4464 | 4397 | struct TCP_Server_Info *server; |
| 4465 | 4398 | pid_t pid; |
| 4466 | − unsigned int xid; | |
| 4399 | + unsigned int xid, nr_pages, last_batch_size = 0, cache_nr_pages = 0; | |
| 4400 | + pgoff_t next_cached = ULONG_MAX; | |
| 4401 | + bool caching = fscache_cookie_enabled(cifs_inode_cookie(ractl->mapping->host)) && | |
| 4402 | + cifs_inode_cookie(ractl->mapping->host)->cache_priv; | |
| 4403 | + bool check_cache = caching; | |
| 4467 | 4404 | |
| 4468 | 4405 | xid = get_xid(); |
| 4469 | − /* | |
| 4470 | − * Reads as many pages as possible from fscache. Returns -ENOBUFS | |
| 4471 | − * immediately if the cookie is negative | |
| 4472 | − * | |
| 4473 | − * After this point, every page in the list might have PG_fscache set, | |
| 4474 | − * so we will need to clean that up off of every page we don't use. | |
| 4475 | − */ | |
| 4476 | − rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list, | |
| 4477 | − &num_pages); | |
| 4478 | − if (rc == 0) { | |
| 4479 | − free_xid(xid); | |
| 4480 | − return rc; | |
| 4481 | − } | |
| 4482 | 4406 | |
| 4483 | 4407 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
| 4484 | 4408 | pid = open_file->pid; |
| @@ -4489,39 +4413,73 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, · 4 unmodified lines | ||
| 4489 | 4413 | server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); |
| 4490 | 4414 | |
| 4491 | 4415 | cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n", |
| 4492 | − __func__, file, mapping, num_pages); | |
| 4416 | + __func__, ractl->file, ractl->mapping, readahead_count(ractl)); | |
| 4493 | 4417 | |
| 4494 | 4418 | /* |
| 4495 | − * Start with the page at end of list and move it to private | |
| 4496 | − * list. Do the same with any following pages until we hit | |
| 4497 | − * the rsize limit, hit an index discontinuity, or run out of | |
| 4498 | − * pages. Issue the async read and then start the loop again | |
| 4499 | − * until the list is empty. | |
| 4500 | − * | |
| 4501 | − * Note that list order is important. The page_list is in | |
| 4502 | − * the order of declining indexes. When we put the pages in | |
| 4503 | − * the rdata->pages, then we want them in increasing order. | |
| 4419 | + * Chop the readahead request up into rsize-sized read requests. | |
| 4504 | 4420 | */ |
| 4505 | − while (!list_empty(page_list) && !err) { | |
| 4506 | − unsigned int i, nr_pages, bytes, rsize; | |
| 4507 | − loff_t offset; | |
| 4508 | − struct page *page, *tpage; | |
| 4421 | + while ((nr_pages = readahead_count(ractl) - last_batch_size)) { | |
| 4422 | + unsigned int i, got, rsize; | |
| 4423 | + struct page *page; | |
| 4509 | 4424 | struct cifs_readdata *rdata; |
| 4510 | 4425 | struct cifs_credits credits_on_stack; |
| 4511 | 4426 | struct cifs_credits *credits = &credits_on_stack; |
| 4427 | + pgoff_t index = readahead_index(ractl) + last_batch_size; | |
| 4428 | + | |
| 4429 | + /* | |
| 4430 | + * Find out if we have anything cached in the range of | |
| 4431 | + * interest, and if so, where the next chunk of cached data is. | |
| 4432 | + */ | |
| 4433 | + if (caching) { | |
| 4434 | + if (check_cache) { | |
| 4435 | + rc = cifs_fscache_query_occupancy( | |
| 4436 | + ractl->mapping->host, index, nr_pages, | |
| 4437 | + &next_cached, &cache_nr_pages); | |
| 4438 | + if (rc < 0) | |
| 4439 | + caching = false; | |
| 4440 | + check_cache = false; | |
| 4441 | + } | |
| 4442 | + | |
| 4443 | + if (index == next_cached) { | |
| 4444 | + /* | |
| 4445 | + * TODO: Send a whole batch of pages to be read | |
| 4446 | + * by the cache. | |
| 4447 | + */ | |
| 4448 | + page = readahead_page(ractl); | |
| 4449 | + last_batch_size = 1 << thp_order(page); | |
| 4450 | + if (cifs_readpage_from_fscache(ractl->mapping->host, | |
| 4451 | + page) < 0) { | |
| 4452 | + /* | |
| 4453 | + * TODO: Deal with cache read failure | |
| 4454 | + * here, but for the moment, delegate | |
| 4455 | + * that to readpage. | |
| 4456 | + */ | |
| 4457 | + caching = false; | |
| 4458 | + } | |
| 4459 | + unlock_page(page); | |
| 4460 | + next_cached++; | |
| 4461 | + cache_nr_pages--; | |
| 4462 | + if (cache_nr_pages == 0) | |
| 4463 | + check_cache = true; | |
| 4464 | + continue; | |
| 4465 | + } | |
| 4466 | + } | |
| 4512 | 4467 | |
| 4513 | 4468 | if (open_file->invalidHandle) { |
| 4514 | 4469 | rc = cifs_reopen_file(open_file, true); |
| 4515 | − if (rc == -EAGAIN) | |
| 4516 | − continue; | |
| 4517 | − else if (rc) | |
| 4470 | + if (rc) { | |
| 4471 | + if (rc == -EAGAIN) | |
| 4472 | + continue; | |
| 4518 | 4473 | break; |
| 4474 | + } | |
| 4519 | 4475 | } |
| 4520 | 4476 | |
| 4521 | 4477 | rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize, |
| 4522 | 4478 | &rsize, credits); |
| 4523 | 4479 | if (rc) |
| 4524 | 4480 | break; |
| 4481 | + nr_pages = min_t(size_t, rsize / PAGE_SIZE, readahead_count(ractl)); | |
| 4482 | + nr_pages = min_t(size_t, nr_pages, next_cached - index); | |
| 4525 | 4483 | |
| 4526 | 4484 | /* |
| 4527 | 4485 | * Give up immediately if rsize is too small to read an entire |
| @@ -4529,16 +4487,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, · 1 unmodified line | ||
| 4529 | 4487 | * reach this point however since we set ra_pages to 0 when the |
| 4530 | 4488 | * rsize is smaller than a cache page. |
| 4531 | 4489 | */ |
| 4532 | − if (unlikely(rsize < PAGE_SIZE)) { | |
| 4533 | − add_credits_and_wake_if(server, credits, 0); | |
| 4534 | − free_xid(xid); | |
| 4535 | − return 0; | |
| 4536 | − } | |
| 4537 | − | |
| 4538 | − nr_pages = 0; | |
| 4539 | − err = readpages_get_pages(mapping, page_list, rsize, &tmplist, | |
| 4540 | − &nr_pages, &offset, &bytes); | |
| 4541 | − if (!nr_pages) { | |
| 4490 | + if (unlikely(!nr_pages)) { | |
| 4542 | 4491 | add_credits_and_wake_if(server, credits, 0); |
| 4543 | 4492 | break; |
| 4544 | 4493 | } |
| @@ -4546,36 +4495,31 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, · 1 unmodified line | ||
| 4546 | 4495 | rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete); |
| 4547 | 4496 | if (!rdata) { |
| 4548 | 4497 | /* best to give up if we're out of mem */ |
| 4549 | − list_for_each_entry_safe(page, tpage, &tmplist, lru) { | |
| 4550 | − list_del(&page->lru); | |
| 4551 | − lru_cache_add(page); | |
| 4552 | − unlock_page(page); | |
| 4553 | − put_page(page); | |
| 4554 | − } | |
| 4555 | − rc = -ENOMEM; | |
| 4556 | 4498 | add_credits_and_wake_if(server, credits, 0); |
| 4557 | 4499 | break; |
| 4558 | 4500 | } |
| 4559 | 4501 | |
| 4560 | − rdata->cfile = cifsFileInfo_get(open_file); | |
| 4561 | − rdata->server = server; | |
| 4562 | − rdata->mapping = mapping; | |
| 4563 | − rdata->offset = offset; | |
| 4564 | − rdata->bytes = bytes; | |
| 4565 | − rdata->pid = pid; | |
| 4566 | − rdata->pagesz = PAGE_SIZE; | |
| 4567 | − rdata->tailsz = PAGE_SIZE; | |
| 4502 | + got = __readahead_batch(ractl, rdata->pages, nr_pages); | |
| 4503 | + if (got != nr_pages) { | |
| 4504 | + pr_warn("__readahead_batch() returned %u/%u\n", | |
| 4505 | + got, nr_pages); | |
| 4506 | + nr_pages = got; | |
| 4507 | + } | |
| 4508 | + | |
| 4509 | + rdata->nr_pages = nr_pages; | |
| 4510 | + rdata->bytes = readahead_batch_length(ractl); | |
| 4511 | + rdata->cfile = cifsFileInfo_get(open_file); | |
| 4512 | + rdata->server = server; | |
| 4513 | + rdata->mapping = ractl->mapping; | |
| 4514 | + rdata->offset = readahead_pos(ractl); | |
| 4515 | + rdata->pid = pid; | |
| 4516 | + rdata->pagesz = PAGE_SIZE; | |
| 4517 | + rdata->tailsz = PAGE_SIZE; | |
| 4568 | 4518 | rdata->read_into_pages = cifs_readpages_read_into_pages; |
| 4569 | 4519 | rdata->copy_into_pages = cifs_readpages_copy_into_pages; |
| 4570 | − rdata->credits = credits_on_stack; | |
| 4571 | − | |
| 4572 | − list_for_each_entry_safe(page, tpage, &tmplist, lru) { | |
| 4573 | − list_del(&page->lru); | |
| 4574 | − rdata->pages[rdata->nr_pages++] = page; | |
| 4575 | − } | |
| 4520 | + rdata->credits = credits_on_stack; | |
| 4576 | 4521 | |
| 4577 | 4522 | rc = adjust_credits(server, &rdata->credits, rdata->bytes); |
| 4578 | − | |
| 4579 | 4523 | if (!rc) { |
| 4580 | 4524 | if (rdata->cfile->invalidHandle) |
| 4581 | 4525 | rc = -EAGAIN; |
| @@ -4587,7 +4531,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, · 5 unmodified lines | ||
| 4587 | 4531 | add_credits_and_wake_if(server, &rdata->credits, 0); |
| 4588 | 4532 | for (i = 0; i < rdata->nr_pages; i++) { |
| 4589 | 4533 | page = rdata->pages[i]; |
| 4590 | − lru_cache_add(page); | |
| 4591 | 4534 | unlock_page(page); |
| 4592 | 4535 | put_page(page); |
| 4593 | 4536 | } |
| @@ -4597,10 +4540,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, · 3 unmodified lines | ||
| 4597 | 4540 | } |
| 4598 | 4541 | |
| 4599 | 4542 | kref_put(&rdata->refcount, cifs_readdata_release); |
| 4543 | + last_batch_size = nr_pages; | |
| 4600 | 4544 | } |
| 4601 | 4545 | |
| 4602 | 4546 | free_xid(xid); |
| 4603 | − return rc; | |
| 4604 | 4547 | } |
| 4605 | 4548 | |
| 4606 | 4549 | /* |
| @@ -4924,7 +4867,7 @@ oplock_break_done: · 317 unmodified lines | ||
| 4924 | 4867 | * In the non-cached mode (mount with cache=none), we shunt off direct read and write requests |
| 4925 | 4868 | * so this method should never be called. |
| 4926 | 4869 | * |
| 4927 | − * Direct IO is not yet supported in the cached mode. | |
| 4870 | + * Direct IO is not yet supported in the cached mode. | |
| 4928 | 4871 | */ |
| 4929 | 4872 | static ssize_t |
| 4930 | 4873 | cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter) |
| @@ -5006,7 +4949,7 @@ static int cifs_set_page_dirty(struct page *page) · 75 unmodified lines | ||
| 5006 | 4949 | |
| 5007 | 4950 | const struct address_space_operations cifs_addr_ops = { |
| 5008 | 4951 | .readpage = cifs_readpage, |
| 5009 | − .readpages = cifs_readpages, | |
| 4952 | + .readahead = cifs_readahead, | |
| 5010 | 4953 | .writepage = cifs_writepage, |
| 5011 | 4954 | .writepages = cifs_writepages, |
| 5012 | 4955 | .write_begin = cifs_write_begin, |
| @@ -134,37 +134,127 @@ void cifs_fscache_release_inode_cookie(struct inode *inode) · 133 unmodified lines | ||
| 134 | 134 | } |
| 135 | 135 | } |
| 136 | 136 | |
| 137 | +static inline void fscache_end_operation(struct netfs_cache_resources *cres) | |
| 138 | +{ | |
| 139 | + const struct netfs_cache_ops *ops = fscache_operation_valid(cres); | |
| 140 | + | |
| 141 | + if (ops) | |
| 142 | + ops->end_operation(cres); | |
| 143 | +} | |
| 144 | + | |
| 137 | 145 | /* |
| 138 | − * Retrieve a page from FS-Cache | |
| 146 | + * Fallback page reading interface. | |
| 139 | 147 | */ |
| 140 | −int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) | |
| 148 | +static int fscache_fallback_read_page(struct inode *inode, struct page *page) | |
| 141 | 149 | { |
| 142 | − cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n", | |
| 143 | − __func__, CIFS_I(inode)->fscache, page, inode); | |
| 144 | − return -ENOBUFS; // Needs conversion to using netfslib | |
| 150 | + struct netfs_cache_resources cres; | |
| 151 | + struct fscache_cookie *cookie = cifs_inode_cookie(inode); | |
| 152 | + struct iov_iter iter; | |
| 153 | + struct bio_vec bvec[1]; | |
| 154 | + int ret; | |
| 155 | + | |
| 156 | + memset(&cres, 0, sizeof(cres)); | |
| 157 | + bvec[0].bv_page = page; | |
| 158 | + bvec[0].bv_offset = 0; | |
| 159 | + bvec[0].bv_len = PAGE_SIZE; | |
| 160 | + iov_iter_bvec(&iter, READ, bvec, ARRAY_SIZE(bvec), PAGE_SIZE); | |
| 161 | + | |
| 162 | + ret = fscache_begin_read_operation(&cres, cookie); | |
| 163 | + if (ret < 0) | |
| 164 | + return ret; | |
| 165 | + | |
| 166 | + ret = fscache_read(&cres, page_offset(page), &iter, NETFS_READ_HOLE_FAIL, | |
| 167 | + NULL, NULL); | |
| 168 | + fscache_end_operation(&cres); | |
| 169 | + return ret; | |
| 145 | 170 | } |
| 146 | 171 | |
| 147 | 172 | /* |
| 148 | − * Retrieve a set of pages from FS-Cache | |
| 173 | + * Fallback page writing interface. | |
| 149 | 174 | */ |
| 150 | −int __cifs_readpages_from_fscache(struct inode *inode, | |
| 151 | − struct address_space *mapping, | |
| 152 | − struct list_head *pages, | |
| 153 | − unsigned *nr_pages) | |
| 175 | +static int fscache_fallback_write_page(struct inode *inode, struct page *page, | |
| 176 | + bool no_space_allocated_yet) | |
| 154 | 177 | { |
| 155 | − cifs_dbg(FYI, "%s: (0x%p/%u/0x%p)\n", | |
| 156 | − __func__, CIFS_I(inode)->fscache, *nr_pages, inode); | |
| 157 | − return -ENOBUFS; // Needs conversion to using netfslib | |
| 178 | + struct netfs_cache_resources cres; | |
| 179 | + struct fscache_cookie *cookie = cifs_inode_cookie(inode); | |
| 180 | + struct iov_iter iter; | |
| 181 | + struct bio_vec bvec[1]; | |
| 182 | + loff_t start = page_offset(page); | |
| 183 | + size_t len = PAGE_SIZE; | |
| 184 | + int ret; | |
| 185 | + | |
| 186 | + memset(&cres, 0, sizeof(cres)); | |
| 187 | + bvec[0].bv_page = page; | |
| 188 | + bvec[0].bv_offset = 0; | |
| 189 | + bvec[0].bv_len = PAGE_SIZE; | |
| 190 | + iov_iter_bvec(&iter, WRITE, bvec, ARRAY_SIZE(bvec), PAGE_SIZE); | |
| 191 | + | |
| 192 | + ret = fscache_begin_write_operation(&cres, cookie); | |
| 193 | + if (ret < 0) | |
| 194 | + return ret; | |
| 195 | + | |
| 196 | + ret = cres.ops->prepare_write(&cres, &start, &len, i_size_read(inode), | |
| 197 | + no_space_allocated_yet); | |
| 198 | + if (ret == 0) | |
| 199 | + ret = fscache_write(&cres, page_offset(page), &iter, NULL, NULL); | |
| 200 | + fscache_end_operation(&cres); | |
| 201 | + return ret; | |
| 158 | 202 | } |
| 159 | 203 | |
| 160 | −void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) | |
| 204 | +/* | |
| 205 | + * Retrieve a page from FS-Cache | |
| 206 | + */ | |
| 207 | +int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) | |
| 161 | 208 | { |
| 162 | − struct cifsInodeInfo *cifsi = CIFS_I(inode); | |
| 209 | + int ret; | |
| 163 | 210 | |
| 164 | − WARN_ON(!cifsi->fscache); | |
| 211 | + cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n", | |
| 212 | + __func__, cifs_inode_cookie(inode), page, inode); | |
| 165 | 213 | |
| 214 | + ret = fscache_fallback_read_page(inode, page); | |
| 215 | + if (ret < 0) | |
| 216 | + return ret; | |
| 217 | + | |
| 218 | + /* Read completed synchronously */ | |
| 219 | + SetPageUptodate(page); | |
| 220 | + return 0; | |
| 221 | +} | |
| 222 | + | |
| 223 | +void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) | |
| 224 | +{ | |
| 166 | 225 | cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n", |
| 167 | − __func__, cifsi->fscache, page, inode); | |
| 226 | + __func__, cifs_inode_cookie(inode), page, inode); | |
| 227 | + | |
| 228 | + fscache_fallback_write_page(inode, page, true); | |
| 229 | +} | |
| 230 | + | |
| 231 | +/* | |
| 232 | + * Query the cache occupancy. | |
| 233 | + */ | |
| 234 | +int __cifs_fscache_query_occupancy(struct inode *inode, | |
| 235 | + pgoff_t first, unsigned int nr_pages, | |
| 236 | + pgoff_t *_data_first, | |
| 237 | + unsigned int *_data_nr_pages) | |
| 238 | +{ | |
| 239 | + struct netfs_cache_resources cres; | |
| 240 | + struct fscache_cookie *cookie = cifs_inode_cookie(inode); | |
| 241 | + loff_t start, data_start; | |
| 242 | + size_t len, data_len; | |
| 243 | + int ret; | |
| 168 | 244 | |
| 169 | − // Needs conversion to using netfslib | |
| 245 | + ret = fscache_begin_read_operation(&cres, cookie); | |
| 246 | + if (ret < 0) | |
| 247 | + return ret; | |
| 248 | + | |
| 249 | + start = first * PAGE_SIZE; | |
| 250 | + len = nr_pages * PAGE_SIZE; | |
| 251 | + ret = cres.ops->query_occupancy(&cres, start, len, PAGE_SIZE, | |
| 252 | + &data_start, &data_len); | |
| 253 | + if (ret == 0) { | |
| 254 | + *_data_first = data_start / PAGE_SIZE; | |
| 255 | + *_data_nr_pages = len / PAGE_SIZE; | |
| 256 | + } | |
| 257 | + | |
| 258 | + fscache_end_operation(&cres); | |
| 259 | + return ret; | |
| 170 | 260 | } |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #ifndef _CIFS_FSCACHE_H |
| 10 | 10 | #define _CIFS_FSCACHE_H |
| 11 | 11 | |
| 12 | +#include <linux/swap.h> | |
| 12 | 13 | #include <linux/fscache.h> |
| 13 | 14 | |
| 14 | 15 | #include "cifsglob.h" |
| @@ -58,14 +59,6 @@ void cifs_fscache_fill_coherency(struct inode *inode, · 43 unmodified lines | ||
| 58 | 59 | } |
| 59 | 60 | |
| 60 | 61 | |
| 61 | −extern int cifs_fscache_release_page(struct page *page, gfp_t gfp); | |
| 62 | −extern int __cifs_readpage_from_fscache(struct inode *, struct page *); | |
| 63 | −extern int __cifs_readpages_from_fscache(struct inode *, | |
| 64 | − struct address_space *, | |
| 65 | − struct list_head *, | |
| 66 | − unsigned *); | |
| 67 | −extern void __cifs_readpage_to_fscache(struct inode *, struct page *); | |
| 68 | − | |
| 69 | 62 | static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) |
| 70 | 63 | { |
| 71 | 64 | return CIFS_I(inode)->fscache; |
| @@ -80,33 +73,52 @@ static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags · 8 unmodified lines | ||
| 80 | 73 | i_size_read(inode), flags); |
| 81 | 74 | } |
| 82 | 75 | |
| 83 | −static inline int cifs_readpage_from_fscache(struct inode *inode, | |
| 84 | − struct page *page) | |
| 85 | −{ | |
| 86 | − if (CIFS_I(inode)->fscache) | |
| 87 | − return __cifs_readpage_from_fscache(inode, page); | |
| 76 | +extern int __cifs_fscache_query_occupancy(struct inode *inode, | |
| 77 | + pgoff_t first, unsigned int nr_pages, | |
| 78 | + pgoff_t *_data_first, | |
| 79 | + unsigned int *_data_nr_pages); | |
| 88 | 80 | |
| 89 | − return -ENOBUFS; | |
| 81 | +static inline int cifs_fscache_query_occupancy(struct inode *inode, | |
| 82 | + pgoff_t first, unsigned int nr_pages, | |
| 83 | + pgoff_t *_data_first, | |
| 84 | + unsigned int *_data_nr_pages) | |
| 85 | +{ | |
| 86 | + if (!cifs_inode_cookie(inode)) | |
| 87 | + return -ENOBUFS; | |
| 88 | + return __cifs_fscache_query_occupancy(inode, first, nr_pages, | |
| 89 | + _data_first, _data_nr_pages); | |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | −static inline int cifs_readpages_from_fscache(struct inode *inode, | |
| 93 | − struct address_space *mapping, | |
| 94 | − struct list_head *pages, | |
| 95 | − unsigned *nr_pages) | |
| 92 | +extern int __cifs_readpage_from_fscache(struct inode *pinode, struct page *ppage); | |
| 93 | +extern void __cifs_readpage_to_fscache(struct inode *pinode, struct page *ppage); | |
| 94 | + | |
| 95 | + | |
| 96 | +static inline int cifs_readpage_from_fscache(struct inode *inode, | |
| 97 | + struct page *page) | |
| 96 | 98 | { |
| 97 | − if (CIFS_I(inode)->fscache) | |
| 98 | − return __cifs_readpages_from_fscache(inode, mapping, pages, | |
| 99 | − nr_pages); | |
| 99 | + if (cifs_inode_cookie(inode)) | |
| 100 | + return __cifs_readpage_from_fscache(inode, page); | |
| 100 | 101 | return -ENOBUFS; |
| 101 | 102 | } |
| 102 | 103 | |
| 103 | 104 | static inline void cifs_readpage_to_fscache(struct inode *inode, |
| 104 | 105 | struct page *page) |
| 105 | 106 | { |
| 106 | − if (PageFsCache(page)) | |
| 107 | + if (cifs_inode_cookie(inode)) | |
| 107 | 108 | __cifs_readpage_to_fscache(inode, page); |
| 108 | 109 | } |
| 109 | 110 | |
| 111 | +static inline int cifs_fscache_release_page(struct page *page, gfp_t gfp) | |
| 112 | +{ | |
| 113 | + if (PageFsCache(page)) { | |
| 114 | + if (current_is_kswapd() || !(gfp & __GFP_FS)) | |
| 115 | + return false; | |
| 116 | + wait_on_page_fscache(page); | |
| 117 | + fscache_note_page_release(cifs_inode_cookie(page->mapping->host)); | |
| 118 | + } | |
| 119 | + return true; | |
| 120 | +} | |
| 121 | + | |
| 110 | 122 | #else /* CONFIG_CIFS_FSCACHE */ |
| 111 | 123 | static inline |
| 112 | 124 | void cifs_fscache_fill_coherency(struct inode *inode, |
| @@ -123,22 +135,29 @@ static inline void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool upd · 10 unmodified lines | ||
| 123 | 135 | static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { return NULL; } |
| 124 | 136 | static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {} |
| 125 | 137 | |
| 126 | −static inline int | |
| 127 | −cifs_readpage_from_fscache(struct inode *inode, struct page *page) | |
| 138 | +static inline int cifs_fscache_query_occupancy(struct inode *inode, | |
| 139 | + pgoff_t first, unsigned int nr_pages, | |
| 140 | + pgoff_t *_data_first, | |
| 141 | + unsigned int *_data_nr_pages) | |
| 128 | 142 | { |
| 143 | + *_data_first = ULONG_MAX; | |
| 144 | + *_data_nr_pages = 0; | |
| 129 | 145 | return -ENOBUFS; |
| 130 | 146 | } |
| 131 | 147 | |
| 132 | −static inline int cifs_readpages_from_fscache(struct inode *inode, | |
| 133 | − struct address_space *mapping, | |
| 134 | − struct list_head *pages, | |
| 135 | − unsigned *nr_pages) | |
| 148 | +static inline int | |
| 149 | +cifs_readpage_from_fscache(struct inode *inode, struct page *page) | |
| 136 | 150 | { |
| 137 | 151 | return -ENOBUFS; |
| 138 | 152 | } |
| 139 | 153 | |
| 140 | −static inline void cifs_readpage_to_fscache(struct inode *inode, | |
| 141 | − struct page *page) {} | |
| 154 | +static inline | |
| 155 | +void cifs_readpage_to_fscache(struct inode *inode, struct page *page) {} | |
| 156 | + | |
| 157 | +static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp) | |
| 158 | +{ | |
| 159 | + return true; /* May release page */ | |
| 160 | +} | |
| 142 | 161 | |
| 143 | 162 | #endif /* CONFIG_CIFS_FSCACHE */ |
| 144 | 163 | |
| @@ -83,6 +83,7 @@ static void cifs_set_ops(struct inode *inode) · 82 unmodified lines | ||
| 83 | 83 | static void |
| 84 | 84 | cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) |
| 85 | 85 | { |
| 86 | + struct cifs_fscache_inode_coherency_data cd; | |
| 86 | 87 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
| 87 | 88 | |
| 88 | 89 | cifs_dbg(FYI, "%s: revalidating inode %llu\n", |
| @@ -113,6 +114,9 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) · 24 unmodified lines | ||
| 113 | 114 | cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n", |
| 114 | 115 | __func__, cifs_i->uniqueid); |
| 115 | 116 | set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags); |
| 117 | + /* Invalidate fscache cookie */ | |
| 118 | + cifs_fscache_fill_coherency(&cifs_i->vfs_inode, &cd); | |
| 119 | + fscache_invalidate(cifs_inode_cookie(inode), &cd, i_size_read(inode), 0); | |
| 116 | 120 | } |
| 117 | 121 | |
| 118 | 122 | /* |
| @@ -2261,8 +2265,6 @@ cifs_dentry_needs_reval(struct dentry *dentry) · 2142 unmodified lines | ||
| 2261 | 2265 | int |
| 2262 | 2266 | cifs_invalidate_mapping(struct inode *inode) |
| 2263 | 2267 | { |
| 2264 | − struct cifs_fscache_inode_coherency_data cd; | |
| 2265 | − struct cifsInodeInfo *cifsi = CIFS_I(inode); | |
| 2266 | 2268 | int rc = 0; |
| 2267 | 2269 | |
| 2268 | 2270 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { |
| @@ -2272,8 +2274,6 @@ cifs_invalidate_mapping(struct inode *inode) · 3 unmodified lines | ||
| 2272 | 2274 | __func__, inode); |
| 2273 | 2275 | } |
| 2274 | 2276 | |
| 2275 | − cifs_fscache_fill_coherency(&cifsi->vfs_inode, &cd); | |
| 2276 | − fscache_invalidate(cifs_inode_cookie(inode), &cd, i_size_read(inode), 0); | |
| 2277 | 2277 | return rc; |
| 2278 | 2278 | } |
| 2279 | 2279 | |
| @@ -713,7 +713,11 @@ static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size) · 712 unmodified lines | ||
| 713 | 713 | else |
| 714 | 714 | sz += sizeof(__le16); |
| 715 | 715 | |
| 716 | − sz += sizeof(__le16) * strnlen(ses->workstation_name, CIFS_MAX_WORKSTATION_LEN); | |
| 716 | + if (ses->workstation_name) | |
| 717 | + sz += sizeof(__le16) * strnlen(ses->workstation_name, | |
| 718 | + CIFS_MAX_WORKSTATION_LEN); | |
| 719 | + else | |
| 720 | + sz += sizeof(__le16); | |
| 717 | 721 | |
| 718 | 722 | return sz; |
| 719 | 723 | } |
| @@ -252,12 +252,10 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, · 251 unmodified lines | ||
| 252 | 252 | return ret; |
| 253 | 253 | |
| 254 | 254 | iomap->offset = map.m_la; |
| 255 | − if (flags & IOMAP_DAX) { | |
| 255 | + if (flags & IOMAP_DAX) | |
| 256 | 256 | iomap->dax_dev = mdev.m_daxdev; |
| 257 | − iomap->offset += mdev.m_dax_part_off; | |
| 258 | − } else { | |
| 257 | + else | |
| 259 | 258 | iomap->bdev = mdev.m_bdev; |
| 260 | − } | |
| 261 | 259 | iomap->length = map.m_llen; |
| 262 | 260 | iomap->flags = 0; |
| 263 | 261 | iomap->private = NULL; |
| @@ -284,6 +282,8 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, · 20 unmodified lines | ||
| 284 | 282 | } else { |
| 285 | 283 | iomap->type = IOMAP_MAPPED; |
| 286 | 284 | iomap->addr = mdev.m_pa; |
| 285 | + if (flags & IOMAP_DAX) | |
| 286 | + iomap->addr += mdev.m_dax_part_off; | |
| 287 | 287 | } |
| 288 | 288 | return 0; |
| 289 | 289 | } |
| @@ -810,68 +810,11 @@ static bool z_erofs_get_sync_decompress_policy(struct erofs_sb_info *sbi, · 809 unmodified lines | ||
| 810 | 810 | return false; |
| 811 | 811 | } |
| 812 | 812 | |
| 813 | −static void z_erofs_decompressqueue_work(struct work_struct *work); | |
| 814 | −static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, | |
| 815 | − bool sync, int bios) | |
| 816 | −{ | |
| 817 | − struct erofs_sb_info *const sbi = EROFS_SB(io->sb); | |
| 818 | − | |
| 819 | − /* wake up the caller thread for sync decompression */ | |
| 820 | − if (sync) { | |
| 821 | − unsigned long flags; | |
| 822 | − | |
| 823 | − spin_lock_irqsave(&io->u.wait.lock, flags); | |
| 824 | − if (!atomic_add_return(bios, &io->pending_bios)) | |
| 825 | − wake_up_locked(&io->u.wait); | |
| 826 | − spin_unlock_irqrestore(&io->u.wait.lock, flags); | |
| 827 | − return; | |
| 828 | − } | |
| 829 | − | |
| 830 | − if (atomic_add_return(bios, &io->pending_bios)) | |
| 831 | − return; | |
| 832 | − /* Use workqueue and sync decompression for atomic contexts only */ | |
| 833 | − if (in_atomic() || irqs_disabled()) { | |
| 834 | − queue_work(z_erofs_workqueue, &io->u.work); | |
| 835 | − /* enable sync decompression for readahead */ | |
| 836 | − if (sbi->opt.sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO) | |
| 837 | − sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON; | |
| 838 | − return; | |
| 839 | − } | |
| 840 | − z_erofs_decompressqueue_work(&io->u.work); | |
| 841 | −} | |
| 842 | − | |
| 843 | 813 | static bool z_erofs_page_is_invalidated(struct page *page) |
| 844 | 814 | { |
| 845 | 815 | return !page->mapping && !z_erofs_is_shortlived_page(page); |
| 846 | 816 | } |
| 847 | 817 | |
| 848 | −static void z_erofs_decompressqueue_endio(struct bio *bio) | |
| 849 | −{ | |
| 850 | − tagptr1_t t = tagptr_init(tagptr1_t, bio->bi_private); | |
| 851 | − struct z_erofs_decompressqueue *q = tagptr_unfold_ptr(t); | |
| 852 | − blk_status_t err = bio->bi_status; | |
| 853 | − struct bio_vec *bvec; | |
| 854 | − struct bvec_iter_all iter_all; | |
| 855 | − | |
| 856 | − bio_for_each_segment_all(bvec, bio, iter_all) { | |
| 857 | − struct page *page = bvec->bv_page; | |
| 858 | − | |
| 859 | − DBG_BUGON(PageUptodate(page)); | |
| 860 | − DBG_BUGON(z_erofs_page_is_invalidated(page)); | |
| 861 | − | |
| 862 | − if (err) | |
| 863 | − SetPageError(page); | |
| 864 | − | |
| 865 | − if (erofs_page_is_managed(EROFS_SB(q->sb), page)) { | |
| 866 | − if (!err) | |
| 867 | − SetPageUptodate(page); | |
| 868 | − unlock_page(page); | |
| 869 | − } | |
| 870 | − } | |
| 871 | − z_erofs_decompress_kickoff(q, tagptr_unfold_tags(t), -1); | |
| 872 | − bio_put(bio); | |
| 873 | −} | |
| 874 | − | |
| 875 | 818 | static int z_erofs_decompress_pcluster(struct super_block *sb, |
| 876 | 819 | struct z_erofs_pcluster *pcl, |
| 877 | 820 | struct page **pagepool) |
| @@ -1123,6 +1066,35 @@ static void z_erofs_decompressqueue_work(struct work_struct *work) · 245 unmodified lines | ||
| 1123 | 1066 | kvfree(bgq); |
| 1124 | 1067 | } |
| 1125 | 1068 | |
| 1069 | +static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, | |
| 1070 | + bool sync, int bios) | |
| 1071 | +{ | |
| 1072 | + struct erofs_sb_info *const sbi = EROFS_SB(io->sb); | |
| 1073 | + | |
| 1074 | + /* wake up the caller thread for sync decompression */ | |
| 1075 | + if (sync) { | |
| 1076 | + unsigned long flags; | |
| 1077 | + | |
| 1078 | + spin_lock_irqsave(&io->u.wait.lock, flags); | |
| 1079 | + if (!atomic_add_return(bios, &io->pending_bios)) | |
| 1080 | + wake_up_locked(&io->u.wait); | |
| 1081 | + spin_unlock_irqrestore(&io->u.wait.lock, flags); | |
| 1082 | + return; | |
| 1083 | + } | |
| 1084 | + | |
| 1085 | + if (atomic_add_return(bios, &io->pending_bios)) | |
| 1086 | + return; | |
| 1087 | + /* Use workqueue and sync decompression for atomic contexts only */ | |
| 1088 | + if (in_atomic() || irqs_disabled()) { | |
| 1089 | + queue_work(z_erofs_workqueue, &io->u.work); | |
| 1090 | + /* enable sync decompression for readahead */ | |
| 1091 | + if (sbi->opt.sync_decompress == EROFS_SYNC_DECOMPRESS_AUTO) | |
| 1092 | + sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_FORCE_ON; | |
| 1093 | + return; | |
| 1094 | + } | |
| 1095 | + z_erofs_decompressqueue_work(&io->u.work); | |
| 1096 | +} | |
| 1097 | + | |
| 1126 | 1098 | static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, |
| 1127 | 1099 | unsigned int nr, |
| 1128 | 1100 | struct page **pagepool, |
| @@ -1300,6 +1272,33 @@ static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, · 171 unmodified lines | ||
| 1300 | 1272 | qtail[JQ_BYPASS] = &pcl->next; |
| 1301 | 1273 | } |
| 1302 | 1274 | |
| 1275 | +static void z_erofs_decompressqueue_endio(struct bio *bio) | |
| 1276 | +{ | |
| 1277 | + tagptr1_t t = tagptr_init(tagptr1_t, bio->bi_private); | |
| 1278 | + struct z_erofs_decompressqueue *q = tagptr_unfold_ptr(t); | |
| 1279 | + blk_status_t err = bio->bi_status; | |
| 1280 | + struct bio_vec *bvec; | |
| 1281 | + struct bvec_iter_all iter_all; | |
| 1282 | + | |
| 1283 | + bio_for_each_segment_all(bvec, bio, iter_all) { | |
| 1284 | + struct page *page = bvec->bv_page; | |
| 1285 | + | |
| 1286 | + DBG_BUGON(PageUptodate(page)); | |
| 1287 | + DBG_BUGON(z_erofs_page_is_invalidated(page)); | |
| 1288 | + | |
| 1289 | + if (err) | |
| 1290 | + SetPageError(page); | |
| 1291 | + | |
| 1292 | + if (erofs_page_is_managed(EROFS_SB(q->sb), page)) { | |
| 1293 | + if (!err) | |
| 1294 | + SetPageUptodate(page); | |
| 1295 | + unlock_page(page); | |
| 1296 | + } | |
| 1297 | + } | |
| 1298 | + z_erofs_decompress_kickoff(q, tagptr_unfold_tags(t), -1); | |
| 1299 | + bio_put(bio); | |
| 1300 | +} | |
| 1301 | + | |
| 1303 | 1302 | static void z_erofs_submit_queue(struct super_block *sb, |
| 1304 | 1303 | struct z_erofs_decompress_frontend *f, |
| 1305 | 1304 | struct page **pagepool, |
| @@ -630,6 +630,13 @@ static int z_erofs_do_map_blocks(struct inode *inode, · 629 unmodified lines | ||
| 630 | 630 | if (endoff >= m.clusterofs) { |
| 631 | 631 | m.headtype = m.type; |
| 632 | 632 | map->m_la = (m.lcn << lclusterbits) | m.clusterofs; |
| 633 | + /* | |
| 634 | + * For ztailpacking files, in order to inline data more | |
| 635 | + * effectively, special EOF lclusters are now supported | |
| 636 | + * which can have three parts at most. | |
| 637 | + */ | |
| 638 | + if (ztailpacking && end > inode->i_size) | |
| 639 | + end = inode->i_size; | |
| 633 | 640 | break; |
| 634 | 641 | } |
| 635 | 642 | /* m.lcn should be >= 1 if endoff < m.clusterofs */ |
| @@ -139,7 +139,7 @@ fail: · 138 unmodified lines | ||
| 139 | 139 | /* |
| 140 | 140 | * Inode operation get_posix_acl(). |
| 141 | 141 | * |
| 142 | − * inode->i_mutex: don't care | |
| 142 | + * inode->i_rwsem: don't care | |
| 143 | 143 | */ |
| 144 | 144 | struct posix_acl * |
| 145 | 145 | ext4_get_acl(struct inode *inode, int type, bool rcu) |
| @@ -183,7 +183,7 @@ ext4_get_acl(struct inode *inode, int type, bool rcu) · 37 unmodified lines | ||
| 183 | 183 | /* |
| 184 | 184 | * Set the access or default ACL of an inode. |
| 185 | 185 | * |
| 186 | − * inode->i_mutex: down unless called from ext4_new_inode | |
| 186 | + * inode->i_rwsem: down unless called from ext4_new_inode | |
| 187 | 187 | */ |
| 188 | 188 | static int |
| 189 | 189 | __ext4_set_acl(handle_t *handle, struct inode *inode, int type, |
| @@ -271,8 +271,8 @@ out_stop: · 81 unmodified lines | ||
| 271 | 271 | /* |
| 272 | 272 | * Initialize the ACLs of a new inode. Called from ext4_new_inode. |
| 273 | 273 | * |
| 274 | − * dir->i_mutex: down | |
| 275 | − * inode->i_mutex: up (access to inode is still exclusive) | |
| 274 | + * dir->i_rwsem: down | |
| 275 | + * inode->i_rwsem: up (access to inode is still exclusive) | |
| 276 | 276 | */ |
| 277 | 277 | int |
| 278 | 278 | ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) |
| @@ -1028,7 +1028,7 @@ struct ext4_inode_info { · 1027 unmodified lines | ||
| 1028 | 1028 | |
| 1029 | 1029 | /* |
| 1030 | 1030 | * Extended attributes can be read independently of the main file |
| 1031 | − * data. Taking i_mutex even when reading would cause contention | |
| 1031 | + * data. Taking i_rwsem even when reading would cause contention | |
| 1032 | 1032 | * between readers of EAs and writers of regular file data, so |
| 1033 | 1033 | * instead we synchronize on xattr_sem when reading or changing |
| 1034 | 1034 | * EAs. |
| @@ -1750,6 +1750,7 @@ struct ext4_sb_info { · 715 unmodified lines | ||
| 1750 | 1750 | spinlock_t s_fc_lock; |
| 1751 | 1751 | struct buffer_head *s_fc_bh; |
| 1752 | 1752 | struct ext4_fc_stats s_fc_stats; |
| 1753 | + tid_t s_fc_ineligible_tid; | |
| 1753 | 1754 | #ifdef CONFIG_EXT4_DEBUG |
| 1754 | 1755 | int s_fc_debug_max_replay; |
| 1755 | 1756 | #endif |
| @@ -1795,10 +1796,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) · 39 unmodified lines | ||
| 1795 | 1796 | enum { |
| 1796 | 1797 | EXT4_MF_MNTDIR_SAMPLED, |
| 1797 | 1798 | EXT4_MF_FS_ABORTED, /* Fatal error detected */ |
| 1798 | − EXT4_MF_FC_INELIGIBLE, /* Fast commit ineligible */ | |
| 1799 | − EXT4_MF_FC_COMMITTING /* File system underoing a fast | |
| 1800 | − * commit. | |
| 1801 | − */ | |
| 1799 | + EXT4_MF_FC_INELIGIBLE /* Fast commit ineligible */ | |
| 1802 | 1800 | }; |
| 1803 | 1801 | |
| 1804 | 1802 | static inline void ext4_set_mount_flag(struct super_block *sb, int bit) |
| @@ -2926,7 +2924,7 @@ void __ext4_fc_track_create(handle_t *handle, struct inode *inode, · 1121 unmodified lines | ||
| 2926 | 2924 | struct dentry *dentry); |
| 2927 | 2925 | void ext4_fc_track_create(handle_t *handle, struct dentry *dentry); |
| 2928 | 2926 | void ext4_fc_track_inode(handle_t *handle, struct inode *inode); |
| 2929 | −void ext4_fc_mark_ineligible(struct super_block *sb, int reason); | |
| 2927 | +void ext4_fc_mark_ineligible(struct super_block *sb, int reason, handle_t *handle); | |
| 2930 | 2928 | void ext4_fc_start_update(struct inode *inode); |
| 2931 | 2929 | void ext4_fc_stop_update(struct inode *inode); |
| 2932 | 2930 | void ext4_fc_del(struct inode *inode); |
| @@ -2935,6 +2933,9 @@ void ext4_fc_replay_cleanup(struct super_block *sb); · 2 unmodified lines | ||
| 2935 | 2933 | int ext4_fc_commit(journal_t *journal, tid_t commit_tid); |
| 2936 | 2934 | int __init ext4_fc_init_dentry_cache(void); |
| 2937 | 2935 | void ext4_fc_destroy_dentry_cache(void); |
| 2936 | +int ext4_fc_record_regions(struct super_block *sb, int ino, | |
| 2937 | + ext4_lblk_t lblk, ext4_fsblk_t pblk, | |
| 2938 | + int len, int replay); | |
| 2938 | 2939 | |
| 2939 | 2940 | /* mballoc.c */ |
| 2940 | 2941 | extern const struct seq_operations ext4_mb_seq_groups_ops; |
| @@ -3407,7 +3408,7 @@ do { \ · 466 unmodified lines | ||
| 3407 | 3408 | #define EXT4_FREECLUSTERS_WATERMARK 0 |
| 3408 | 3409 | #endif |
| 3409 | 3410 | |
| 3410 | −/* Update i_disksize. Requires i_mutex to avoid races with truncate */ | |
| 3411 | +/* Update i_disksize. Requires i_rwsem to avoid races with truncate */ | |
| 3411 | 3412 | static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize) |
| 3412 | 3413 | { |
| 3413 | 3414 | WARN_ON_ONCE(S_ISREG(inode->i_mode) && |
| @@ -3418,7 +3419,7 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize) · 4 unmodified lines | ||
| 3418 | 3419 | up_write(&EXT4_I(inode)->i_data_sem); |
| 3419 | 3420 | } |
| 3420 | 3421 | |
| 3421 | −/* Update i_size, i_disksize. Requires i_mutex to avoid races with truncate */ | |
| 3422 | +/* Update i_size, i_disksize. Requires i_rwsem to avoid races with truncate */ | |
| 3422 | 3423 | static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize) |
| 3423 | 3424 | { |
| 3424 | 3425 | int changed = 0; |
| @@ -491,7 +491,7 @@ static inline int ext4_free_data_revoke_credits(struct inode *inode, int blocks) · 490 unmodified lines | ||
| 491 | 491 | /* |
| 492 | 492 | * This function controls whether or not we should try to go down the |
| 493 | 493 | * dioread_nolock code paths, which makes it safe to avoid taking |
| 494 | − * i_mutex for direct I/O reads. This only works for extent-based | |
| 494 | + * i_rwsem for direct I/O reads. This only works for extent-based | |
| 495 | 495 | * files, and it doesn't work if data journaling is enabled, since the |
| 496 | 496 | * dioread_nolock code uses b_private to pass information back to the |
| 497 | 497 | * I/O completion handler, and this conflicts with the jbd's use of |
| @@ -97,7 +97,7 @@ static int ext4_ext_trunc_restart_fn(struct inode *inode, int *dropped) · 96 unmodified lines | ||
| 97 | 97 | * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this |
| 98 | 98 | * moment, get_block can be called only for blocks inside i_size since |
| 99 | 99 | * page cache has been already dropped and writes are blocked by |
| 100 | − * i_mutex. So we can safely drop the i_data_sem here. | |
| 100 | + * i_rwsem. So we can safely drop the i_data_sem here. | |
| 101 | 101 | */ |
| 102 | 102 | BUG_ON(EXT4_JOURNAL(inode) == NULL); |
| 103 | 103 | ext4_discard_preallocations(inode, 0); |
| @@ -4572,7 +4572,7 @@ static long ext4_zero_range(struct file *file, loff_t offset, · 4468 unmodified lines | ||
| 4572 | 4572 | |
| 4573 | 4573 | flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT; |
| 4574 | 4574 | |
| 4575 | − /* Wait all existing dio workers, newcomers will block on i_mutex */ | |
| 4575 | + /* Wait all existing dio workers, newcomers will block on i_rwsem */ | |
| 4576 | 4576 | inode_dio_wait(inode); |
| 4577 | 4577 | |
| 4578 | 4578 | /* Preallocate the range including the unaligned edges */ |
| @@ -4738,7 +4738,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) · 159 unmodified lines | ||
| 4738 | 4738 | goto out; |
| 4739 | 4739 | } |
| 4740 | 4740 | |
| 4741 | − /* Wait all existing dio workers, newcomers will block on i_mutex */ | |
| 4741 | + /* Wait all existing dio workers, newcomers will block on i_rwsem */ | |
| 4742 | 4742 | inode_dio_wait(inode); |
| 4743 | 4743 | |
| 4744 | 4744 | ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, flags); |
| @@ -5334,7 +5334,7 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) · 589 unmodified lines | ||
| 5334 | 5334 | ret = PTR_ERR(handle); |
| 5335 | 5335 | goto out_mmap; |
| 5336 | 5336 | } |
| 5337 | − ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE); | |
| 5337 | + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE, handle); | |
| 5338 | 5338 | |
| 5339 | 5339 | down_write(&EXT4_I(inode)->i_data_sem); |
| 5340 | 5340 | ext4_discard_preallocations(inode, 0); |
| @@ -5474,7 +5474,7 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) · 133 unmodified lines | ||
| 5474 | 5474 | ret = PTR_ERR(handle); |
| 5475 | 5475 | goto out_mmap; |
| 5476 | 5476 | } |
| 5477 | − ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE); | |
| 5477 | + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE, handle); | |
| 5478 | 5478 | |
| 5479 | 5479 | /* Expand file to avoid data loss if there is error while shifting */ |
| 5480 | 5480 | inode->i_size += len; |
| @@ -5571,7 +5571,7 @@ out_mutex: · 90 unmodified lines | ||
| 5571 | 5571 | * stuff such as page-cache locking consistency, bh mapping consistency or |
| 5572 | 5572 | * extent's data copying must be performed by caller. |
| 5573 | 5573 | * Locking: |
| 5574 | − * i_mutex is held for both inodes | |
| 5574 | + * i_rwsem is held for both inodes | |
| 5575 | 5575 | * i_data_sem is locked for write for both inodes |
| 5576 | 5576 | * Assumptions: |
| 5577 | 5577 | * All pages from requested range are locked for both inodes |
| @@ -6091,11 +6091,15 @@ int ext4_ext_clear_bb(struct inode *inode) · 513 unmodified lines | ||
| 6091 | 6091 | |
| 6092 | 6092 | ext4_mb_mark_bb(inode->i_sb, |
| 6093 | 6093 | path[j].p_block, 1, 0); |
| 6094 | + ext4_fc_record_regions(inode->i_sb, inode->i_ino, | |
| 6095 | + 0, path[j].p_block, 1, 1); | |
| 6094 | 6096 | } |
| 6095 | 6097 | ext4_ext_drop_refs(path); |
| 6096 | 6098 | kfree(path); |
| 6097 | 6099 | } |
| 6098 | 6100 | ext4_mb_mark_bb(inode->i_sb, map.m_pblk, map.m_len, 0); |
| 6101 | + ext4_fc_record_regions(inode->i_sb, inode->i_ino, | |
| 6102 | + map.m_lblk, map.m_pblk, map.m_len, 1); | |
| 6099 | 6103 | } |
| 6100 | 6104 | cur = cur + map.m_len; |
| 6101 | 6105 | } |
| @@ -300,18 +300,32 @@ restart: · 299 unmodified lines | ||
| 300 | 300 | } |
| 301 | 301 | |
| 302 | 302 | /* |
| 303 | − * Mark file system as fast commit ineligible. This means that next commit | |
| 304 | − * operation would result in a full jbd2 commit. | |
| 303 | + * Mark file system as fast commit ineligible, and record latest | |
| 304 | + * ineligible transaction tid. This means until the recorded | |
| 305 | + * transaction, commit operation would result in a full jbd2 commit. | |
| 305 | 306 | */ |
| 306 | −void ext4_fc_mark_ineligible(struct super_block *sb, int reason) | |
| 307 | +void ext4_fc_mark_ineligible(struct super_block *sb, int reason, handle_t *handle) | |
| 307 | 308 | { |
| 308 | 309 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 310 | + tid_t tid; | |
| 309 | 311 | |
| 310 | 312 | if (!test_opt2(sb, JOURNAL_FAST_COMMIT) || |
| 311 | 313 | (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) |
| 312 | 314 | return; |
| 313 | 315 | |
| 314 | 316 | ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); |
| 317 | + if (handle && !IS_ERR(handle)) | |
| 318 | + tid = handle->h_transaction->t_tid; | |
| 319 | + else { | |
| 320 | + read_lock(&sbi->s_journal->j_state_lock); | |
| 321 | + tid = sbi->s_journal->j_running_transaction ? | |
| 322 | + sbi->s_journal->j_running_transaction->t_tid : 0; | |
| 323 | + read_unlock(&sbi->s_journal->j_state_lock); | |
| 324 | + } | |
| 325 | + spin_lock(&sbi->s_fc_lock); | |
| 326 | + if (sbi->s_fc_ineligible_tid < tid) | |
| 327 | + sbi->s_fc_ineligible_tid = tid; | |
| 328 | + spin_unlock(&sbi->s_fc_lock); | |
| 315 | 329 | WARN_ON(reason >= EXT4_FC_REASON_MAX); |
| 316 | 330 | sbi->s_fc_stats.fc_ineligible_reason_count[reason]++; |
| 317 | 331 | } |
| @@ -361,7 +375,8 @@ static int ext4_fc_track_template( · 43 unmodified lines | ||
| 361 | 375 | spin_lock(&sbi->s_fc_lock); |
| 362 | 376 | if (list_empty(&EXT4_I(inode)->i_fc_list)) |
| 363 | 377 | list_add_tail(&EXT4_I(inode)->i_fc_list, |
| 364 | − (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING)) ? | |
| 378 | + (sbi->s_journal->j_flags & JBD2_FULL_COMMIT_ONGOING || | |
| 379 | + sbi->s_journal->j_flags & JBD2_FAST_COMMIT_ONGOING) ? | |
| 365 | 380 | &sbi->s_fc_q[FC_Q_STAGING] : |
| 366 | 381 | &sbi->s_fc_q[FC_Q_MAIN]); |
| 367 | 382 | spin_unlock(&sbi->s_fc_lock); |
| @@ -387,7 +402,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update) · 19 unmodified lines | ||
| 387 | 402 | mutex_unlock(&ei->i_fc_lock); |
| 388 | 403 | node = kmem_cache_alloc(ext4_fc_dentry_cachep, GFP_NOFS); |
| 389 | 404 | if (!node) { |
| 390 | − ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM); | |
| 405 | + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM, NULL); | |
| 391 | 406 | mutex_lock(&ei->i_fc_lock); |
| 392 | 407 | return -ENOMEM; |
| 393 | 408 | } |
| @@ -400,7 +415,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update) · 6 unmodified lines | ||
| 400 | 415 | if (!node->fcd_name.name) { |
| 401 | 416 | kmem_cache_free(ext4_fc_dentry_cachep, node); |
| 402 | 417 | ext4_fc_mark_ineligible(inode->i_sb, |
| 403 | − EXT4_FC_REASON_NOMEM); | |
| 418 | + EXT4_FC_REASON_NOMEM, NULL); | |
| 404 | 419 | mutex_lock(&ei->i_fc_lock); |
| 405 | 420 | return -ENOMEM; |
| 406 | 421 | } |
| @@ -414,7 +429,8 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update) · 7 unmodified lines | ||
| 414 | 429 | node->fcd_name.len = dentry->d_name.len; |
| 415 | 430 | |
| 416 | 431 | spin_lock(&sbi->s_fc_lock); |
| 417 | − if (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING)) | |
| 432 | + if (sbi->s_journal->j_flags & JBD2_FULL_COMMIT_ONGOING || | |
| 433 | + sbi->s_journal->j_flags & JBD2_FAST_COMMIT_ONGOING) | |
| 418 | 434 | list_add_tail(&node->fcd_list, |
| 419 | 435 | &sbi->s_fc_dentry_q[FC_Q_STAGING]); |
| 420 | 436 | else |
| @@ -502,7 +518,7 @@ void ext4_fc_track_inode(handle_t *handle, struct inode *inode) · 81 unmodified lines | ||
| 502 | 518 | |
| 503 | 519 | if (ext4_should_journal_data(inode)) { |
| 504 | 520 | ext4_fc_mark_ineligible(inode->i_sb, |
| 505 | − EXT4_FC_REASON_INODE_JOURNAL_DATA); | |
| 521 | + EXT4_FC_REASON_INODE_JOURNAL_DATA, handle); | |
| 506 | 522 | return; |
| 507 | 523 | } |
| 508 | 524 | |
| @@ -879,7 +895,6 @@ static int ext4_fc_submit_inode_data_all(journal_t *journal) · 370 unmodified lines | ||
| 879 | 895 | int ret = 0; |
| 880 | 896 | |
| 881 | 897 | spin_lock(&sbi->s_fc_lock); |
| 882 | − ext4_set_mount_flag(sb, EXT4_MF_FC_COMMITTING); | |
| 883 | 898 | list_for_each_entry(ei, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) { |
| 884 | 899 | ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING); |
| 885 | 900 | while (atomic_read(&ei->i_fc_updates)) { |
| @@ -1179,7 +1194,7 @@ fallback: · 293 unmodified lines | ||
| 1179 | 1194 | * Fast commit cleanup routine. This is called after every fast commit and |
| 1180 | 1195 | * full commit. full is true if we are called after a full commit. |
| 1181 | 1196 | */ |
| 1182 | −static void ext4_fc_cleanup(journal_t *journal, int full) | |
| 1197 | +static void ext4_fc_cleanup(journal_t *journal, int full, tid_t tid) | |
| 1183 | 1198 | { |
| 1184 | 1199 | struct super_block *sb = journal->j_private; |
| 1185 | 1200 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| @@ -1197,7 +1212,8 @@ static void ext4_fc_cleanup(journal_t *journal, int full) · 11 unmodified lines | ||
| 1197 | 1212 | list_del_init(&iter->i_fc_list); |
| 1198 | 1213 | ext4_clear_inode_state(&iter->vfs_inode, |
| 1199 | 1214 | EXT4_STATE_FC_COMMITTING); |
| 1200 | − ext4_fc_reset_inode(&iter->vfs_inode); | |
| 1215 | + if (iter->i_sync_tid <= tid) | |
| 1216 | + ext4_fc_reset_inode(&iter->vfs_inode); | |
| 1201 | 1217 | /* Make sure EXT4_STATE_FC_COMMITTING bit is clear */ |
| 1202 | 1218 | smp_mb(); |
| 1203 | 1219 | #if (BITS_PER_LONG < 64) |
| @@ -1226,8 +1242,10 @@ static void ext4_fc_cleanup(journal_t *journal, int full) · 22 unmodified lines | ||
| 1226 | 1242 | list_splice_init(&sbi->s_fc_q[FC_Q_STAGING], |
| 1227 | 1243 | &sbi->s_fc_q[FC_Q_MAIN]); |
| 1228 | 1244 | |
| 1229 | − ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); | |
| 1230 | − ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); | |
| 1245 | + if (tid >= sbi->s_fc_ineligible_tid) { | |
| 1246 | + sbi->s_fc_ineligible_tid = 0; | |
| 1247 | + ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); | |
| 1248 | + } | |
| 1231 | 1249 | |
| 1232 | 1250 | if (full) |
| 1233 | 1251 | sbi->s_fc_bytes = 0; |
| @@ -1392,14 +1410,15 @@ static int ext4_fc_record_modified_inode(struct super_block *sb, int ino) · 158 unmodified lines | ||
| 1392 | 1410 | if (state->fc_modified_inodes[i] == ino) |
| 1393 | 1411 | return 0; |
| 1394 | 1412 | if (state->fc_modified_inodes_used == state->fc_modified_inodes_size) { |
| 1395 | − state->fc_modified_inodes_size += | |
| 1396 | − EXT4_FC_REPLAY_REALLOC_INCREMENT; | |
| 1397 | 1413 | state->fc_modified_inodes = krealloc( |
| 1398 | − state->fc_modified_inodes, sizeof(int) * | |
| 1399 | − state->fc_modified_inodes_size, | |
| 1400 | − GFP_KERNEL); | |
| 1414 | + state->fc_modified_inodes, | |
| 1415 | + sizeof(int) * (state->fc_modified_inodes_size + | |
| 1416 | + EXT4_FC_REPLAY_REALLOC_INCREMENT), | |
| 1417 | + GFP_KERNEL); | |
| 1401 | 1418 | if (!state->fc_modified_inodes) |
| 1402 | 1419 | return -ENOMEM; |
| 1420 | + state->fc_modified_inodes_size += | |
| 1421 | + EXT4_FC_REPLAY_REALLOC_INCREMENT; | |
| 1403 | 1422 | } |
| 1404 | 1423 | state->fc_modified_inodes[state->fc_modified_inodes_used++] = ino; |
| 1405 | 1424 | return 0; |
| @@ -1431,7 +1450,9 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl, · 25 unmodified lines | ||
| 1431 | 1450 | } |
| 1432 | 1451 | inode = NULL; |
| 1433 | 1452 | |
| 1434 | − ext4_fc_record_modified_inode(sb, ino); | |
| 1453 | + ret = ext4_fc_record_modified_inode(sb, ino); | |
| 1454 | + if (ret) | |
| 1455 | + goto out; | |
| 1435 | 1456 | |
| 1436 | 1457 | raw_fc_inode = (struct ext4_inode *) |
| 1437 | 1458 | (val + offsetof(struct ext4_fc_inode, fc_raw_inode)); |
| @@ -1563,16 +1584,23 @@ out: · 125 unmodified lines | ||
| 1563 | 1584 | } |
| 1564 | 1585 | |
| 1565 | 1586 | /* |
| 1566 | − * Record physical disk regions which are in use as per fast commit area. Our | |
| 1567 | − * simple replay phase allocator excludes these regions from allocation. | |
| 1587 | + * Record physical disk regions which are in use as per fast commit area, | |
| 1588 | + * and used by inodes during replay phase. Our simple replay phase | |
| 1589 | + * allocator excludes these regions from allocation. | |
| 1568 | 1590 | */ |
| 1569 | −static int ext4_fc_record_regions(struct super_block *sb, int ino, | |
| 1570 | − ext4_lblk_t lblk, ext4_fsblk_t pblk, int len) | |
| 1591 | +int ext4_fc_record_regions(struct super_block *sb, int ino, | |
| 1592 | + ext4_lblk_t lblk, ext4_fsblk_t pblk, int len, int replay) | |
| 1571 | 1593 | { |
| 1572 | 1594 | struct ext4_fc_replay_state *state; |
| 1573 | 1595 | struct ext4_fc_alloc_region *region; |
| 1574 | 1596 | |
| 1575 | 1597 | state = &EXT4_SB(sb)->s_fc_replay_state; |
| 1598 | + /* | |
| 1599 | + * during replay phase, the fc_regions_valid may not same as | |
| 1600 | + * fc_regions_used, update it when do new additions. | |
| 1601 | + */ | |
| 1602 | + if (replay && state->fc_regions_used != state->fc_regions_valid) | |
| 1603 | + state->fc_regions_used = state->fc_regions_valid; | |
| 1576 | 1604 | if (state->fc_regions_used == state->fc_regions_size) { |
| 1577 | 1605 | state->fc_regions_size += |
| 1578 | 1606 | EXT4_FC_REPLAY_REALLOC_INCREMENT; |
| @@ -1590,6 +1618,9 @@ static int ext4_fc_record_regions(struct super_block *sb, int ino, · 11 unmodified lines | ||
| 1590 | 1618 | region->pblk = pblk; |
| 1591 | 1619 | region->len = len; |
| 1592 | 1620 | |
| 1621 | + if (replay) | |
| 1622 | + state->fc_regions_valid++; | |
| 1623 | + | |
| 1593 | 1624 | return 0; |
| 1594 | 1625 | } |
| 1595 | 1626 | |
| @@ -1621,6 +1652,8 @@ static int ext4_fc_replay_add_range(struct super_block *sb, · 25 unmodified lines | ||
| 1621 | 1652 | } |
| 1622 | 1653 | |
| 1623 | 1654 | ret = ext4_fc_record_modified_inode(sb, inode->i_ino); |
| 1655 | + if (ret) | |
| 1656 | + goto out; | |
| 1624 | 1657 | |
| 1625 | 1658 | start = le32_to_cpu(ex->ee_block); |
| 1626 | 1659 | start_pblk = ext4_ext_pblock(ex); |
| @@ -1638,18 +1671,14 @@ static int ext4_fc_replay_add_range(struct super_block *sb, · 11 unmodified lines | ||
| 1638 | 1671 | map.m_pblk = 0; |
| 1639 | 1672 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
| 1640 | 1673 | |
| 1641 | − if (ret < 0) { | |
| 1642 | − iput(inode); | |
| 1643 | − return 0; | |
| 1644 | − } | |
| 1674 | + if (ret < 0) | |
| 1675 | + goto out; | |
| 1645 | 1676 | |
| 1646 | 1677 | if (ret == 0) { |
| 1647 | 1678 | /* Range is not mapped */ |
| 1648 | 1679 | path = ext4_find_extent(inode, cur, NULL, 0); |
| 1649 | − if (IS_ERR(path)) { | |
| 1650 | − iput(inode); | |
| 1651 | − return 0; | |
| 1652 | − } | |
| 1680 | + if (IS_ERR(path)) | |
| 1681 | + goto out; | |
| 1653 | 1682 | memset(&newex, 0, sizeof(newex)); |
| 1654 | 1683 | newex.ee_block = cpu_to_le32(cur); |
| 1655 | 1684 | ext4_ext_store_pblock( |
| @@ -1663,10 +1692,8 @@ static int ext4_fc_replay_add_range(struct super_block *sb, · 7 unmodified lines | ||
| 1663 | 1692 | up_write((&EXT4_I(inode)->i_data_sem)); |
| 1664 | 1693 | ext4_ext_drop_refs(path); |
| 1665 | 1694 | kfree(path); |
| 1666 | − if (ret) { | |
| 1667 | − iput(inode); | |
| 1668 | − return 0; | |
| 1669 | − } | |
| 1695 | + if (ret) | |
| 1696 | + goto out; | |
| 1670 | 1697 | goto next; |
| 1671 | 1698 | } |
| 1672 | 1699 | |
| @@ -1679,10 +1706,8 @@ static int ext4_fc_replay_add_range(struct super_block *sb, · 6 unmodified lines | ||
| 1679 | 1706 | ret = ext4_ext_replay_update_ex(inode, cur, map.m_len, |
| 1680 | 1707 | ext4_ext_is_unwritten(ex), |
| 1681 | 1708 | start_pblk + cur - start); |
| 1682 | − if (ret) { | |
| 1683 | − iput(inode); | |
| 1684 | − return 0; | |
| 1685 | − } | |
| 1709 | + if (ret) | |
| 1710 | + goto out; | |
| 1686 | 1711 | /* |
| 1687 | 1712 | * Mark the old blocks as free since they aren't used |
| 1688 | 1713 | * anymore. We maintain an array of all the modified |
| @@ -1702,10 +1727,8 @@ static int ext4_fc_replay_add_range(struct super_block *sb, · 13 unmodified lines | ||
| 1702 | 1727 | ext4_ext_is_unwritten(ex), map.m_pblk); |
| 1703 | 1728 | ret = ext4_ext_replay_update_ex(inode, cur, map.m_len, |
| 1704 | 1729 | ext4_ext_is_unwritten(ex), map.m_pblk); |
| 1705 | − if (ret) { | |
| 1706 | − iput(inode); | |
| 1707 | − return 0; | |
| 1708 | − } | |
| 1730 | + if (ret) | |
| 1731 | + goto out; | |
| 1709 | 1732 | /* |
| 1710 | 1733 | * We may have split the extent tree while toggling the state. |
| 1711 | 1734 | * Try to shrink the extent tree now. |
| @@ -1717,6 +1740,7 @@ next: · 5 unmodified lines | ||
| 1717 | 1740 | } |
| 1718 | 1741 | ext4_ext_replay_shrink_inode(inode, i_size_read(inode) >> |
| 1719 | 1742 | sb->s_blocksize_bits); |
| 1743 | +out: | |
| 1720 | 1744 | iput(inode); |
| 1721 | 1745 | return 0; |
| 1722 | 1746 | } |
| @@ -1746,6 +1770,8 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl, · 23 unmodified lines | ||
| 1746 | 1770 | } |
| 1747 | 1771 | |
| 1748 | 1772 | ret = ext4_fc_record_modified_inode(sb, inode->i_ino); |
| 1773 | + if (ret) | |
| 1774 | + goto out; | |
| 1749 | 1775 | |
| 1750 | 1776 | jbd_debug(1, "DEL_RANGE, inode %ld, lblk %d, len %d\n", |
| 1751 | 1777 | inode->i_ino, le32_to_cpu(lrange.fc_lblk), |
| @@ -1755,10 +1781,8 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl, · 3 unmodified lines | ||
| 1755 | 1781 | map.m_len = remaining; |
| 1756 | 1782 | |
| 1757 | 1783 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
| 1758 | − if (ret < 0) { | |
| 1759 | − iput(inode); | |
| 1760 | − return 0; | |
| 1761 | − } | |
| 1784 | + if (ret < 0) | |
| 1785 | + goto out; | |
| 1762 | 1786 | if (ret > 0) { |
| 1763 | 1787 | remaining -= ret; |
| 1764 | 1788 | cur += ret; |
| @@ -1770,18 +1794,17 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl, · 5 unmodified lines | ||
| 1770 | 1794 | } |
| 1771 | 1795 | |
| 1772 | 1796 | down_write(&EXT4_I(inode)->i_data_sem); |
| 1773 | − ret = ext4_ext_remove_space(inode, lrange.fc_lblk, | |
| 1774 | − lrange.fc_lblk + lrange.fc_len - 1); | |
| 1797 | + ret = ext4_ext_remove_space(inode, le32_to_cpu(lrange.fc_lblk), | |
| 1798 | + le32_to_cpu(lrange.fc_lblk) + | |
| 1799 | + le32_to_cpu(lrange.fc_len) - 1); | |
| 1775 | 1800 | up_write(&EXT4_I(inode)->i_data_sem); |
| 1776 | − if (ret) { | |
| 1777 | − iput(inode); | |
| 1778 | − return 0; | |
| 1779 | − } | |
| 1801 | + if (ret) | |
| 1802 | + goto out; | |
| 1780 | 1803 | ext4_ext_replay_shrink_inode(inode, |
| 1781 | 1804 | i_size_read(inode) >> sb->s_blocksize_bits); |
| 1782 | 1805 | ext4_mark_inode_dirty(NULL, inode); |
| 1806 | +out: | |
| 1783 | 1807 | iput(inode); |
| 1784 | − | |
| 1785 | 1808 | return 0; |
| 1786 | 1809 | } |
| 1787 | 1810 | |
| @@ -1937,7 +1960,7 @@ static int ext4_fc_replay_scan(journal_t *journal, · 149 unmodified lines | ||
| 1937 | 1960 | ret = ext4_fc_record_regions(sb, |
| 1938 | 1961 | le32_to_cpu(ext.fc_ino), |
| 1939 | 1962 | le32_to_cpu(ex->ee_block), ext4_ext_pblock(ex), |
| 1940 | − ext4_ext_get_actual_len(ex)); | |
| 1963 | + ext4_ext_get_actual_len(ex), 0); | |
| 1941 | 1964 | if (ret < 0) |
| 1942 | 1965 | break; |
| 1943 | 1966 | ret = JBD2_FC_REPLAY_CONTINUE; |
| @@ -696,7 +696,7 @@ static int ext4_ind_trunc_restart_fn(handle_t *handle, struct inode *inode, · 695 unmodified lines | ||
| 696 | 696 | * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this |
| 697 | 697 | * moment, get_block can be called only for blocks inside i_size since |
| 698 | 698 | * page cache has been already dropped and writes are blocked by |
| 699 | − * i_mutex. So we can safely drop the i_data_sem here. | |
| 699 | + * i_rwsem. So we can safely drop the i_data_sem here. | |
| 700 | 700 | */ |
| 701 | 701 | BUG_ON(EXT4_JOURNAL(inode) == NULL); |
| 702 | 702 | ext4_discard_preallocations(inode, 0); |
| @@ -911,7 +911,7 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping, · 910 unmodified lines | ||
| 911 | 911 | struct page **pagep, |
| 912 | 912 | void **fsdata) |
| 913 | 913 | { |
| 914 | − int ret, inline_size; | |
| 914 | + int ret; | |
| 915 | 915 | handle_t *handle; |
| 916 | 916 | struct page *page; |
| 917 | 917 | struct ext4_iloc iloc; |
| @@ -928,14 +928,9 @@ retry_journal: · 10 unmodified lines | ||
| 928 | 928 | goto out; |
| 929 | 929 | } |
| 930 | 930 | |
| 931 | − inline_size = ext4_get_max_inline_size(inode); | |
| 932 | − | |
| 933 | − ret = -ENOSPC; | |
| 934 | − if (inline_size >= pos + len) { | |
| 935 | − ret = ext4_prepare_inline_data(handle, inode, pos + len); | |
| 936 | − if (ret && ret != -ENOSPC) | |
| 937 | − goto out_journal; | |
| 938 | − } | |
| 931 | + ret = ext4_prepare_inline_data(handle, inode, pos + len); | |
| 932 | + if (ret && ret != -ENOSPC) | |
| 933 | + goto out_journal; | |
| 939 | 934 | |
| 940 | 935 | /* |
| 941 | 936 | * We cannot recurse into the filesystem as the transaction |
| @@ -1133,7 +1128,15 @@ static void ext4_restore_inline_data(handle_t *handle, struct inode *inode, · 191 unmodified lines | ||
| 1133 | 1128 | struct ext4_iloc *iloc, |
| 1134 | 1129 | void *buf, int inline_size) |
| 1135 | 1130 | { |
| 1136 | − ext4_create_inline_data(handle, inode, inline_size); | |
| 1131 | + int ret; | |
| 1132 | + | |
| 1133 | + ret = ext4_create_inline_data(handle, inode, inline_size); | |
| 1134 | + if (ret) { | |
| 1135 | + ext4_msg(inode->i_sb, KERN_EMERG, | |
| 1136 | + "error restoring inline_data for inode -- potential data loss! (inode %lu, error %d)", | |
| 1137 | + inode->i_ino, ret); | |
| 1138 | + return; | |
| 1139 | + } | |
| 1137 | 1140 | ext4_write_inline_data(inode, iloc, buf, 0, inline_size); |
| 1138 | 1141 | ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); |
| 1139 | 1142 | } |
| @@ -338,7 +338,7 @@ stop_handle: · 337 unmodified lines | ||
| 338 | 338 | return; |
| 339 | 339 | no_delete: |
| 340 | 340 | if (!list_empty(&EXT4_I(inode)->i_fc_list)) |
| 341 | − ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM); | |
| 341 | + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM, NULL); | |
| 342 | 342 | ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ |
| 343 | 343 | } |
| 344 | 344 | |
| @@ -1224,7 +1224,7 @@ retry_journal: · 879 unmodified lines | ||
| 1224 | 1224 | /* |
| 1225 | 1225 | * __block_write_begin may have instantiated a few blocks |
| 1226 | 1226 | * outside i_size. Trim these off again. Don't need |
| 1227 | − * i_size_read because we hold i_mutex. | |
| 1227 | + * i_size_read because we hold i_rwsem. | |
| 1228 | 1228 | * |
| 1229 | 1229 | * Add inode to orphan list in case we crash before |
| 1230 | 1230 | * truncate finishes |
| @@ -3979,7 +3979,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) · 2748 unmodified lines | ||
| 3979 | 3979 | |
| 3980 | 3980 | } |
| 3981 | 3981 | |
| 3982 | − /* Wait all existing dio workers, newcomers will block on i_mutex */ | |
| 3982 | + /* Wait all existing dio workers, newcomers will block on i_rwsem */ | |
| 3983 | 3983 | inode_dio_wait(inode); |
| 3984 | 3984 | |
| 3985 | 3985 | /* |
| @@ -4129,7 +4129,7 @@ int ext4_truncate(struct inode *inode) · 143 unmodified lines | ||
| 4129 | 4129 | /* |
| 4130 | 4130 | * There is a possibility that we're either freeing the inode |
| 4131 | 4131 | * or it's a completely new inode. In those cases we might not |
| 4132 | − * have i_mutex locked because it's not necessary. | |
| 4132 | + * have i_rwsem locked because it's not necessary. | |
| 4133 | 4133 | */ |
| 4134 | 4134 | if (!(inode->i_state & (I_NEW|I_FREEING))) |
| 4135 | 4135 | WARN_ON(!inode_is_locked(inode)); |
| @@ -5271,7 +5271,7 @@ static void ext4_wait_for_tail_page_commit(struct inode *inode) · 1135 unmodified lines | ||
| 5271 | 5271 | * transaction are already on disk (truncate waits for pages under |
| 5272 | 5272 | * writeback). |
| 5273 | 5273 | * |
| 5274 | − * Called with inode->i_mutex down. | |
| 5274 | + * Called with inode->i_rwsem down. | |
| 5275 | 5275 | */ |
| 5276 | 5276 | int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, |
| 5277 | 5277 | struct iattr *attr) |
| @@ -5983,7 +5983,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) · 705 unmodified lines | ||
| 5983 | 5983 | return PTR_ERR(handle); |
| 5984 | 5984 | |
| 5985 | 5985 | ext4_fc_mark_ineligible(inode->i_sb, |
| 5986 | − EXT4_FC_REASON_JOURNAL_FLAG_CHANGE); | |
| 5986 | + EXT4_FC_REASON_JOURNAL_FLAG_CHANGE, handle); | |
| 5987 | 5987 | err = ext4_mark_inode_dirty(handle, inode); |
| 5988 | 5988 | ext4_handle_sync(handle); |
| 5989 | 5989 | ext4_journal_stop(handle); |
| @@ -411,7 +411,7 @@ static long swap_inode_boot_loader(struct super_block *sb, · 410 unmodified lines | ||
| 411 | 411 | err = -EINVAL; |
| 412 | 412 | goto err_out; |
| 413 | 413 | } |
| 414 | − ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_SWAP_BOOT); | |
| 414 | + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_SWAP_BOOT, handle); | |
| 415 | 415 | |
| 416 | 416 | /* Protect extent tree against block allocations via delalloc */ |
| 417 | 417 | ext4_double_down_write_data_sem(inode, inode_bl); |
| @@ -1373,7 +1373,7 @@ mext_out: · 955 unmodified lines | ||
| 1373 | 1373 | |
| 1374 | 1374 | err = ext4_resize_fs(sb, n_blocks_count); |
| 1375 | 1375 | if (EXT4_SB(sb)->s_journal) { |
| 1376 | − ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE); | |
| 1376 | + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE, NULL); | |
| 1377 | 1377 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
| 1378 | 1378 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0); |
| 1379 | 1379 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
| @@ -5753,7 +5753,8 @@ static ext4_fsblk_t ext4_mb_new_blocks_simple(handle_t *handle, · 5752 unmodified lines | ||
| 5753 | 5753 | struct super_block *sb = ar->inode->i_sb; |
| 5754 | 5754 | ext4_group_t group; |
| 5755 | 5755 | ext4_grpblk_t blkoff; |
| 5756 | − int i = sb->s_blocksize; | |
| 5756 | + ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb); | |
| 5757 | + ext4_grpblk_t i = 0; | |
| 5757 | 5758 | ext4_fsblk_t goal, block; |
| 5758 | 5759 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
| 5759 | 5760 | |
| @@ -5775,19 +5776,26 @@ static ext4_fsblk_t ext4_mb_new_blocks_simple(handle_t *handle, · 15 unmodified lines | ||
| 5775 | 5776 | ext4_get_group_no_and_offset(sb, |
| 5776 | 5777 | max(ext4_group_first_block_no(sb, group), goal), |
| 5777 | 5778 | NULL, &blkoff); |
| 5778 | − i = mb_find_next_zero_bit(bitmap_bh->b_data, sb->s_blocksize, | |
| 5779 | + while (1) { | |
| 5780 | + i = mb_find_next_zero_bit(bitmap_bh->b_data, max, | |
| 5779 | 5781 | blkoff); |
| 5782 | + if (i >= max) | |
| 5783 | + break; | |
| 5784 | + if (ext4_fc_replay_check_excluded(sb, | |
| 5785 | + ext4_group_first_block_no(sb, group) + i)) { | |
| 5786 | + blkoff = i + 1; | |
| 5787 | + } else | |
| 5788 | + break; | |
| 5789 | + } | |
| 5780 | 5790 | brelse(bitmap_bh); |
| 5781 | − if (i >= sb->s_blocksize) | |
| 5782 | − continue; | |
| 5783 | − if (ext4_fc_replay_check_excluded(sb, | |
| 5784 | − ext4_group_first_block_no(sb, group) + i)) | |
| 5785 | − continue; | |
| 5786 | − break; | |
| 5791 | + if (i < max) | |
| 5792 | + break; | |
| 5787 | 5793 | } |
| 5788 | 5794 | |
| 5789 | − if (group >= ext4_get_groups_count(sb) && i >= sb->s_blocksize) | |
| 5795 | + if (group >= ext4_get_groups_count(sb) || i >= max) { | |
| 5796 | + *errp = -ENOSPC; | |
| 5790 | 5797 | return 0; |
| 5798 | + } | |
| 5791 | 5799 | |
| 5792 | 5800 | block = ext4_group_first_block_no(sb, group) + i; |
| 5793 | 5801 | ext4_mb_mark_bb(sb, block, 1, 1); |
| @@ -485,7 +485,7 @@ int ext4_ext_migrate(struct inode *inode) · 484 unmodified lines | ||
| 485 | 485 | * when we add extents we extent the journal |
| 486 | 486 | */ |
| 487 | 487 | /* |
| 488 | − * Even though we take i_mutex we can still cause block | |
| 488 | + * Even though we take i_rwsem we can still cause block | |
| 489 | 489 | * allocation via mmap write to holes. If we have allocated |
| 490 | 490 | * new blocks we fail migrate. New block allocation will |
| 491 | 491 | * clear EXT4_STATE_EXT_MIGRATE flag. The flag is updated |
| @@ -3889,7 +3889,7 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir, · 3888 unmodified lines | ||
| 3889 | 3889 | * dirents in directories. |
| 3890 | 3890 | */ |
| 3891 | 3891 | ext4_fc_mark_ineligible(old.inode->i_sb, |
| 3892 | − EXT4_FC_REASON_RENAME_DIR); | |
| 3892 | + EXT4_FC_REASON_RENAME_DIR, handle); | |
| 3893 | 3893 | } else { |
| 3894 | 3894 | if (new.inode) |
| 3895 | 3895 | ext4_fc_track_unlink(handle, new.dentry); |
| @@ -4049,7 +4049,7 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry, · 153 unmodified lines | ||
| 4049 | 4049 | if (unlikely(retval)) |
| 4050 | 4050 | goto end_rename; |
| 4051 | 4051 | ext4_fc_mark_ineligible(new.inode->i_sb, |
| 4052 | − EXT4_FC_REASON_CROSS_RENAME); | |
| 4052 | + EXT4_FC_REASON_CROSS_RENAME, handle); | |
| 4053 | 4053 | if (old.dir_bh) { |
| 4054 | 4054 | retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); |
| 4055 | 4055 | if (retval) |
| @@ -93,7 +93,7 @@ static int ext4_orphan_file_add(handle_t *handle, struct inode *inode) · 92 unmodified lines | ||
| 93 | 93 | * At filesystem recovery time, we walk this list deleting unlinked |
| 94 | 94 | * inodes and truncating linked inodes in ext4_orphan_cleanup(). |
| 95 | 95 | * |
| 96 | − * Orphan list manipulation functions must be called under i_mutex unless | |
| 96 | + * Orphan list manipulation functions must be called under i_rwsem unless | |
| 97 | 97 | * we are just creating the inode or deleting it. |
| 98 | 98 | */ |
| 99 | 99 | int ext4_orphan_add(handle_t *handle, struct inode *inode) |
| @@ -119,7 +119,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode) · 19 unmodified lines | ||
| 119 | 119 | /* |
| 120 | 120 | * Orphan handling is only valid for files with data blocks |
| 121 | 121 | * being truncated, or files being unlinked. Note that we either |
| 122 | − * hold i_mutex, or the inode can not be referenced from outside, | |
| 122 | + * hold i_rwsem, or the inode can not be referenced from outside, | |
| 123 | 123 | * so i_nlink should not be bumped due to race |
| 124 | 124 | */ |
| 125 | 125 | ASSERT((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
| @@ -5082,7 +5082,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) · 5081 unmodified lines | ||
| 5082 | 5082 | INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_STAGING]); |
| 5083 | 5083 | sbi->s_fc_bytes = 0; |
| 5084 | 5084 | ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); |
| 5085 | − ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); | |
| 5085 | + sbi->s_fc_ineligible_tid = 0; | |
| 5086 | 5086 | spin_lock_init(&sbi->s_fc_lock); |
| 5087 | 5087 | memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats)); |
| 5088 | 5088 | sbi->s_fc_replay_state.fc_regions = NULL; |
| @@ -5540,7 +5540,7 @@ static int ext4_fill_super(struct super_block *sb, struct fs_context *fc) · 451 unmodified lines | ||
| 5540 | 5540 | |
| 5541 | 5541 | sbi = ext4_alloc_sbi(sb); |
| 5542 | 5542 | if (!sbi) |
| 5543 | − ret = -ENOMEM; | |
| 5543 | + return -ENOMEM; | |
| 5544 | 5544 | |
| 5545 | 5545 | fc->s_fs_info = sbi; |
| 5546 | 5546 | |
| @@ -2408,7 +2408,7 @@ retry_inode: · 2407 unmodified lines | ||
| 2408 | 2408 | if (IS_SYNC(inode)) |
| 2409 | 2409 | ext4_handle_sync(handle); |
| 2410 | 2410 | } |
| 2411 | − ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); | |
| 2411 | + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, handle); | |
| 2412 | 2412 | |
| 2413 | 2413 | cleanup: |
| 2414 | 2414 | brelse(is.iloc.bh); |
| @@ -2486,7 +2486,7 @@ retry: · 71 unmodified lines | ||
| 2486 | 2486 | if (error == 0) |
| 2487 | 2487 | error = error2; |
| 2488 | 2488 | } |
| 2489 | − ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); | |
| 2489 | + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, NULL); | |
| 2490 | 2490 | |
| 2491 | 2491 | return error; |
| 2492 | 2492 | } |
| @@ -2920,7 +2920,7 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, · 427 unmodified lines | ||
| 2920 | 2920 | error); |
| 2921 | 2921 | goto cleanup; |
| 2922 | 2922 | } |
| 2923 | − ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); | |
| 2923 | + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, handle); | |
| 2924 | 2924 | } |
| 2925 | 2925 | error = 0; |
| 2926 | 2926 | cleanup: |
| @@ -119,6 +119,8 @@ static struct ctl_table fs_stat_sysctls[] = { · 118 unmodified lines | ||
| 119 | 119 | static int __init init_fs_stat_sysctls(void) |
| 120 | 120 | { |
| 121 | 121 | register_sysctl_init("fs", fs_stat_sysctls); |
| 122 | + if (IS_ENABLED(CONFIG_BINFMT_MISC)) | |
| 123 | + register_sysctl_mount_point("fs/binfmt_misc"); | |
| 122 | 124 | return 0; |
| 123 | 125 | } |
| 124 | 126 | fs_initcall(init_fs_stat_sysctls); |
| @@ -21,6 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 22 | #include "../internal.h" |
| 23 | 23 | |
| 24 | +#define IOEND_BATCH_SIZE 4096 | |
| 25 | + | |
| 24 | 26 | /* |
| 25 | 27 | * Structure allocated for each folio when block size < folio size |
| 26 | 28 | * to track sub-folio uptodate status and I/O completions. |
| @@ -1039,7 +1041,7 @@ static void iomap_finish_folio_write(struct inode *inode, struct folio *folio, · 1012 unmodified lines | ||
| 1039 | 1041 | * state, release holds on bios, and finally free up memory. Do not use the |
| 1040 | 1042 | * ioend after this. |
| 1041 | 1043 | */ |
| 1042 | −static void | |
| 1044 | +static u32 | |
| 1043 | 1045 | iomap_finish_ioend(struct iomap_ioend *ioend, int error) |
| 1044 | 1046 | { |
| 1045 | 1047 | struct inode *inode = ioend->io_inode; |
| @@ -1048,6 +1050,7 @@ iomap_finish_ioend(struct iomap_ioend *ioend, int error) · 2 unmodified lines | ||
| 1048 | 1050 | u64 start = bio->bi_iter.bi_sector; |
| 1049 | 1051 | loff_t offset = ioend->io_offset; |
| 1050 | 1052 | bool quiet = bio_flagged(bio, BIO_QUIET); |
| 1053 | + u32 folio_count = 0; | |
| 1051 | 1054 | |
| 1052 | 1055 | for (bio = &ioend->io_inline_bio; bio; bio = next) { |
| 1053 | 1056 | struct folio_iter fi; |
| @@ -1062,9 +1065,11 @@ iomap_finish_ioend(struct iomap_ioend *ioend, int error) · 8 unmodified lines | ||
| 1062 | 1065 | next = bio->bi_private; |
| 1063 | 1066 | |
| 1064 | 1067 | /* walk all folios in bio, ending page IO on them */ |
| 1065 | − bio_for_each_folio_all(fi, bio) | |
| 1068 | + bio_for_each_folio_all(fi, bio) { | |
| 1066 | 1069 | iomap_finish_folio_write(inode, fi.folio, fi.length, |
| 1067 | 1070 | error); |
| 1071 | + folio_count++; | |
| 1072 | + } | |
| 1068 | 1073 | bio_put(bio); |
| 1069 | 1074 | } |
| 1070 | 1075 | /* The ioend has been freed by bio_put() */ |
| @@ -1074,20 +1079,36 @@ iomap_finish_ioend(struct iomap_ioend *ioend, int error) · 3 unmodified lines | ||
| 1074 | 1079 | "%s: writeback error on inode %lu, offset %lld, sector %llu", |
| 1075 | 1080 | inode->i_sb->s_id, inode->i_ino, offset, start); |
| 1076 | 1081 | } |
| 1082 | + return folio_count; | |
| 1077 | 1083 | } |
| 1078 | 1084 | |
| 1085 | +/* | |
| 1086 | + * Ioend completion routine for merged bios. This can only be called from task | |
| 1087 | + * contexts as merged ioends can be of unbound length. Hence we have to break up | |
| 1088 | + * the writeback completions into manageable chunks to avoid long scheduler | |
| 1089 | + * holdoffs. We aim to keep scheduler holdoffs down below 10ms so that we get | |
| 1090 | + * good batch processing throughput without creating adverse scheduler latency | |
| 1091 | + * conditions. | |
| 1092 | + */ | |
| 1079 | 1093 | void |
| 1080 | 1094 | iomap_finish_ioends(struct iomap_ioend *ioend, int error) |
| 1081 | 1095 | { |
| 1082 | 1096 | struct list_head tmp; |
| 1097 | + u32 completions; | |
| 1098 | + | |
| 1099 | + might_sleep(); | |
| 1083 | 1100 | |
| 1084 | 1101 | list_replace_init(&ioend->io_list, &tmp); |
| 1085 | − iomap_finish_ioend(ioend, error); | |
| 1102 | + completions = iomap_finish_ioend(ioend, error); | |
| 1086 | 1103 | |
| 1087 | 1104 | while (!list_empty(&tmp)) { |
| 1105 | + if (completions > IOEND_BATCH_SIZE * 8) { | |
| 1106 | + cond_resched(); | |
| 1107 | + completions = 0; | |
| 1108 | + } | |
| 1088 | 1109 | ioend = list_first_entry(&tmp, struct iomap_ioend, io_list); |
| 1089 | 1110 | list_del_init(&ioend->io_list); |
| 1090 | − iomap_finish_ioend(ioend, error); | |
| 1111 | + completions += iomap_finish_ioend(ioend, error); | |
| 1091 | 1112 | } |
| 1092 | 1113 | } |
| 1093 | 1114 | EXPORT_SYMBOL_GPL(iomap_finish_ioends); |
| @@ -1108,6 +1129,18 @@ iomap_ioend_can_merge(struct iomap_ioend *ioend, struct iomap_ioend *next) · 14 unmodified lines | ||
| 1108 | 1129 | return false; |
| 1109 | 1130 | if (ioend->io_offset + ioend->io_size != next->io_offset) |
| 1110 | 1131 | return false; |
| 1132 | + /* | |
| 1133 | + * Do not merge physically discontiguous ioends. The filesystem | |
| 1134 | + * completion functions will have to iterate the physical | |
| 1135 | + * discontiguities even if we merge the ioends at a logical level, so | |
| 1136 | + * we don't gain anything by merging physical discontiguities here. | |
| 1137 | + * | |
| 1138 | + * We cannot use bio->bi_iter.bi_sector here as it is modified during | |
| 1139 | + * submission so does not point to the start sector of the bio at | |
| 1140 | + * completion. | |
| 1141 | + */ | |
| 1142 | + if (ioend->io_sector + (ioend->io_size >> 9) != next->io_sector) | |
| 1143 | + return false; | |
| 1111 | 1144 | return true; |
| 1112 | 1145 | } |
| 1113 | 1146 | |
| @@ -1209,8 +1242,10 @@ iomap_alloc_ioend(struct inode *inode, struct iomap_writepage_ctx *wpc, · 95 unmodified lines | ||
| 1209 | 1242 | ioend->io_flags = wpc->iomap.flags; |
| 1210 | 1243 | ioend->io_inode = inode; |
| 1211 | 1244 | ioend->io_size = 0; |
| 1245 | + ioend->io_folios = 0; | |
| 1212 | 1246 | ioend->io_offset = offset; |
| 1213 | 1247 | ioend->io_bio = bio; |
| 1248 | + ioend->io_sector = sector; | |
| 1214 | 1249 | return ioend; |
| 1215 | 1250 | } |
| 1216 | 1251 | |
| @@ -1251,6 +1286,13 @@ iomap_can_add_to_ioend(struct iomap_writepage_ctx *wpc, loff_t offset, · 34 unmodified lines | ||
| 1251 | 1286 | return false; |
| 1252 | 1287 | if (sector != bio_end_sector(wpc->ioend->io_bio)) |
| 1253 | 1288 | return false; |
| 1289 | + /* | |
| 1290 | + * Limit ioend bio chain lengths to minimise IO completion latency. This | |
| 1291 | + * also prevents long tight loops ending page writeback on all the | |
| 1292 | + * folios in the ioend. | |
| 1293 | + */ | |
| 1294 | + if (wpc->ioend->io_folios >= IOEND_BATCH_SIZE) | |
| 1295 | + return false; | |
| 1254 | 1296 | return true; |
| 1255 | 1297 | } |
| 1256 | 1298 | |
| @@ -1335,6 +1377,8 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc, · 78 unmodified lines | ||
| 1335 | 1377 | &submit_list); |
| 1336 | 1378 | count++; |
| 1337 | 1379 | } |
| 1380 | + if (count) | |
| 1381 | + wpc->ioend->io_folios++; | |
| 1338 | 1382 | |
| 1339 | 1383 | WARN_ON_ONCE(!wpc->ioend && !list_empty(&submit_list)); |
| 1340 | 1384 | WARN_ON_ONCE(!folio_test_locked(folio)); |
| @@ -484,22 +484,9 @@ void jbd2_journal_commit_transaction(journal_t *journal) · 483 unmodified lines | ||
| 484 | 484 | stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start, |
| 485 | 485 | stats.run.rs_locked); |
| 486 | 486 | |
| 487 | − spin_lock(&commit_transaction->t_handle_lock); | |
| 488 | − while (atomic_read(&commit_transaction->t_updates)) { | |
| 489 | − DEFINE_WAIT(wait); | |
| 487 | + // waits for any t_updates to finish | |
| 488 | + jbd2_journal_wait_updates(journal); | |
| 490 | 489 | |
| 491 | − prepare_to_wait(&journal->j_wait_updates, &wait, | |
| 492 | − TASK_UNINTERRUPTIBLE); | |
| 493 | − if (atomic_read(&commit_transaction->t_updates)) { | |
| 494 | − spin_unlock(&commit_transaction->t_handle_lock); | |
| 495 | − write_unlock(&journal->j_state_lock); | |
| 496 | − schedule(); | |
| 497 | − write_lock(&journal->j_state_lock); | |
| 498 | − spin_lock(&commit_transaction->t_handle_lock); | |
| 499 | − } | |
| 500 | − finish_wait(&journal->j_wait_updates, &wait); | |
| 501 | − } | |
| 502 | − spin_unlock(&commit_transaction->t_handle_lock); | |
| 503 | 490 | commit_transaction->t_state = T_SWITCH; |
| 504 | 491 | write_unlock(&journal->j_state_lock); |
| 505 | 492 | |
| @@ -817,7 +804,7 @@ start_journal_io: · 311 unmodified lines | ||
| 817 | 804 | commit_transaction->t_state = T_COMMIT_DFLUSH; |
| 818 | 805 | write_unlock(&journal->j_state_lock); |
| 819 | 806 | |
| 820 | − /* | |
| 807 | + /* | |
| 821 | 808 | * If the journal is not located on the file system device, |
| 822 | 809 | * then we must flush the file system device before we issue |
| 823 | 810 | * the commit record |
| @@ -1170,7 +1157,7 @@ restart_loop: · 346 unmodified lines | ||
| 1170 | 1157 | if (journal->j_commit_callback) |
| 1171 | 1158 | journal->j_commit_callback(journal, commit_transaction); |
| 1172 | 1159 | if (journal->j_fc_cleanup_callback) |
| 1173 | − journal->j_fc_cleanup_callback(journal, 1); | |
| 1160 | + journal->j_fc_cleanup_callback(journal, 1, commit_transaction->t_tid); | |
| 1174 | 1161 | |
| 1175 | 1162 | trace_jbd2_end_commit(journal, commit_transaction); |
| 1176 | 1163 | jbd_debug(1, "JBD2: commit %d complete, head %d\n", |
| @@ -771,7 +771,7 @@ static int __jbd2_fc_end_commit(journal_t *journal, tid_t tid, bool fallback) · 770 unmodified lines | ||
| 771 | 771 | { |
| 772 | 772 | jbd2_journal_unlock_updates(journal); |
| 773 | 773 | if (journal->j_fc_cleanup_callback) |
| 774 | − journal->j_fc_cleanup_callback(journal, 0); | |
| 774 | + journal->j_fc_cleanup_callback(journal, 0, tid); | |
| 775 | 775 | write_lock(&journal->j_state_lock); |
| 776 | 776 | journal->j_flags &= ~JBD2_FAST_COMMIT_ONGOING; |
| 777 | 777 | if (fallback) |
| @@ -1287,6 +1287,8 @@ static int jbd2_min_tag_size(void) · 509 unmodified lines | ||
| 1287 | 1287 | |
| 1288 | 1288 | /** |
| 1289 | 1289 | * jbd2_journal_shrink_scan() |
| 1290 | + * @shrink: shrinker to work on | |
| 1291 | + * @sc: reclaim request to process | |
| 1290 | 1292 | * |
| 1291 | 1293 | * Scan the checkpointed buffer on the checkpoint list and release the |
| 1292 | 1294 | * journal_head. |
| @@ -1312,6 +1314,8 @@ static unsigned long jbd2_journal_shrink_scan(struct shrinker *shrink, · 19 unmodified lines | ||
| 1312 | 1314 | |
| 1313 | 1315 | /** |
| 1314 | 1316 | * jbd2_journal_shrink_count() |
| 1317 | + * @shrink: shrinker to work on | |
| 1318 | + * @sc: reclaim request to process | |
| 1315 | 1319 | * |
| 1316 | 1320 | * Count the number of checkpoint buffers on the checkpoint list. |
| 1317 | 1321 | */ |
| @@ -449,7 +449,7 @@ repeat: · 448 unmodified lines | ||
| 449 | 449 | } |
| 450 | 450 | |
| 451 | 451 | /* OK, account for the buffers that this operation expects to |
| 452 | − * use and add the handle to the running transaction. | |
| 452 | + * use and add the handle to the running transaction. | |
| 453 | 453 | */ |
| 454 | 454 | update_t_max_wait(transaction, ts); |
| 455 | 455 | handle->h_transaction = transaction; |
| @@ -836,6 +836,35 @@ int jbd2_journal_restart(handle_t *handle, int nblocks) · 380 unmodified lines | ||
| 836 | 836 | } |
| 837 | 837 | EXPORT_SYMBOL(jbd2_journal_restart); |
| 838 | 838 | |
| 839 | +/* | |
| 840 | + * Waits for any outstanding t_updates to finish. | |
| 841 | + * This is called with write j_state_lock held. | |
| 842 | + */ | |
| 843 | +void jbd2_journal_wait_updates(journal_t *journal) | |
| 844 | +{ | |
| 845 | + transaction_t *commit_transaction = journal->j_running_transaction; | |
| 846 | + | |
| 847 | + if (!commit_transaction) | |
| 848 | + return; | |
| 849 | + | |
| 850 | + spin_lock(&commit_transaction->t_handle_lock); | |
| 851 | + while (atomic_read(&commit_transaction->t_updates)) { | |
| 852 | + DEFINE_WAIT(wait); | |
| 853 | + | |
| 854 | + prepare_to_wait(&journal->j_wait_updates, &wait, | |
| 855 | + TASK_UNINTERRUPTIBLE); | |
| 856 | + if (atomic_read(&commit_transaction->t_updates)) { | |
| 857 | + spin_unlock(&commit_transaction->t_handle_lock); | |
| 858 | + write_unlock(&journal->j_state_lock); | |
| 859 | + schedule(); | |
| 860 | + write_lock(&journal->j_state_lock); | |
| 861 | + spin_lock(&commit_transaction->t_handle_lock); | |
| 862 | + } | |
| 863 | + finish_wait(&journal->j_wait_updates, &wait); | |
| 864 | + } | |
| 865 | + spin_unlock(&commit_transaction->t_handle_lock); | |
| 866 | +} | |
| 867 | + | |
| 839 | 868 | /** |
| 840 | 869 | * jbd2_journal_lock_updates () - establish a transaction barrier. |
| 841 | 870 | * @journal: Journal to establish a barrier on. |
| @@ -863,27 +892,9 @@ void jbd2_journal_lock_updates(journal_t *journal) · 21 unmodified lines | ||
| 863 | 892 | write_lock(&journal->j_state_lock); |
| 864 | 893 | } |
| 865 | 894 | |
| 866 | − /* Wait until there are no running updates */ | |
| 867 | − while (1) { | |
| 868 | − transaction_t *transaction = journal->j_running_transaction; | |
| 869 | − | |
| 870 | − if (!transaction) | |
| 871 | − break; | |
| 895 | + /* Wait until there are no running t_updates */ | |
| 896 | + jbd2_journal_wait_updates(journal); | |
| 872 | 897 | |
| 873 | − spin_lock(&transaction->t_handle_lock); | |
| 874 | − prepare_to_wait(&journal->j_wait_updates, &wait, | |
| 875 | − TASK_UNINTERRUPTIBLE); | |
| 876 | − if (!atomic_read(&transaction->t_updates)) { | |
| 877 | − spin_unlock(&transaction->t_handle_lock); | |
| 878 | − finish_wait(&journal->j_wait_updates, &wait); | |
| 879 | − break; | |
| 880 | − } | |
| 881 | − spin_unlock(&transaction->t_handle_lock); | |
| 882 | − write_unlock(&journal->j_state_lock); | |
| 883 | − schedule(); | |
| 884 | − finish_wait(&journal->j_wait_updates, &wait); | |
| 885 | − write_lock(&journal->j_state_lock); | |
| 886 | − } | |
| 887 | 898 | write_unlock(&journal->j_state_lock); |
| 888 | 899 | |
| 889 | 900 | /* |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include "mgmt/user_config.h" |
| 30 | 30 | #include "crypto_ctx.h" |
| 31 | 31 | #include "transport_ipc.h" |
| 32 | +#include "../smbfs_common/arc4.h" | |
| 32 | 33 | |
| 33 | 34 | /* |
| 34 | 35 | * Fixed format data defining GSS header and fixed string |
| @@ -336,6 +337,29 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, · 301 unmodified lines | ||
| 336 | 337 | nt_len - CIFS_ENCPWD_SIZE, |
| 337 | 338 | domain_name, conn->ntlmssp.cryptkey); |
| 338 | 339 | kfree(domain_name); |
| 340 | + | |
| 341 | + /* The recovered secondary session key */ | |
| 342 | + if (conn->ntlmssp.client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) { | |
| 343 | + struct arc4_ctx *ctx_arc4; | |
| 344 | + unsigned int sess_key_off, sess_key_len; | |
| 345 | + | |
| 346 | + sess_key_off = le32_to_cpu(authblob->SessionKey.BufferOffset); | |
| 347 | + sess_key_len = le16_to_cpu(authblob->SessionKey.Length); | |
| 348 | + | |
| 349 | + if (blob_len < (u64)sess_key_off + sess_key_len) | |
| 350 | + return -EINVAL; | |
| 351 | + | |
| 352 | + ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL); | |
| 353 | + if (!ctx_arc4) | |
| 354 | + return -ENOMEM; | |
| 355 | + | |
| 356 | + cifs_arc4_setkey(ctx_arc4, sess->sess_key, | |
| 357 | + SMB2_NTLMV2_SESSKEY_SIZE); | |
| 358 | + cifs_arc4_crypt(ctx_arc4, sess->sess_key, | |
| 359 | + (char *)authblob + sess_key_off, sess_key_len); | |
| 360 | + kfree_sensitive(ctx_arc4); | |
| 361 | + } | |
| 362 | + | |
| 339 | 363 | return ret; |
| 340 | 364 | } |
| 341 | 365 | |
| @@ -408,6 +432,9 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, · 66 unmodified lines | ||
| 408 | 432 | (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) |
| 409 | 433 | flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
| 410 | 434 | |
| 435 | + if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH) | |
| 436 | + flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | |
| 437 | + | |
| 411 | 438 | chgblob->NegotiateFlags = cpu_to_le32(flags); |
| 412 | 439 | len = strlen(ksmbd_netbios_name()); |
| 413 | 440 | name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL); |
| @@ -2688,7 +2688,7 @@ int smb2_open(struct ksmbd_work *work) · 2687 unmodified lines | ||
| 2688 | 2688 | (struct create_posix *)context; |
| 2689 | 2689 | if (le16_to_cpu(context->DataOffset) + |
| 2690 | 2690 | le32_to_cpu(context->DataLength) < |
| 2691 | − sizeof(struct create_posix)) { | |
| 2691 | + sizeof(struct create_posix) - 4) { | |
| 2692 | 2692 | rc = -EINVAL; |
| 2693 | 2693 | goto err_out1; |
| 2694 | 2694 | } |
| @@ -3422,9 +3422,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level, · 727 unmodified lines | ||
| 3422 | 3422 | goto free_conv_name; |
| 3423 | 3423 | } |
| 3424 | 3424 | |
| 3425 | − struct_sz = readdir_info_level_struct_sz(info_level); | |
| 3426 | − next_entry_offset = ALIGN(struct_sz - 1 + conv_len, | |
| 3427 | − KSMBD_DIR_INFO_ALIGNMENT); | |
| 3425 | + struct_sz = readdir_info_level_struct_sz(info_level) - 1 + conv_len; | |
| 3426 | + next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT); | |
| 3427 | + d_info->last_entry_off_align = next_entry_offset - struct_sz; | |
| 3428 | 3428 | |
| 3429 | 3429 | if (next_entry_offset > d_info->out_buf_len) { |
| 3430 | 3430 | d_info->out_buf_len = 0; |
| @@ -3976,6 +3976,7 @@ int smb2_query_dir(struct ksmbd_work *work) · 545 unmodified lines | ||
| 3976 | 3976 | ((struct file_directory_info *) |
| 3977 | 3977 | ((char *)rsp->Buffer + d_info.last_entry_offset)) |
| 3978 | 3978 | ->NextEntryOffset = 0; |
| 3979 | + d_info.data_count -= d_info.last_entry_off_align; | |
| 3979 | 3980 | |
| 3980 | 3981 | rsp->StructureSize = cpu_to_le16(9); |
| 3981 | 3982 | rsp->OutputBufferOffset = cpu_to_le16(72); |
| @@ -6126,13 +6127,26 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work, · 2144 unmodified lines | ||
| 6126 | 6127 | __le16 ChannelInfoOffset, |
| 6127 | 6128 | __le16 ChannelInfoLength) |
| 6128 | 6129 | { |
| 6130 | + unsigned int i, ch_count; | |
| 6131 | + | |
| 6129 | 6132 | if (work->conn->dialect == SMB30_PROT_ID && |
| 6130 | 6133 | Channel != SMB2_CHANNEL_RDMA_V1) |
| 6131 | 6134 | return -EINVAL; |
| 6132 | 6135 | |
| 6133 | − if (ChannelInfoOffset == 0 || | |
| 6134 | − le16_to_cpu(ChannelInfoLength) < sizeof(*desc)) | |
| 6136 | + ch_count = le16_to_cpu(ChannelInfoLength) / sizeof(*desc); | |
| 6137 | + if (ksmbd_debug_types & KSMBD_DEBUG_RDMA) { | |
| 6138 | + for (i = 0; i < ch_count; i++) { | |
| 6139 | + pr_info("RDMA r/w request %#x: token %#x, length %#x\n", | |
| 6140 | + i, | |
| 6141 | + le32_to_cpu(desc[i].token), | |
| 6142 | + le32_to_cpu(desc[i].length)); | |
| 6143 | + } | |
| 6144 | + } | |
| 6145 | + if (ch_count != 1) { | |
| 6146 | + ksmbd_debug(RDMA, "RDMA multiple buffer descriptors %d are not supported yet\n", | |
| 6147 | + ch_count); | |
| 6135 | 6148 | return -EINVAL; |
| 6149 | + } | |
| 6136 | 6150 | |
| 6137 | 6151 | work->need_invalidate_rkey = |
| 6138 | 6152 | (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE); |
| @@ -6185,9 +6199,15 @@ int smb2_read(struct ksmbd_work *work) · 46 unmodified lines | ||
| 6185 | 6199 | |
| 6186 | 6200 | if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE || |
| 6187 | 6201 | req->Channel == SMB2_CHANNEL_RDMA_V1) { |
| 6202 | + unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset); | |
| 6203 | + | |
| 6204 | + if (ch_offset < offsetof(struct smb2_read_req, Buffer)) { | |
| 6205 | + err = -EINVAL; | |
| 6206 | + goto out; | |
| 6207 | + } | |
| 6188 | 6208 | err = smb2_set_remote_key_for_rdma(work, |
| 6189 | 6209 | (struct smb2_buffer_desc_v1 *) |
| 6190 | − &req->Buffer[0], | |
| 6210 | + ((char *)req + ch_offset), | |
| 6191 | 6211 | req->Channel, |
| 6192 | 6212 | req->ReadChannelInfoOffset, |
| 6193 | 6213 | req->ReadChannelInfoLength); |
| @@ -6428,11 +6448,16 @@ int smb2_write(struct ksmbd_work *work) · 234 unmodified lines | ||
| 6428 | 6448 | |
| 6429 | 6449 | if (req->Channel == SMB2_CHANNEL_RDMA_V1 || |
| 6430 | 6450 | req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) { |
| 6431 | − if (req->Length != 0 || req->DataOffset != 0) | |
| 6432 | − return -EINVAL; | |
| 6451 | + unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset); | |
| 6452 | + | |
| 6453 | + if (req->Length != 0 || req->DataOffset != 0 || | |
| 6454 | + ch_offset < offsetof(struct smb2_write_req, Buffer)) { | |
| 6455 | + err = -EINVAL; | |
| 6456 | + goto out; | |
| 6457 | + } | |
| 6433 | 6458 | err = smb2_set_remote_key_for_rdma(work, |
| 6434 | 6459 | (struct smb2_buffer_desc_v1 *) |
| 6435 | − &req->Buffer[0], | |
| 6460 | + ((char *)req + ch_offset), | |
| 6436 | 6461 | req->Channel, |
| 6437 | 6462 | req->WriteChannelInfoOffset, |
| 6438 | 6463 | req->WriteChannelInfoLength); |
| @@ -308,14 +308,17 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level, · 307 unmodified lines | ||
| 308 | 308 | for (i = 0; i < 2; i++) { |
| 309 | 309 | struct kstat kstat; |
| 310 | 310 | struct ksmbd_kstat ksmbd_kstat; |
| 311 | + struct dentry *dentry; | |
| 311 | 312 | |
| 312 | 313 | if (!dir->dot_dotdot[i]) { /* fill dot entry info */ |
| 313 | 314 | if (i == 0) { |
| 314 | 315 | d_info->name = "."; |
| 315 | 316 | d_info->name_len = 1; |
| 317 | + dentry = dir->filp->f_path.dentry; | |
| 316 | 318 | } else { |
| 317 | 319 | d_info->name = ".."; |
| 318 | 320 | d_info->name_len = 2; |
| 321 | + dentry = dir->filp->f_path.dentry->d_parent; | |
| 319 | 322 | } |
| 320 | 323 | |
| 321 | 324 | if (!match_pattern(d_info->name, d_info->name_len, |
| @@ -327,7 +330,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level, · 5 unmodified lines | ||
| 327 | 330 | ksmbd_kstat.kstat = &kstat; |
| 328 | 331 | ksmbd_vfs_fill_dentry_attrs(work, |
| 329 | 332 | user_ns, |
| 330 | − dir->filp->f_path.dentry->d_parent, | |
| 333 | + dentry, | |
| 331 | 334 | &ksmbd_kstat); |
| 332 | 335 | rc = fn(conn, info_level, d_info, &ksmbd_kstat); |
| 333 | 336 | if (rc) |
| @@ -80,7 +80,7 @@ static int smb_direct_max_fragmented_recv_size = 1024 * 1024; · 79 unmodified lines | ||
| 80 | 80 | /* The maximum single-message size which can be received */ |
| 81 | 81 | static int smb_direct_max_receive_size = 8192; |
| 82 | 82 | |
| 83 | −static int smb_direct_max_read_write_size = 1048512; | |
| 83 | +static int smb_direct_max_read_write_size = 524224; | |
| 84 | 84 | |
| 85 | 85 | static int smb_direct_max_outstanding_rw_ops = 8; |
| 86 | 86 | |
| @@ -47,6 +47,7 @@ struct ksmbd_dir_info { · 46 unmodified lines | ||
| 47 | 47 | int last_entry_offset; |
| 48 | 48 | bool hide_dot_file; |
| 49 | 49 | int flags; |
| 50 | + int last_entry_off_align; | |
| 50 | 51 | }; |
| 51 | 52 | |
| 52 | 53 | struct ksmbd_readdir_data { |
| @@ -177,6 +177,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) · 176 unmodified lines | ||
| 177 | 177 | INIT_LIST_HEAD(&clp->cl_superblocks); |
| 178 | 178 | clp->cl_rpcclient = ERR_PTR(-EINVAL); |
| 179 | 179 | |
| 180 | + clp->cl_flags = cl_init->init_flags; | |
| 180 | 181 | clp->cl_proto = cl_init->proto; |
| 181 | 182 | clp->cl_nconnect = cl_init->nconnect; |
| 182 | 183 | clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1; |
| @@ -423,7 +424,6 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init) · 240 unmodified lines | ||
| 423 | 424 | list_add_tail(&new->cl_share_link, |
| 424 | 425 | &nn->nfs_client_list); |
| 425 | 426 | spin_unlock(&nn->nfs_client_lock); |
| 426 | − new->cl_flags = cl_init->init_flags; | |
| 427 | 427 | return rpc_ops->init_client(new, cl_init); |
| 428 | 428 | } |
| 429 | 429 | |
| @@ -80,6 +80,7 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir · 79 unmodified lines | ||
| 80 | 80 | ctx->dir_cookie = 0; |
| 81 | 81 | ctx->dup_cookie = 0; |
| 82 | 82 | ctx->page_index = 0; |
| 83 | + ctx->eof = false; | |
| 83 | 84 | spin_lock(&dir->i_lock); |
| 84 | 85 | if (list_empty(&nfsi->open_files) && |
| 85 | 86 | (nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER)) |
| @@ -168,6 +169,7 @@ struct nfs_readdir_descriptor { · 82 unmodified lines | ||
| 168 | 169 | unsigned int cache_entry_index; |
| 169 | 170 | signed char duped; |
| 170 | 171 | bool plus; |
| 172 | + bool eob; | |
| 171 | 173 | bool eof; |
| 172 | 174 | }; |
| 173 | 175 | |
| @@ -867,7 +869,8 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc, · 693 unmodified lines | ||
| 867 | 869 | |
| 868 | 870 | status = nfs_readdir_page_filler(desc, entry, pages, pglen, |
| 869 | 871 | arrays, narrays); |
| 870 | − } while (!status && nfs_readdir_page_needs_filling(page)); | |
| 872 | + } while (!status && nfs_readdir_page_needs_filling(page) && | |
| 873 | + page_mapping(page)); | |
| 871 | 874 | |
| 872 | 875 | nfs_readdir_free_pages(pages, array_size); |
| 873 | 876 | out: |
| @@ -988,7 +991,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc, · 114 unmodified lines | ||
| 988 | 991 | ent = &array->array[i]; |
| 989 | 992 | if (!dir_emit(desc->ctx, ent->name, ent->name_len, |
| 990 | 993 | nfs_compat_user_ino64(ent->ino), ent->d_type)) { |
| 991 | − desc->eof = true; | |
| 994 | + desc->eob = true; | |
| 992 | 995 | break; |
| 993 | 996 | } |
| 994 | 997 | memcpy(desc->verf, verf, sizeof(desc->verf)); |
| @@ -1004,7 +1007,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc, · 9 unmodified lines | ||
| 1004 | 1007 | desc->duped = 1; |
| 1005 | 1008 | } |
| 1006 | 1009 | if (array->page_is_eof) |
| 1007 | − desc->eof = true; | |
| 1010 | + desc->eof = !desc->eob; | |
| 1008 | 1011 | |
| 1009 | 1012 | kunmap(desc->page); |
| 1010 | 1013 | dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %llu\n", |
| @@ -1041,12 +1044,13 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc) · 30 unmodified lines | ||
| 1041 | 1044 | goto out; |
| 1042 | 1045 | |
| 1043 | 1046 | desc->page_index = 0; |
| 1047 | + desc->cache_entry_index = 0; | |
| 1044 | 1048 | desc->last_cookie = desc->dir_cookie; |
| 1045 | 1049 | desc->duped = 0; |
| 1046 | 1050 | |
| 1047 | 1051 | status = nfs_readdir_xdr_to_array(desc, desc->verf, verf, arrays, sz); |
| 1048 | 1052 | |
| 1049 | − for (i = 0; !desc->eof && i < sz && arrays[i]; i++) { | |
| 1053 | + for (i = 0; !desc->eob && i < sz && arrays[i]; i++) { | |
| 1050 | 1054 | desc->page = arrays[i]; |
| 1051 | 1055 | nfs_do_filldir(desc, verf); |
| 1052 | 1056 | } |
| @@ -1105,9 +1109,15 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) · 52 unmodified lines | ||
| 1105 | 1109 | desc->duped = dir_ctx->duped; |
| 1106 | 1110 | page_index = dir_ctx->page_index; |
| 1107 | 1111 | desc->attr_gencount = dir_ctx->attr_gencount; |
| 1112 | + desc->eof = dir_ctx->eof; | |
| 1108 | 1113 | memcpy(desc->verf, dir_ctx->verf, sizeof(desc->verf)); |
| 1109 | 1114 | spin_unlock(&file->f_lock); |
| 1110 | 1115 | |
| 1116 | + if (desc->eof) { | |
| 1117 | + res = 0; | |
| 1118 | + goto out_free; | |
| 1119 | + } | |
| 1120 | + | |
| 1111 | 1121 | if (test_and_clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags) && |
| 1112 | 1122 | list_is_singular(&nfsi->open_files)) |
| 1113 | 1123 | invalidate_mapping_pages(inode->i_mapping, page_index + 1, -1); |
| @@ -1141,7 +1151,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) · 27 unmodified lines | ||
| 1141 | 1151 | |
| 1142 | 1152 | nfs_do_filldir(desc, nfsi->cookieverf); |
| 1143 | 1153 | nfs_readdir_page_unlock_and_put_cached(desc); |
| 1144 | − } while (!desc->eof); | |
| 1154 | + } while (!desc->eob && !desc->eof); | |
| 1145 | 1155 | |
| 1146 | 1156 | spin_lock(&file->f_lock); |
| 1147 | 1157 | dir_ctx->dir_cookie = desc->dir_cookie; |
| @@ -1149,9 +1159,10 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) · 1 unmodified line | ||
| 1149 | 1159 | dir_ctx->duped = desc->duped; |
| 1150 | 1160 | dir_ctx->attr_gencount = desc->attr_gencount; |
| 1151 | 1161 | dir_ctx->page_index = desc->page_index; |
| 1162 | + dir_ctx->eof = desc->eof; | |
| 1152 | 1163 | memcpy(dir_ctx->verf, desc->verf, sizeof(dir_ctx->verf)); |
| 1153 | 1164 | spin_unlock(&file->f_lock); |
| 1154 | − | |
| 1165 | +out_free: | |
| 1155 | 1166 | kfree(desc); |
| 1156 | 1167 | |
| 1157 | 1168 | out: |
| @@ -1193,6 +1204,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence) · 35 unmodified lines | ||
| 1193 | 1204 | if (offset == 0) |
| 1194 | 1205 | memset(dir_ctx->verf, 0, sizeof(dir_ctx->verf)); |
| 1195 | 1206 | dir_ctx->duped = 0; |
| 1207 | + dir_ctx->eof = false; | |
| 1196 | 1208 | } |
| 1197 | 1209 | spin_unlock(&filp->f_lock); |
| 1198 | 1210 | return offset; |
| @@ -8032,7 +8032,8 @@ static int _nfs41_proc_get_locations(struct nfs_server *server, · 8031 unmodified lines | ||
| 8032 | 8032 | |
| 8033 | 8033 | /** |
| 8034 | 8034 | * nfs4_proc_get_locations - discover locations for a migrated FSID |
| 8035 | − * @inode: inode on FSID that is migrating | |
| 8035 | + * @server: pointer to nfs_server to process | |
| 8036 | + * @fhandle: pointer to the kernel NFS client file handle | |
| 8036 | 8037 | * @locations: result of query |
| 8037 | 8038 | * @page: buffer |
| 8038 | 8039 | * @cred: credential to use for this operation |
| @@ -150,13 +150,17 @@ nfsd3_proc_read(struct svc_rqst *rqstp) · 149 unmodified lines | ||
| 150 | 150 | unsigned int len; |
| 151 | 151 | int v; |
| 152 | 152 | |
| 153 | − argp->count = min_t(u32, argp->count, max_blocksize); | |
| 154 | − | |
| 155 | 153 | dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n", |
| 156 | 154 | SVCFH_fmt(&argp->fh), |
| 157 | 155 | (unsigned long) argp->count, |
| 158 | 156 | (unsigned long long) argp->offset); |
| 159 | 157 | |
| 158 | + argp->count = min_t(u32, argp->count, max_blocksize); | |
| 159 | + if (argp->offset > (u64)OFFSET_MAX) | |
| 160 | + argp->offset = (u64)OFFSET_MAX; | |
| 161 | + if (argp->offset + argp->count > (u64)OFFSET_MAX) | |
| 162 | + argp->count = (u64)OFFSET_MAX - argp->offset; | |
| 163 | + | |
| 160 | 164 | v = 0; |
| 161 | 165 | len = argp->count; |
| 162 | 166 | resp->pages = rqstp->rq_next_page; |
| @@ -199,6 +203,11 @@ nfsd3_proc_write(struct svc_rqst *rqstp) · 36 unmodified lines | ||
| 199 | 203 | (unsigned long long) argp->offset, |
| 200 | 204 | argp->stable? " stable" : ""); |
| 201 | 205 | |
| 206 | + resp->status = nfserr_fbig; | |
| 207 | + if (argp->offset > (u64)OFFSET_MAX || | |
| 208 | + argp->offset + argp->len > (u64)OFFSET_MAX) | |
| 209 | + return rpc_success; | |
| 210 | + | |
| 202 | 211 | fh_copy(&resp->fh, &argp->fh); |
| 203 | 212 | resp->committed = argp->stable; |
| 204 | 213 | nvecs = svc_fill_write_vector(rqstp, &argp->payload); |
| @@ -651,15 +660,9 @@ nfsd3_proc_commit(struct svc_rqst *rqstp) · 446 unmodified lines | ||
| 651 | 660 | argp->count, |
| 652 | 661 | (unsigned long long) argp->offset); |
| 653 | 662 | |
| 654 | − if (argp->offset > NFS_OFFSET_MAX) { | |
| 655 | − resp->status = nfserr_inval; | |
| 656 | − goto out; | |
| 657 | − } | |
| 658 | − | |
| 659 | 663 | fh_copy(&resp->fh, &argp->fh); |
| 660 | 664 | resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset, |
| 661 | 665 | argp->count, resp->verf); |
| 662 | −out: | |
| 663 | 666 | return rpc_success; |
| 664 | 667 | } |
| 665 | 668 | |
| @@ -254,7 +254,7 @@ svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr, · 253 unmodified lines | ||
| 254 | 254 | if (xdr_stream_decode_u64(xdr, &newsize) < 0) |
| 255 | 255 | return false; |
| 256 | 256 | iap->ia_valid |= ATTR_SIZE; |
| 257 | − iap->ia_size = min_t(u64, newsize, NFS_OFFSET_MAX); | |
| 257 | + iap->ia_size = newsize; | |
| 258 | 258 | } |
| 259 | 259 | if (xdr_stream_decode_u32(xdr, &set_it) < 0) |
| 260 | 260 | return false; |
| @@ -1060,7 +1060,7 @@ svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name, · 799 unmodified lines | ||
| 1060 | 1060 | return false; |
| 1061 | 1061 | /* cookie */ |
| 1062 | 1062 | resp->cookie_offset = dirlist->len; |
| 1063 | − if (xdr_stream_encode_u64(xdr, NFS_OFFSET_MAX) < 0) | |
| 1063 | + if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0) | |
| 1064 | 1064 | return false; |
| 1065 | 1065 | |
| 1066 | 1066 | return true; |
| @@ -782,12 +782,16 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 781 unmodified lines | ||
| 782 | 782 | __be32 status; |
| 783 | 783 | |
| 784 | 784 | read->rd_nf = NULL; |
| 785 | − if (read->rd_offset >= OFFSET_MAX) | |
| 786 | − return nfserr_inval; | |
| 787 | 785 | |
| 788 | 786 | trace_nfsd_read_start(rqstp, &cstate->current_fh, |
| 789 | 787 | read->rd_offset, read->rd_length); |
| 790 | 788 | |
| 789 | + read->rd_length = min_t(u32, read->rd_length, svc_max_payload(rqstp)); | |
| 790 | + if (read->rd_offset > (u64)OFFSET_MAX) | |
| 791 | + read->rd_offset = (u64)OFFSET_MAX; | |
| 792 | + if (read->rd_offset + read->rd_length > (u64)OFFSET_MAX) | |
| 793 | + read->rd_length = (u64)OFFSET_MAX - read->rd_offset; | |
| 794 | + | |
| 791 | 795 | /* |
| 792 | 796 | * If we do a zero copy read, then a client will see read data |
| 793 | 797 | * that reflects the state of the file *after* performing the |
| @@ -1018,8 +1022,9 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 224 unmodified lines | ||
| 1018 | 1022 | unsigned long cnt; |
| 1019 | 1023 | int nvecs; |
| 1020 | 1024 | |
| 1021 | − if (write->wr_offset >= OFFSET_MAX) | |
| 1022 | − return nfserr_inval; | |
| 1025 | + if (write->wr_offset > (u64)OFFSET_MAX || | |
| 1026 | + write->wr_offset + write->wr_buflen > (u64)OFFSET_MAX) | |
| 1027 | + return nfserr_fbig; | |
| 1023 | 1028 | |
| 1024 | 1029 | cnt = write->wr_buflen; |
| 1025 | 1030 | trace_nfsd_write_start(rqstp, &cstate->current_fh, |
| @@ -3495,7 +3495,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, · 3494 unmodified lines | ||
| 3495 | 3495 | p = xdr_reserve_space(xdr, 3*4 + namlen); |
| 3496 | 3496 | if (!p) |
| 3497 | 3497 | goto fail; |
| 3498 | − p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ | |
| 3498 | + p = xdr_encode_hyper(p, OFFSET_MAX); /* offset of next entry */ | |
| 3499 | 3499 | p = xdr_encode_array(p, name, namlen); /* name length & name */ |
| 3500 | 3500 | |
| 3501 | 3501 | nfserr = nfsd4_encode_dirent_fattr(xdr, cd, name, namlen); |
| @@ -3986,10 +3986,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, · 484 unmodified lines | ||
| 3986 | 3986 | } |
| 3987 | 3987 | xdr_commit_encode(xdr); |
| 3988 | 3988 | |
| 3989 | − maxcount = svc_max_payload(resp->rqstp); | |
| 3990 | − maxcount = min_t(unsigned long, maxcount, | |
| 3989 | + maxcount = min_t(unsigned long, read->rd_length, | |
| 3991 | 3990 | (xdr->buf->buflen - xdr->buf->len)); |
| 3992 | − maxcount = min_t(unsigned long, maxcount, read->rd_length); | |
| 3993 | 3991 | |
| 3994 | 3992 | if (file->f_op->splice_read && |
| 3995 | 3993 | test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) |
| @@ -4826,10 +4824,8 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, · 830 unmodified lines | ||
| 4826 | 4824 | return nfserr_resource; |
| 4827 | 4825 | xdr_commit_encode(xdr); |
| 4828 | 4826 | |
| 4829 | − maxcount = svc_max_payload(resp->rqstp); | |
| 4830 | − maxcount = min_t(unsigned long, maxcount, | |
| 4827 | + maxcount = min_t(unsigned long, read->rd_length, | |
| 4831 | 4828 | (xdr->buf->buflen - xdr->buf->len)); |
| 4832 | − maxcount = min_t(unsigned long, maxcount, read->rd_length); | |
| 4833 | 4829 | count = maxcount; |
| 4834 | 4830 | |
| 4835 | 4831 | eof = read->rd_offset >= i_size_read(file_inode(file)); |
| @@ -306,14 +306,14 @@ TRACE_EVENT(nfsd_export_update, · 305 unmodified lines | ||
| 306 | 306 | DECLARE_EVENT_CLASS(nfsd_io_class, |
| 307 | 307 | TP_PROTO(struct svc_rqst *rqstp, |
| 308 | 308 | struct svc_fh *fhp, |
| 309 | − loff_t offset, | |
| 310 | − unsigned long len), | |
| 309 | + u64 offset, | |
| 310 | + u32 len), | |
| 311 | 311 | TP_ARGS(rqstp, fhp, offset, len), |
| 312 | 312 | TP_STRUCT__entry( |
| 313 | 313 | __field(u32, xid) |
| 314 | 314 | __field(u32, fh_hash) |
| 315 | − __field(loff_t, offset) | |
| 316 | − __field(unsigned long, len) | |
| 315 | + __field(u64, offset) | |
| 316 | + __field(u32, len) | |
| 317 | 317 | ), |
| 318 | 318 | TP_fast_assign( |
| 319 | 319 | __entry->xid = be32_to_cpu(rqstp->rq_xid); |
| @@ -321,7 +321,7 @@ DECLARE_EVENT_CLASS(nfsd_io_class, · 1 unmodified line | ||
| 321 | 321 | __entry->offset = offset; |
| 322 | 322 | __entry->len = len; |
| 323 | 323 | ), |
| 324 | − TP_printk("xid=0x%08x fh_hash=0x%08x offset=%lld len=%lu", | |
| 324 | + TP_printk("xid=0x%08x fh_hash=0x%08x offset=%llu len=%u", | |
| 325 | 325 | __entry->xid, __entry->fh_hash, |
| 326 | 326 | __entry->offset, __entry->len) |
| 327 | 327 | ) |
| @@ -330,8 +330,8 @@ DECLARE_EVENT_CLASS(nfsd_io_class, · 2 unmodified lines | ||
| 330 | 330 | DEFINE_EVENT(nfsd_io_class, nfsd_##name, \ |
| 331 | 331 | TP_PROTO(struct svc_rqst *rqstp, \ |
| 332 | 332 | struct svc_fh *fhp, \ |
| 333 | − loff_t offset, \ | |
| 334 | − unsigned long len), \ | |
| 333 | + u64 offset, \ | |
| 334 | + u32 len), \ | |
| 335 | 335 | TP_ARGS(rqstp, fhp, offset, len)) |
| 336 | 336 | |
| 337 | 337 | DEFINE_NFSD_IO_EVENT(read_start); |
| @@ -435,6 +435,10 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, · 434 unmodified lines | ||
| 435 | 435 | .ia_size = iap->ia_size, |
| 436 | 436 | }; |
| 437 | 437 | |
| 438 | + host_err = -EFBIG; | |
| 439 | + if (iap->ia_size < 0) | |
| 440 | + goto out_unlock; | |
| 441 | + | |
| 438 | 442 | host_err = notify_change(&init_user_ns, dentry, &size_attr, NULL); |
| 439 | 443 | if (host_err) |
| 440 | 444 | goto out_unlock; |
| @@ -1110,42 +1114,61 @@ out: · 669 unmodified lines | ||
| 1110 | 1114 | } |
| 1111 | 1115 | |
| 1112 | 1116 | #ifdef CONFIG_NFSD_V3 |
| 1113 | −/* | |
| 1114 | − * Commit all pending writes to stable storage. | |
| 1117 | +/** | |
| 1118 | + * nfsd_commit - Commit pending writes to stable storage | |
| 1119 | + * @rqstp: RPC request being processed | |
| 1120 | + * @fhp: NFS filehandle | |
| 1121 | + * @offset: raw offset from beginning of file | |
| 1122 | + * @count: raw count of bytes to sync | |
| 1123 | + * @verf: filled in with the server's current write verifier | |
| 1115 | 1124 | * |
| 1116 | − * Note: we only guarantee that data that lies within the range specified | |
| 1117 | − * by the 'offset' and 'count' parameters will be synced. | |
| 1125 | + * Note: we guarantee that data that lies within the range specified | |
| 1126 | + * by the 'offset' and 'count' parameters will be synced. The server | |
| 1127 | + * is permitted to sync data that lies outside this range at the | |
| 1128 | + * same time. | |
| 1118 | 1129 | * |
| 1119 | 1130 | * Unfortunately we cannot lock the file to make sure we return full WCC |
| 1120 | 1131 | * data to the client, as locking happens lower down in the filesystem. |
| 1132 | + * | |
| 1133 | + * Return values: | |
| 1134 | + * An nfsstat value in network byte order. | |
| 1121 | 1135 | */ |
| 1122 | 1136 | __be32 |
| 1123 | −nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, | |
| 1124 | − loff_t offset, unsigned long count, __be32 *verf) | |
| 1137 | +nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset, | |
| 1138 | + u32 count, __be32 *verf) | |
| 1125 | 1139 | { |
| 1140 | + u64 maxbytes; | |
| 1141 | + loff_t start, end; | |
| 1126 | 1142 | struct nfsd_net *nn; |
| 1127 | 1143 | struct nfsd_file *nf; |
| 1128 | − loff_t end = LLONG_MAX; | |
| 1129 | − __be32 err = nfserr_inval; | |
| 1130 | − | |
| 1131 | − if (offset < 0) | |
| 1132 | − goto out; | |
| 1133 | − if (count != 0) { | |
| 1134 | − end = offset + (loff_t)count - 1; | |
| 1135 | − if (end < offset) | |
| 1136 | − goto out; | |
| 1137 | − } | |
| 1144 | + __be32 err; | |
| 1138 | 1145 | |
| 1139 | 1146 | err = nfsd_file_acquire(rqstp, fhp, |
| 1140 | 1147 | NFSD_MAY_WRITE|NFSD_MAY_NOT_BREAK_LEASE, &nf); |
| 1141 | 1148 | if (err) |
| 1142 | 1149 | goto out; |
| 1150 | + | |
| 1151 | + /* | |
| 1152 | + * Convert the client-provided (offset, count) range to a | |
| 1153 | + * (start, end) range. If the client-provided range falls | |
| 1154 | + * outside the maximum file size of the underlying FS, | |
| 1155 | + * clamp the sync range appropriately. | |
| 1156 | + */ | |
| 1157 | + start = 0; | |
| 1158 | + end = LLONG_MAX; | |
| 1159 | + maxbytes = (u64)fhp->fh_dentry->d_sb->s_maxbytes; | |
| 1160 | + if (offset < maxbytes) { | |
| 1161 | + start = offset; | |
| 1162 | + if (count && (offset + count - 1 < maxbytes)) | |
| 1163 | + end = offset + count - 1; | |
| 1164 | + } | |
| 1165 | + | |
| 1143 | 1166 | nn = net_generic(nf->nf_net, nfsd_net_id); |
| 1144 | 1167 | if (EX_ISSYNC(fhp->fh_export)) { |
| 1145 | 1168 | errseq_t since = READ_ONCE(nf->nf_file->f_wb_err); |
| 1146 | 1169 | int err2; |
| 1147 | 1170 | |
| 1148 | − err2 = vfs_fsync_range(nf->nf_file, offset, end, 0); | |
| 1171 | + err2 = vfs_fsync_range(nf->nf_file, start, end, 0); | |
| 1149 | 1172 | switch (err2) { |
| 1150 | 1173 | case 0: |
| 1151 | 1174 | nfsd_copy_write_verifier(verf, nn); |
| @@ -74,8 +74,8 @@ __be32 do_nfsd_create(struct svc_rqst *, struct svc_fh *, · 73 unmodified lines | ||
| 74 | 74 | char *name, int len, struct iattr *attrs, |
| 75 | 75 | struct svc_fh *res, int createmode, |
| 76 | 76 | u32 *verifier, bool *truncp, bool *created); |
| 77 | −__be32 nfsd_commit(struct svc_rqst *, struct svc_fh *, | |
| 78 | − loff_t, unsigned long, __be32 *verf); | |
| 77 | +__be32 nfsd_commit(struct svc_rqst *rqst, struct svc_fh *fhp, | |
| 78 | + u64 offset, u32 count, __be32 *verf); | |
| 79 | 79 | #endif /* CONFIG_NFSD_V3 */ |
| 80 | 80 | #ifdef CONFIG_NFSD_V4 |
| 81 | 81 | __be32 nfsd_getxattr(struct svc_rqst *rqstp, struct svc_fh *fhp, |
| @@ -690,9 +690,14 @@ int dquot_quota_sync(struct super_block *sb, int type) · 689 unmodified lines | ||
| 690 | 690 | /* This is not very clever (and fast) but currently I don't know about |
| 691 | 691 | * any other simple way of getting quota data to disk and we must get |
| 692 | 692 | * them there for userspace to be visible... */ |
| 693 | − if (sb->s_op->sync_fs) | |
| 694 | − sb->s_op->sync_fs(sb, 1); | |
| 695 | − sync_blockdev(sb->s_bdev); | |
| 693 | + if (sb->s_op->sync_fs) { | |
| 694 | + ret = sb->s_op->sync_fs(sb, 1); | |
| 695 | + if (ret) | |
| 696 | + return ret; | |
| 697 | + } | |
| 698 | + ret = sync_blockdev(sb->s_bdev); | |
| 699 | + if (ret) | |
| 700 | + return ret; | |
| 696 | 701 | |
| 697 | 702 | /* |
| 698 | 703 | * Now when everything is written we can discard the pagecache so |
| @@ -1616,11 +1616,9 @@ static void lockdep_sb_freeze_acquire(struct super_block *sb) · 1615 unmodified lines | ||
| 1616 | 1616 | percpu_rwsem_acquire(sb->s_writers.rw_sem + level, 0, _THIS_IP_); |
| 1617 | 1617 | } |
| 1618 | 1618 | |
| 1619 | −static void sb_freeze_unlock(struct super_block *sb) | |
| 1619 | +static void sb_freeze_unlock(struct super_block *sb, int level) | |
| 1620 | 1620 | { |
| 1621 | − int level; | |
| 1622 | − | |
| 1623 | − for (level = SB_FREEZE_LEVELS - 1; level >= 0; level--) | |
| 1621 | + for (level--; level >= 0; level--) | |
| 1624 | 1622 | percpu_up_write(sb->s_writers.rw_sem + level); |
| 1625 | 1623 | } |
| 1626 | 1624 | |
| @@ -1691,7 +1689,14 @@ int freeze_super(struct super_block *sb) · 64 unmodified lines | ||
| 1691 | 1689 | sb_wait_write(sb, SB_FREEZE_PAGEFAULT); |
| 1692 | 1690 | |
| 1693 | 1691 | /* All writers are done so after syncing there won't be dirty data */ |
| 1694 | − sync_filesystem(sb); | |
| 1692 | + ret = sync_filesystem(sb); | |
| 1693 | + if (ret) { | |
| 1694 | + sb->s_writers.frozen = SB_UNFROZEN; | |
| 1695 | + sb_freeze_unlock(sb, SB_FREEZE_PAGEFAULT); | |
| 1696 | + wake_up(&sb->s_writers.wait_unfrozen); | |
| 1697 | + deactivate_locked_super(sb); | |
| 1698 | + return ret; | |
| 1699 | + } | |
| 1695 | 1700 | |
| 1696 | 1701 | /* Now wait for internal filesystem counter */ |
| 1697 | 1702 | sb->s_writers.frozen = SB_FREEZE_FS; |
| @@ -1703,7 +1708,7 @@ int freeze_super(struct super_block *sb) · 5 unmodified lines | ||
| 1703 | 1708 | printk(KERN_ERR |
| 1704 | 1709 | "VFS:Filesystem freeze failed\n"); |
| 1705 | 1710 | sb->s_writers.frozen = SB_UNFROZEN; |
| 1706 | − sb_freeze_unlock(sb); | |
| 1711 | + sb_freeze_unlock(sb, SB_FREEZE_FS); | |
| 1707 | 1712 | wake_up(&sb->s_writers.wait_unfrozen); |
| 1708 | 1713 | deactivate_locked_super(sb); |
| 1709 | 1714 | return ret; |
| @@ -1748,7 +1753,7 @@ static int thaw_super_locked(struct super_block *sb) · 38 unmodified lines | ||
| 1748 | 1753 | } |
| 1749 | 1754 | |
| 1750 | 1755 | sb->s_writers.frozen = SB_UNFROZEN; |
| 1751 | − sb_freeze_unlock(sb); | |
| 1756 | + sb_freeze_unlock(sb, SB_FREEZE_FS); | |
| 1752 | 1757 | out: |
| 1753 | 1758 | wake_up(&sb->s_writers.wait_unfrozen); |
| 1754 | 1759 | deactivate_locked_super(sb); |
| @@ -29,7 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | */ |
| 30 | 30 | int sync_filesystem(struct super_block *sb) |
| 31 | 31 | { |
| 32 | − int ret; | |
| 32 | + int ret = 0; | |
| 33 | 33 | |
| 34 | 34 | /* |
| 35 | 35 | * We need to be protected against the filesystem going from |
| @@ -52,15 +52,21 @@ int sync_filesystem(struct super_block *sb) · 16 unmodified lines | ||
| 52 | 52 | * at a time. |
| 53 | 53 | */ |
| 54 | 54 | writeback_inodes_sb(sb, WB_REASON_SYNC); |
| 55 | − if (sb->s_op->sync_fs) | |
| 56 | − sb->s_op->sync_fs(sb, 0); | |
| 55 | + if (sb->s_op->sync_fs) { | |
| 56 | + ret = sb->s_op->sync_fs(sb, 0); | |
| 57 | + if (ret) | |
| 58 | + return ret; | |
| 59 | + } | |
| 57 | 60 | ret = sync_blockdev_nowait(sb->s_bdev); |
| 58 | − if (ret < 0) | |
| 61 | + if (ret) | |
| 59 | 62 | return ret; |
| 60 | 63 | |
| 61 | 64 | sync_inodes_sb(sb); |
| 62 | − if (sb->s_op->sync_fs) | |
| 63 | − sb->s_op->sync_fs(sb, 1); | |
| 65 | + if (sb->s_op->sync_fs) { | |
| 66 | + ret = sb->s_op->sync_fs(sb, 1); | |
| 67 | + if (ret) | |
| 68 | + return ret; | |
| 69 | + } | |
| 64 | 70 | return sync_blockdev(sb->s_bdev); |
| 65 | 71 | } |
| 66 | 72 | EXPORT_SYMBOL(sync_filesystem); |
| @@ -136,7 +136,20 @@ done: · 135 unmodified lines | ||
| 136 | 136 | memalloc_nofs_restore(nofs_flag); |
| 137 | 137 | } |
| 138 | 138 | |
| 139 | −/* Finish all pending io completions. */ | |
| 139 | +/* | |
| 140 | + * Finish all pending IO completions that require transactional modifications. | |
| 141 | + * | |
| 142 | + * We try to merge physical and logically contiguous ioends before completion to | |
| 143 | + * minimise the number of transactions we need to perform during IO completion. | |
| 144 | + * Both unwritten extent conversion and COW remapping need to iterate and modify | |
| 145 | + * one physical extent at a time, so we gain nothing by merging physically | |
| 146 | + * discontiguous extents here. | |
| 147 | + * | |
| 148 | + * The ioend chain length that we can be processing here is largely unbound in | |
| 149 | + * length and we may have to perform significant amounts of work on each ioend | |
| 150 | + * to complete it. Hence we have to be careful about holding the CPU for too | |
| 151 | + * long in this loop. | |
| 152 | + */ | |
| 140 | 153 | void |
| 141 | 154 | xfs_end_io( |
| 142 | 155 | struct work_struct *work) |
| @@ -157,6 +170,7 @@ xfs_end_io( · 14 unmodified lines | ||
| 157 | 170 | list_del_init(&ioend->io_list); |
| 158 | 171 | iomap_ioend_try_merge(ioend, &tmp); |
| 159 | 172 | xfs_end_ioend(ioend); |
| 173 | + cond_resched(); | |
| 160 | 174 | } |
| 161 | 175 | } |
| 162 | 176 | |
| @@ -850,9 +850,6 @@ xfs_alloc_file_space( · 849 unmodified lines | ||
| 850 | 850 | rblocks = 0; |
| 851 | 851 | } |
| 852 | 852 | |
| 853 | − /* | |
| 854 | − * Allocate and setup the transaction. | |
| 855 | − */ | |
| 856 | 853 | error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, |
| 857 | 854 | dblocks, rblocks, false, &tp); |
| 858 | 855 | if (error) |
| @@ -869,9 +866,9 @@ xfs_alloc_file_space( · 10 unmodified lines | ||
| 869 | 866 | if (error) |
| 870 | 867 | goto error; |
| 871 | 868 | |
| 872 | − /* | |
| 873 | − * Complete the transaction | |
| 874 | − */ | |
| 869 | + ip->i_diflags |= XFS_DIFLAG_PREALLOC; | |
| 870 | + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | |
| 871 | + | |
| 875 | 872 | error = xfs_trans_commit(tp); |
| 876 | 873 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 877 | 874 | if (error) |
| @@ -66,40 +66,6 @@ xfs_is_falloc_aligned( · 65 unmodified lines | ||
| 66 | 66 | return !((pos | len) & mask); |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | −int | |
| 70 | −xfs_update_prealloc_flags( | |
| 71 | − struct xfs_inode *ip, | |
| 72 | − enum xfs_prealloc_flags flags) | |
| 73 | −{ | |
| 74 | − struct xfs_trans *tp; | |
| 75 | − int error; | |
| 76 | − | |
| 77 | − error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_writeid, | |
| 78 | − 0, 0, 0, &tp); | |
| 79 | − if (error) | |
| 80 | − return error; | |
| 81 | − | |
| 82 | − xfs_ilock(ip, XFS_ILOCK_EXCL); | |
| 83 | − xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | |
| 84 | − | |
| 85 | − if (!(flags & XFS_PREALLOC_INVISIBLE)) { | |
| 86 | − VFS_I(ip)->i_mode &= ~S_ISUID; | |
| 87 | − if (VFS_I(ip)->i_mode & S_IXGRP) | |
| 88 | − VFS_I(ip)->i_mode &= ~S_ISGID; | |
| 89 | − xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | |
| 90 | − } | |
| 91 | − | |
| 92 | − if (flags & XFS_PREALLOC_SET) | |
| 93 | − ip->i_diflags |= XFS_DIFLAG_PREALLOC; | |
| 94 | − if (flags & XFS_PREALLOC_CLEAR) | |
| 95 | − ip->i_diflags &= ~XFS_DIFLAG_PREALLOC; | |
| 96 | − | |
| 97 | − xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | |
| 98 | − if (flags & XFS_PREALLOC_SYNC) | |
| 99 | − xfs_trans_set_sync(tp); | |
| 100 | − return xfs_trans_commit(tp); | |
| 101 | −} | |
| 102 | − | |
| 103 | 69 | /* |
| 104 | 70 | * Fsync operations on directories are much simpler than on regular files, |
| 105 | 71 | * as there is no file data to flush, and thus also no need for explicit |
| @@ -895,6 +861,21 @@ xfs_break_layouts( · 789 unmodified lines | ||
| 895 | 861 | return error; |
| 896 | 862 | } |
| 897 | 863 | |
| 864 | +/* Does this file, inode, or mount want synchronous writes? */ | |
| 865 | +static inline bool xfs_file_sync_writes(struct file *filp) | |
| 866 | +{ | |
| 867 | + struct xfs_inode *ip = XFS_I(file_inode(filp)); | |
| 868 | + | |
| 869 | + if (xfs_has_wsync(ip->i_mount)) | |
| 870 | + return true; | |
| 871 | + if (filp->f_flags & (__O_SYNC | O_DSYNC)) | |
| 872 | + return true; | |
| 873 | + if (IS_SYNC(file_inode(filp))) | |
| 874 | + return true; | |
| 875 | + | |
| 876 | + return false; | |
| 877 | +} | |
| 878 | + | |
| 898 | 879 | #define XFS_FALLOC_FL_SUPPORTED \ |
| 899 | 880 | (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \ |
| 900 | 881 | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \ |
| @@ -910,7 +891,6 @@ xfs_file_fallocate( · 9 unmodified lines | ||
| 910 | 891 | struct inode *inode = file_inode(file); |
| 911 | 892 | struct xfs_inode *ip = XFS_I(inode); |
| 912 | 893 | long error; |
| 913 | − enum xfs_prealloc_flags flags = 0; | |
| 914 | 894 | uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; |
| 915 | 895 | loff_t new_size = 0; |
| 916 | 896 | bool do_file_insert = false; |
| @@ -955,6 +935,10 @@ xfs_file_fallocate( · 38 unmodified lines | ||
| 955 | 935 | goto out_unlock; |
| 956 | 936 | } |
| 957 | 937 | |
| 938 | + error = file_modified(file); | |
| 939 | + if (error) | |
| 940 | + goto out_unlock; | |
| 941 | + | |
| 958 | 942 | if (mode & FALLOC_FL_PUNCH_HOLE) { |
| 959 | 943 | error = xfs_free_file_space(ip, offset, len); |
| 960 | 944 | if (error) |
| @@ -1004,8 +988,6 @@ xfs_file_fallocate( · 43 unmodified lines | ||
| 1004 | 988 | } |
| 1005 | 989 | do_file_insert = true; |
| 1006 | 990 | } else { |
| 1007 | − flags |= XFS_PREALLOC_SET; | |
| 1008 | − | |
| 1009 | 991 | if (!(mode & FALLOC_FL_KEEP_SIZE) && |
| 1010 | 992 | offset + len > i_size_read(inode)) { |
| 1011 | 993 | new_size = offset + len; |
| @@ -1057,13 +1039,6 @@ xfs_file_fallocate( · 45 unmodified lines | ||
| 1057 | 1039 | } |
| 1058 | 1040 | } |
| 1059 | 1041 | |
| 1060 | − if (file->f_flags & O_DSYNC) | |
| 1061 | − flags |= XFS_PREALLOC_SYNC; | |
| 1062 | − | |
| 1063 | − error = xfs_update_prealloc_flags(ip, flags); | |
| 1064 | − if (error) | |
| 1065 | − goto out_unlock; | |
| 1066 | − | |
| 1067 | 1042 | /* Change file size if needed */ |
| 1068 | 1043 | if (new_size) { |
| 1069 | 1044 | struct iattr iattr; |
| @@ -1082,8 +1057,14 @@ xfs_file_fallocate( · 12 unmodified lines | ||
| 1082 | 1057 | * leave shifted extents past EOF and hence losing access to |
| 1083 | 1058 | * the data that is contained within them. |
| 1084 | 1059 | */ |
| 1085 | − if (do_file_insert) | |
| 1060 | + if (do_file_insert) { | |
| 1086 | 1061 | error = xfs_insert_file_space(ip, offset, len); |
| 1062 | + if (error) | |
| 1063 | + goto out_unlock; | |
| 1064 | + } | |
| 1065 | + | |
| 1066 | + if (xfs_file_sync_writes(file)) | |
| 1067 | + error = xfs_log_force_inode(ip); | |
| 1087 | 1068 | |
| 1088 | 1069 | out_unlock: |
| 1089 | 1070 | xfs_iunlock(ip, iolock); |
| @@ -1115,21 +1096,6 @@ xfs_file_fadvise( · 25 unmodified lines | ||
| 1115 | 1096 | return ret; |
| 1116 | 1097 | } |
| 1117 | 1098 | |
| 1118 | −/* Does this file, inode, or mount want synchronous writes? */ | |
| 1119 | −static inline bool xfs_file_sync_writes(struct file *filp) | |
| 1120 | −{ | |
| 1121 | − struct xfs_inode *ip = XFS_I(file_inode(filp)); | |
| 1122 | − | |
| 1123 | − if (xfs_has_wsync(ip->i_mount)) | |
| 1124 | − return true; | |
| 1125 | − if (filp->f_flags & (__O_SYNC | O_DSYNC)) | |
| 1126 | − return true; | |
| 1127 | − if (IS_SYNC(file_inode(filp))) | |
| 1128 | − return true; | |
| 1129 | − | |
| 1130 | − return false; | |
| 1131 | −} | |
| 1132 | − | |
| 1133 | 1099 | STATIC loff_t |
| 1134 | 1100 | xfs_file_remap_range( |
| 1135 | 1101 | struct file *file_in, |
| @@ -462,15 +462,6 @@ xfs_itruncate_extents( · 461 unmodified lines | ||
| 462 | 462 | } |
| 463 | 463 | |
| 464 | 464 | /* from xfs_file.c */ |
| 465 | −enum xfs_prealloc_flags { | |
| 466 | − XFS_PREALLOC_SET = (1 << 1), | |
| 467 | − XFS_PREALLOC_CLEAR = (1 << 2), | |
| 468 | − XFS_PREALLOC_SYNC = (1 << 3), | |
| 469 | − XFS_PREALLOC_INVISIBLE = (1 << 4), | |
| 470 | −}; | |
| 471 | − | |
| 472 | −int xfs_update_prealloc_flags(struct xfs_inode *ip, | |
| 473 | − enum xfs_prealloc_flags flags); | |
| 474 | 465 | int xfs_break_layouts(struct inode *inode, uint *iolock, |
| 475 | 466 | enum layout_break_reason reason); |
| 476 | 467 | |
| @@ -1464,7 +1464,7 @@ xfs_ioc_getbmap( · 1463 unmodified lines | ||
| 1464 | 1464 | |
| 1465 | 1465 | if (bmx.bmv_count < 2) |
| 1466 | 1466 | return -EINVAL; |
| 1467 | − if (bmx.bmv_count > ULONG_MAX / recsize) | |
| 1467 | + if (bmx.bmv_count >= INT_MAX / recsize) | |
| 1468 | 1468 | return -ENOMEM; |
| 1469 | 1469 | |
| 1470 | 1470 | buf = kvcalloc(bmx.bmv_count, sizeof(*buf), GFP_KERNEL); |
| @@ -70,6 +70,40 @@ xfs_fs_get_uuid( · 69 unmodified lines | ||
| 70 | 70 | return 0; |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | +/* | |
| 74 | + * We cannot use file based VFS helpers such as file_modified() to update | |
| 75 | + * inode state as we modify the data/metadata in the inode here. Hence we have | |
| 76 | + * to open code the timestamp updates and SUID/SGID stripping. We also need | |
| 77 | + * to set the inode prealloc flag to ensure that the extents we allocate are not | |
| 78 | + * removed if the inode is reclaimed from memory before xfs_fs_block_commit() | |
| 79 | + * is from the client to indicate that data has been written and the file size | |
| 80 | + * can be extended. | |
| 81 | + */ | |
| 82 | +static int | |
| 83 | +xfs_fs_map_update_inode( | |
| 84 | + struct xfs_inode *ip) | |
| 85 | +{ | |
| 86 | + struct xfs_trans *tp; | |
| 87 | + int error; | |
| 88 | + | |
| 89 | + error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_writeid, | |
| 90 | + 0, 0, 0, &tp); | |
| 91 | + if (error) | |
| 92 | + return error; | |
| 93 | + | |
| 94 | + xfs_ilock(ip, XFS_ILOCK_EXCL); | |
| 95 | + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | |
| 96 | + | |
| 97 | + VFS_I(ip)->i_mode &= ~S_ISUID; | |
| 98 | + if (VFS_I(ip)->i_mode & S_IXGRP) | |
| 99 | + VFS_I(ip)->i_mode &= ~S_ISGID; | |
| 100 | + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | |
| 101 | + ip->i_diflags |= XFS_DIFLAG_PREALLOC; | |
| 102 | + | |
| 103 | + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | |
| 104 | + return xfs_trans_commit(tp); | |
| 105 | +} | |
| 106 | + | |
| 73 | 107 | /* |
| 74 | 108 | * Get a layout for the pNFS client. |
| 75 | 109 | */ |
| @@ -164,10 +198,12 @@ xfs_fs_map_blocks( · 88 unmodified lines | ||
| 164 | 198 | * that the blocks allocated and handed out to the client are |
| 165 | 199 | * guaranteed to be present even after a server crash. |
| 166 | 200 | */ |
| 167 | − error = xfs_update_prealloc_flags(ip, | |
| 168 | − XFS_PREALLOC_SET | XFS_PREALLOC_SYNC); | |
| 201 | + error = xfs_fs_map_update_inode(ip); | |
| 202 | + if (!error) | |
| 203 | + error = xfs_log_force_inode(ip); | |
| 169 | 204 | if (error) |
| 170 | 205 | goto out_unlock; |
| 206 | + | |
| 171 | 207 | } else { |
| 172 | 208 | xfs_iunlock(ip, lock_flags); |
| 173 | 209 | } |
| @@ -255,7 +291,7 @@ xfs_fs_commit_blocks( · 81 unmodified lines | ||
| 255 | 291 | length = end - start; |
| 256 | 292 | if (!length) |
| 257 | 293 | continue; |
| 258 | − | |
| 294 | + | |
| 259 | 295 | /* |
| 260 | 296 | * Make sure reads through the pagecache see the new data. |
| 261 | 297 | */ |
| @@ -735,6 +735,7 @@ xfs_fs_sync_fs( · 734 unmodified lines | ||
| 735 | 735 | int wait) |
| 736 | 736 | { |
| 737 | 737 | struct xfs_mount *mp = XFS_M(sb); |
| 738 | + int error; | |
| 738 | 739 | |
| 739 | 740 | trace_xfs_fs_sync_fs(mp, __return_address); |
| 740 | 741 | |
| @@ -744,7 +745,10 @@ xfs_fs_sync_fs( · 3 unmodified lines | ||
| 744 | 745 | if (!wait) |
| 745 | 746 | return 0; |
| 746 | 747 | |
| 747 | − xfs_log_force(mp, XFS_LOG_SYNC); | |
| 748 | + error = xfs_log_force(mp, XFS_LOG_SYNC); | |
| 749 | + if (error) | |
| 750 | + return error; | |
| 751 | + | |
| 748 | 752 | if (laptop_mode) { |
| 749 | 753 | /* |
| 750 | 754 | * The disk must be active because we're syncing. |
| @@ -24,14 +24,11 @@ static inline void blake2s_set_lastblock(struct blake2s_state *state) · 23 unmodified lines | ||
| 24 | 24 | state->f[0] = -1; |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | −typedef void (*blake2s_compress_t)(struct blake2s_state *state, | |
| 28 | − const u8 *block, size_t nblocks, u32 inc); | |
| 29 | − | |
| 30 | 27 | /* Helper functions for BLAKE2s shared by the library and shash APIs */ |
| 31 | 28 | |
| 32 | −static inline void __blake2s_update(struct blake2s_state *state, | |
| 33 | − const u8 *in, size_t inlen, | |
| 34 | − blake2s_compress_t compress) | |
| 29 | +static __always_inline void | |
| 30 | +__blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen, | |
| 31 | + bool force_generic) | |
| 35 | 32 | { |
| 36 | 33 | const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen; |
| 37 | 34 | |
| @@ -39,7 +36,12 @@ static inline void __blake2s_update(struct blake2s_state *state, · 1 unmodified line | ||
| 39 | 36 | return; |
| 40 | 37 | if (inlen > fill) { |
| 41 | 38 | memcpy(state->buf + state->buflen, in, fill); |
| 42 | − (*compress)(state, state->buf, 1, BLAKE2S_BLOCK_SIZE); | |
| 39 | + if (force_generic) | |
| 40 | + blake2s_compress_generic(state, state->buf, 1, | |
| 41 | + BLAKE2S_BLOCK_SIZE); | |
| 42 | + else | |
| 43 | + blake2s_compress(state, state->buf, 1, | |
| 44 | + BLAKE2S_BLOCK_SIZE); | |
| 43 | 45 | state->buflen = 0; |
| 44 | 46 | in += fill; |
| 45 | 47 | inlen -= fill; |
| @@ -47,7 +49,12 @@ static inline void __blake2s_update(struct blake2s_state *state, · 1 unmodified line | ||
| 47 | 49 | if (inlen > BLAKE2S_BLOCK_SIZE) { |
| 48 | 50 | const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE); |
| 49 | 51 | /* Hash one less (full) block than strictly possible */ |
| 50 | − (*compress)(state, in, nblocks - 1, BLAKE2S_BLOCK_SIZE); | |
| 52 | + if (force_generic) | |
| 53 | + blake2s_compress_generic(state, in, nblocks - 1, | |
| 54 | + BLAKE2S_BLOCK_SIZE); | |
| 55 | + else | |
| 56 | + blake2s_compress(state, in, nblocks - 1, | |
| 57 | + BLAKE2S_BLOCK_SIZE); | |
| 51 | 58 | in += BLAKE2S_BLOCK_SIZE * (nblocks - 1); |
| 52 | 59 | inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1); |
| 53 | 60 | } |
| @@ -55,13 +62,16 @@ static inline void __blake2s_update(struct blake2s_state *state, · 1 unmodified line | ||
| 55 | 62 | state->buflen += inlen; |
| 56 | 63 | } |
| 57 | 64 | |
| 58 | −static inline void __blake2s_final(struct blake2s_state *state, u8 *out, | |
| 59 | − blake2s_compress_t compress) | |
| 65 | +static __always_inline void | |
| 66 | +__blake2s_final(struct blake2s_state *state, u8 *out, bool force_generic) | |
| 60 | 67 | { |
| 61 | 68 | blake2s_set_lastblock(state); |
| 62 | 69 | memset(state->buf + state->buflen, 0, |
| 63 | 70 | BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */ |
| 64 | − (*compress)(state, state->buf, 1, state->buflen); | |
| 71 | + if (force_generic) | |
| 72 | + blake2s_compress_generic(state, state->buf, 1, state->buflen); | |
| 73 | + else | |
| 74 | + blake2s_compress(state, state->buf, 1, state->buflen); | |
| 65 | 75 | cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); |
| 66 | 76 | memcpy(out, state->h, state->outlen); |
| 67 | 77 | } |
| @@ -99,20 +109,20 @@ static inline int crypto_blake2s_init(struct shash_desc *desc) · 31 unmodified lines | ||
| 99 | 109 | |
| 100 | 110 | static inline int crypto_blake2s_update(struct shash_desc *desc, |
| 101 | 111 | const u8 *in, unsigned int inlen, |
| 102 | − blake2s_compress_t compress) | |
| 112 | + bool force_generic) | |
| 103 | 113 | { |
| 104 | 114 | struct blake2s_state *state = shash_desc_ctx(desc); |
| 105 | 115 | |
| 106 | − __blake2s_update(state, in, inlen, compress); | |
| 116 | + __blake2s_update(state, in, inlen, force_generic); | |
| 107 | 117 | return 0; |
| 108 | 118 | } |
| 109 | 119 | |
| 110 | 120 | static inline int crypto_blake2s_final(struct shash_desc *desc, u8 *out, |
| 111 | − blake2s_compress_t compress) | |
| 121 | + bool force_generic) | |
| 112 | 122 | { |
| 113 | 123 | struct blake2s_state *state = shash_desc_ctx(desc); |
| 114 | 124 | |
| 115 | − __blake2s_final(state, out, compress); | |
| 125 | + __blake2s_final(state, out, force_generic); | |
| 116 | 126 | return 0; |
| 117 | 127 | } |
| 118 | 128 | |
| @@ -324,12 +324,12 @@ enum { · 323 unmodified lines | ||
| 324 | 324 | ATA_LOG_NCQ_NON_DATA = 0x12, |
| 325 | 325 | ATA_LOG_NCQ_SEND_RECV = 0x13, |
| 326 | 326 | ATA_LOG_IDENTIFY_DEVICE = 0x30, |
| 327 | + ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47, | |
| 327 | 328 | |
| 328 | 329 | /* Identify device log pages: */ |
| 329 | 330 | ATA_LOG_SECURITY = 0x06, |
| 330 | 331 | ATA_LOG_SATA_SETTINGS = 0x08, |
| 331 | 332 | ATA_LOG_ZONED_INFORMATION = 0x09, |
| 332 | − ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47, | |
| 333 | 333 | |
| 334 | 334 | /* Identify device SATA settings log:*/ |
| 335 | 335 | ATA_LOG_DEVSLP_OFFSET = 0x30, |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | #define CEPH_OPT_TCP_NODELAY (1<<4) /* TCP_NODELAY on TCP sockets */ |
| 36 | 36 | #define CEPH_OPT_NOMSGSIGN (1<<5) /* don't sign msgs (msgr1) */ |
| 37 | 37 | #define CEPH_OPT_ABORT_ON_FULL (1<<6) /* abort w/ ENOSPC when full */ |
| 38 | +#define CEPH_OPT_RXBOUNCE (1<<7) /* double-buffer read data */ | |
| 38 | 39 | |
| 39 | 40 | #define CEPH_OPT_DEFAULT (CEPH_OPT_TCP_NODELAY) |
| 40 | 41 | |
| @@ -383,6 +383,10 @@ struct ceph_connection_v2_info { · 382 unmodified lines | ||
| 383 | 383 | struct ceph_gcm_nonce in_gcm_nonce; |
| 384 | 384 | struct ceph_gcm_nonce out_gcm_nonce; |
| 385 | 385 | |
| 386 | + struct page **in_enc_pages; | |
| 387 | + int in_enc_page_cnt; | |
| 388 | + int in_enc_resid; | |
| 389 | + int in_enc_i; | |
| 386 | 390 | struct page **out_enc_pages; |
| 387 | 391 | int out_enc_page_cnt; |
| 388 | 392 | int out_enc_resid; |
| @@ -457,6 +461,7 @@ struct ceph_connection { · 68 unmodified lines | ||
| 457 | 461 | struct ceph_msg *out_msg; /* sending message (== tail of |
| 458 | 462 | out_sent) */ |
| 459 | 463 | |
| 464 | + struct page *bounce_page; | |
| 460 | 465 | u32 in_front_crc, in_middle_crc, in_data_crc; /* calculated crc */ |
| 461 | 466 | |
| 462 | 467 | struct timespec64 last_keepalive_ack; /* keepalive2 ack stamp */ |
| @@ -262,7 +262,7 @@ struct fb_ops { · 261 unmodified lines | ||
| 262 | 262 | |
| 263 | 263 | /* Draws a rectangle */ |
| 264 | 264 | void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); |
| 265 | − /* Copy data from area to another. Obsolete. */ | |
| 265 | + /* Copy data from area to another */ | |
| 266 | 266 | void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); |
| 267 | 267 | /* Draws a image to the display */ |
| 268 | 268 | void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); |
| @@ -263,9 +263,11 @@ struct iomap_ioend { · 262 unmodified lines | ||
| 263 | 263 | struct list_head io_list; /* next ioend in chain */ |
| 264 | 264 | u16 io_type; |
| 265 | 265 | u16 io_flags; /* IOMAP_F_* */ |
| 266 | + u32 io_folios; /* folios added to ioend */ | |
| 266 | 267 | struct inode *io_inode; /* file being written to */ |
| 267 | 268 | size_t io_size; /* size of the extent */ |
| 268 | 269 | loff_t io_offset; /* offset in the file */ |
| 270 | + sector_t io_sector; /* start sector of ioend */ | |
| 269 | 271 | struct bio *io_bio; /* bio being built */ |
| 270 | 272 | struct bio io_inline_bio; /* MUST BE LAST! */ |
| 271 | 273 | }; |
| @@ -594,7 +594,7 @@ struct transaction_s · 593 unmodified lines | ||
| 594 | 594 | */ |
| 595 | 595 | unsigned long t_log_start; |
| 596 | 596 | |
| 597 | − /* | |
| 597 | + /* | |
| 598 | 598 | * Number of buffers on the t_buffers list [j_list_lock, no locks |
| 599 | 599 | * needed for jbd2 thread] |
| 600 | 600 | */ |
| @@ -1295,7 +1295,7 @@ struct journal_s · 694 unmodified lines | ||
| 1295 | 1295 | * Clean-up after fast commit or full commit. JBD2 calls this function |
| 1296 | 1296 | * after every commit operation. |
| 1297 | 1297 | */ |
| 1298 | − void (*j_fc_cleanup_callback)(struct journal_s *journal, int); | |
| 1298 | + void (*j_fc_cleanup_callback)(struct journal_s *journal, int full, tid_t tid); | |
| 1299 | 1299 | |
| 1300 | 1300 | /** |
| 1301 | 1301 | * @j_fc_replay_callback: |
| @@ -1419,9 +1419,7 @@ extern void jbd2_journal_unfile_buffer(journal_t *, struct journal_head *); · 117 unmodified lines | ||
| 1419 | 1419 | extern bool __jbd2_journal_refile_buffer(struct journal_head *); |
| 1420 | 1420 | extern void jbd2_journal_refile_buffer(journal_t *, struct journal_head *); |
| 1421 | 1421 | extern void __jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); |
| 1422 | −extern void __journal_free_buffer(struct journal_head *bh); | |
| 1423 | 1422 | extern void jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); |
| 1424 | −extern void __journal_clean_data_list(transaction_t *transaction); | |
| 1425 | 1423 | static inline void jbd2_file_log_bh(struct list_head *head, struct buffer_head *bh) |
| 1426 | 1424 | { |
| 1427 | 1425 | list_add_tail(&bh->b_assoc_buffers, head); |
| @@ -1486,9 +1484,6 @@ extern int jbd2_journal_write_metadata_buffer(transaction_t *transaction, · 58 unmodified lines | ||
| 1486 | 1484 | struct buffer_head **bh_out, |
| 1487 | 1485 | sector_t blocknr); |
| 1488 | 1486 | |
| 1489 | −/* Transaction locking */ | |
| 1490 | −extern void __wait_on_journal (journal_t *); | |
| 1491 | − | |
| 1492 | 1487 | /* Transaction cache support */ |
| 1493 | 1488 | extern void jbd2_journal_destroy_transaction_cache(void); |
| 1494 | 1489 | extern int __init jbd2_journal_init_transaction_cache(void); |
| @@ -1543,6 +1538,8 @@ extern int jbd2_journal_flush(journal_t *journal, unsigned int flags); · 48 unmodified lines | ||
| 1543 | 1538 | extern void jbd2_journal_lock_updates (journal_t *); |
| 1544 | 1539 | extern void jbd2_journal_unlock_updates (journal_t *); |
| 1545 | 1540 | |
| 1541 | +void jbd2_journal_wait_updates(journal_t *); | |
| 1542 | + | |
| 1546 | 1543 | extern journal_t * jbd2_journal_init_dev(struct block_device *bdev, |
| 1547 | 1544 | struct block_device *fs_dev, |
| 1548 | 1545 | unsigned long long start, int len, int bsize); |
| @@ -1774,8 +1771,6 @@ static inline unsigned long jbd2_log_space_left(journal_t *journal) · 225 unmodified lines | ||
| 1774 | 1771 | #define BJ_Reserved 4 /* Buffer is reserved for access by journal */ |
| 1775 | 1772 | #define BJ_Types 5 |
| 1776 | 1773 | |
| 1777 | −extern int jbd_blocks_per_page(struct inode *inode); | |
| 1778 | − | |
| 1779 | 1774 | /* JBD uses a CRC32 checksum */ |
| 1780 | 1775 | #define JBD_MAX_CHECKSUM_SIZE 4 |
| 1781 | 1776 | |
| @@ -29,7 +29,9 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/refcount.h> |
| 30 | 30 | #include <linux/nospec.h> |
| 31 | 31 | #include <linux/notifier.h> |
| 32 | +#include <linux/ftrace.h> | |
| 32 | 33 | #include <linux/hashtable.h> |
| 34 | +#include <linux/instrumentation.h> | |
| 33 | 35 | #include <linux/interval_tree.h> |
| 34 | 36 | #include <linux/rbtree.h> |
| 35 | 37 | #include <linux/xarray.h> |
| @@ -368,8 +370,11 @@ struct kvm_vcpu { · 332 unmodified lines | ||
| 368 | 370 | u64 last_used_slot_gen; |
| 369 | 371 | }; |
| 370 | 372 | |
| 371 | −/* must be called with irqs disabled */ | |
| 372 | −static __always_inline void guest_enter_irqoff(void) | |
| 373 | +/* | |
| 374 | + * Start accounting time towards a guest. | |
| 375 | + * Must be called before entering guest context. | |
| 376 | + */ | |
| 377 | +static __always_inline void guest_timing_enter_irqoff(void) | |
| 373 | 378 | { |
| 374 | 379 | /* |
| 375 | 380 | * This is running in ioctl context so its safe to assume that it's the |
| @@ -378,7 +383,18 @@ static __always_inline void guest_enter_irqoff(void) · 2 unmodified lines | ||
| 378 | 383 | instrumentation_begin(); |
| 379 | 384 | vtime_account_guest_enter(); |
| 380 | 385 | instrumentation_end(); |
| 386 | +} | |
| 381 | 387 | |
| 388 | +/* | |
| 389 | + * Enter guest context and enter an RCU extended quiescent state. | |
| 390 | + * | |
| 391 | + * Between guest_context_enter_irqoff() and guest_context_exit_irqoff() it is | |
| 392 | + * unsafe to use any code which may directly or indirectly use RCU, tracing | |
| 393 | + * (including IRQ flag tracing), or lockdep. All code in this period must be | |
| 394 | + * non-instrumentable. | |
| 395 | + */ | |
| 396 | +static __always_inline void guest_context_enter_irqoff(void) | |
| 397 | +{ | |
| 382 | 398 | /* |
| 383 | 399 | * KVM does not hold any references to rcu protected data when it |
| 384 | 400 | * switches CPU into a guest mode. In fact switching to a guest mode |
| @@ -394,16 +410,79 @@ static __always_inline void guest_enter_irqoff(void) · 9 unmodified lines | ||
| 394 | 410 | } |
| 395 | 411 | } |
| 396 | 412 | |
| 397 | −static __always_inline void guest_exit_irqoff(void) | |
| 413 | +/* | |
| 414 | + * Deprecated. Architectures should move to guest_timing_enter_irqoff() and | |
| 415 | + * guest_state_enter_irqoff(). | |
| 416 | + */ | |
| 417 | +static __always_inline void guest_enter_irqoff(void) | |
| 418 | +{ | |
| 419 | + guest_timing_enter_irqoff(); | |
| 420 | + guest_context_enter_irqoff(); | |
| 421 | +} | |
| 422 | + | |
| 423 | +/** | |
| 424 | + * guest_state_enter_irqoff - Fixup state when entering a guest | |
| 425 | + * | |
| 426 | + * Entry to a guest will enable interrupts, but the kernel state is interrupts | |
| 427 | + * disabled when this is invoked. Also tell RCU about it. | |
| 428 | + * | |
| 429 | + * 1) Trace interrupts on state | |
| 430 | + * 2) Invoke context tracking if enabled to adjust RCU state | |
| 431 | + * 3) Tell lockdep that interrupts are enabled | |
| 432 | + * | |
| 433 | + * Invoked from architecture specific code before entering a guest. | |
| 434 | + * Must be called with interrupts disabled and the caller must be | |
| 435 | + * non-instrumentable. | |
| 436 | + * The caller has to invoke guest_timing_enter_irqoff() before this. | |
| 437 | + * | |
| 438 | + * Note: this is analogous to exit_to_user_mode(). | |
| 439 | + */ | |
| 440 | +static __always_inline void guest_state_enter_irqoff(void) | |
| 441 | +{ | |
| 442 | + instrumentation_begin(); | |
| 443 | + trace_hardirqs_on_prepare(); | |
| 444 | + lockdep_hardirqs_on_prepare(CALLER_ADDR0); | |
| 445 | + instrumentation_end(); | |
| 446 | + | |
| 447 | + guest_context_enter_irqoff(); | |
| 448 | + lockdep_hardirqs_on(CALLER_ADDR0); | |
| 449 | +} | |
| 450 | + | |
| 451 | +/* | |
| 452 | + * Exit guest context and exit an RCU extended quiescent state. | |
| 453 | + * | |
| 454 | + * Between guest_context_enter_irqoff() and guest_context_exit_irqoff() it is | |
| 455 | + * unsafe to use any code which may directly or indirectly use RCU, tracing | |
| 456 | + * (including IRQ flag tracing), or lockdep. All code in this period must be | |
| 457 | + * non-instrumentable. | |
| 458 | + */ | |
| 459 | +static __always_inline void guest_context_exit_irqoff(void) | |
| 398 | 460 | { |
| 399 | 461 | context_tracking_guest_exit(); |
| 462 | +} | |
| 400 | 463 | |
| 464 | +/* | |
| 465 | + * Stop accounting time towards a guest. | |
| 466 | + * Must be called after exiting guest context. | |
| 467 | + */ | |
| 468 | +static __always_inline void guest_timing_exit_irqoff(void) | |
| 469 | +{ | |
| 401 | 470 | instrumentation_begin(); |
| 402 | 471 | /* Flush the guest cputime we spent on the guest */ |
| 403 | 472 | vtime_account_guest_exit(); |
| 404 | 473 | instrumentation_end(); |
| 405 | 474 | } |
| 406 | 475 | |
| 476 | +/* | |
| 477 | + * Deprecated. Architectures should move to guest_state_exit_irqoff() and | |
| 478 | + * guest_timing_exit_irqoff(). | |
| 479 | + */ | |
| 480 | +static __always_inline void guest_exit_irqoff(void) | |
| 481 | +{ | |
| 482 | + guest_context_exit_irqoff(); | |
| 483 | + guest_timing_exit_irqoff(); | |
| 484 | +} | |
| 485 | + | |
| 407 | 486 | static inline void guest_exit(void) |
| 408 | 487 | { |
| 409 | 488 | unsigned long flags; |
| @@ -413,6 +492,33 @@ static inline void guest_exit(void) · 3 unmodified lines | ||
| 413 | 492 | local_irq_restore(flags); |
| 414 | 493 | } |
| 415 | 494 | |
| 495 | +/** | |
| 496 | + * guest_state_exit_irqoff - Establish state when returning from guest mode | |
| 497 | + * | |
| 498 | + * Entry from a guest disables interrupts, but guest mode is traced as | |
| 499 | + * interrupts enabled. Also with NO_HZ_FULL RCU might be idle. | |
| 500 | + * | |
| 501 | + * 1) Tell lockdep that interrupts are disabled | |
| 502 | + * 2) Invoke context tracking if enabled to reactivate RCU | |
| 503 | + * 3) Trace interrupts off state | |
| 504 | + * | |
| 505 | + * Invoked from architecture specific code after exiting a guest. | |
| 506 | + * Must be invoked with interrupts disabled and the caller must be | |
| 507 | + * non-instrumentable. | |
| 508 | + * The caller has to invoke guest_timing_exit_irqoff() after this. | |
| 509 | + * | |
| 510 | + * Note: this is analogous to enter_from_user_mode(). | |
| 511 | + */ | |
| 512 | +static __always_inline void guest_state_exit_irqoff(void) | |
| 513 | +{ | |
| 514 | + lockdep_hardirqs_off(CALLER_ADDR0); | |
| 515 | + guest_context_exit_irqoff(); | |
| 516 | + | |
| 517 | + instrumentation_begin(); | |
| 518 | + trace_hardirqs_off_finish(); | |
| 519 | + instrumentation_end(); | |
| 520 | +} | |
| 521 | + | |
| 416 | 522 | static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu) |
| 417 | 523 | { |
| 418 | 524 | /* |
| @@ -380,6 +380,7 @@ enum { · 379 unmodified lines | ||
| 380 | 380 | ATA_HORKAGE_MAX_TRIM_128M = (1 << 26), /* Limit max trim size to 128M */ |
| 381 | 381 | ATA_HORKAGE_NO_NCQ_ON_ATI = (1 << 27), /* Disable NCQ on ATI chipset */ |
| 382 | 382 | ATA_HORKAGE_NO_ID_DEV_LOG = (1 << 28), /* Identify device log missing */ |
| 383 | + ATA_HORKAGE_NO_LOG_DIR = (1 << 29), /* Do not read log directory */ | |
| 383 | 384 | |
| 384 | 385 | /* DMA mask for user DMA control: User visible values; DO NOT |
| 385 | 386 | renumber */ |
| @@ -244,6 +244,13 @@ struct netfs_cache_ops { · 243 unmodified lines | ||
| 244 | 244 | int (*prepare_write)(struct netfs_cache_resources *cres, |
| 245 | 245 | loff_t *_start, size_t *_len, loff_t i_size, |
| 246 | 246 | bool no_space_allocated_yet); |
| 247 | + | |
| 248 | + /* Query the occupancy of the cache in a region, returning where the | |
| 249 | + * next chunk of data starts and how long it is. | |
| 250 | + */ | |
| 251 | + int (*query_occupancy)(struct netfs_cache_resources *cres, | |
| 252 | + loff_t start, size_t len, size_t granularity, | |
| 253 | + loff_t *_data_start, size_t *_data_len); | |
| 247 | 254 | }; |
| 248 | 255 | |
| 249 | 256 | struct readahead_control; |
| @@ -36,14 +36,6 @@ static inline void nfs_copy_fh(struct nfs_fh *target, const struct nfs_fh *sourc · 35 unmodified lines | ||
| 36 | 36 | memcpy(target->data, source->data, source->size); |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | − | |
| 40 | −/* | |
| 41 | − * This is really a general kernel constant, but since nothing like | |
| 42 | − * this is defined in the kernel headers, I have to do it here. | |
| 43 | − */ | |
| 44 | −#define NFS_OFFSET_MAX ((__s64)((~(__u64)0) >> 1)) | |
| 45 | − | |
| 46 | − | |
| 47 | 39 | enum nfs3_stable_how { |
| 48 | 40 | NFS_UNSTABLE = 0, |
| 49 | 41 | NFS_DATA_SYNC = 1, |
| @@ -107,6 +107,7 @@ struct nfs_open_dir_context { · 106 unmodified lines | ||
| 107 | 107 | __u64 dup_cookie; |
| 108 | 108 | pgoff_t page_index; |
| 109 | 109 | signed char duped; |
| 110 | + bool eof; | |
| 110 | 111 | }; |
| 111 | 112 | |
| 112 | 113 | /* |
| @@ -26,6 +26,9 @@ void __page_table_check_pmd_set(struct mm_struct *mm, unsigned long addr, · 25 unmodified lines | ||
| 26 | 26 | pmd_t *pmdp, pmd_t pmd); |
| 27 | 27 | void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, |
| 28 | 28 | pud_t *pudp, pud_t pud); |
| 29 | +void __page_table_check_pte_clear_range(struct mm_struct *mm, | |
| 30 | + unsigned long addr, | |
| 31 | + pmd_t pmd); | |
| 29 | 32 | |
| 30 | 33 | static inline void page_table_check_alloc(struct page *page, unsigned int order) |
| 31 | 34 | { |
| @@ -100,6 +103,16 @@ static inline void page_table_check_pud_set(struct mm_struct *mm, · 68 unmodified lines | ||
| 100 | 103 | __page_table_check_pud_set(mm, addr, pudp, pud); |
| 101 | 104 | } |
| 102 | 105 | |
| 106 | +static inline void page_table_check_pte_clear_range(struct mm_struct *mm, | |
| 107 | + unsigned long addr, | |
| 108 | + pmd_t pmd) | |
| 109 | +{ | |
| 110 | + if (static_branch_likely(&page_table_check_disabled)) | |
| 111 | + return; | |
| 112 | + | |
| 113 | + __page_table_check_pte_clear_range(mm, addr, pmd); | |
| 114 | +} | |
| 115 | + | |
| 103 | 116 | #else |
| 104 | 117 | |
| 105 | 118 | static inline void page_table_check_alloc(struct page *page, unsigned int order) |
| @@ -143,5 +156,11 @@ static inline void page_table_check_pud_set(struct mm_struct *mm, · 37 unmodified lines | ||
| 143 | 156 | { |
| 144 | 157 | } |
| 145 | 158 | |
| 159 | +static inline void page_table_check_pte_clear_range(struct mm_struct *mm, | |
| 160 | + unsigned long addr, | |
| 161 | + pmd_t pmd) | |
| 162 | +{ | |
| 163 | +} | |
| 164 | + | |
| 146 | 165 | #endif /* CONFIG_PAGE_TABLE_CHECK */ |
| 147 | 166 | #endif /* __LINUX_PAGE_TABLE_CHECK_H */ |
| @@ -62,6 +62,7 @@ static inline unsigned long pte_index(unsigned long address) · 61 unmodified lines | ||
| 62 | 62 | { |
| 63 | 63 | return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); |
| 64 | 64 | } |
| 65 | +#define pte_index pte_index | |
| 65 | 66 | |
| 66 | 67 | #ifndef pmd_index |
| 67 | 68 | static inline unsigned long pmd_index(unsigned long address) |
| @@ -123,8 +123,20 @@ static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb) · 122 unmodified lines | ||
| 123 | 123 | |
| 124 | 124 | memcpy(&new_md->u.tun_info, &md_dst->u.tun_info, |
| 125 | 125 | sizeof(struct ip_tunnel_info) + md_size); |
| 126 | +#ifdef CONFIG_DST_CACHE | |
| 127 | + /* Unclone the dst cache if there is one */ | |
| 128 | + if (new_md->u.tun_info.dst_cache.cache) { | |
| 129 | + int ret; | |
| 130 | + | |
| 131 | + ret = dst_cache_init(&new_md->u.tun_info.dst_cache, GFP_ATOMIC); | |
| 132 | + if (ret) { | |
| 133 | + metadata_dst_free(new_md); | |
| 134 | + return ERR_PTR(ret); | |
| 135 | + } | |
| 136 | + } | |
| 137 | +#endif | |
| 138 | + | |
| 126 | 139 | skb_dst_drop(skb); |
| 127 | − dst_hold(&new_md->dst); | |
| 128 | 140 | skb_dst_set(skb, &new_md->dst); |
| 129 | 141 | return new_md; |
| 130 | 142 | } |
| @@ -617,6 +617,7 @@ void snd_pcm_stream_unlock(struct snd_pcm_substream *substream); · 616 unmodified lines | ||
| 617 | 617 | void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream); |
| 618 | 618 | void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream); |
| 619 | 619 | unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream); |
| 620 | +unsigned long _snd_pcm_stream_lock_irqsave_nested(struct snd_pcm_substream *substream); | |
| 620 | 621 | |
| 621 | 622 | /** |
| 622 | 623 | * snd_pcm_stream_lock_irqsave - Lock the PCM stream |
| @@ -635,6 +636,20 @@ unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream); · 12 unmodified lines | ||
| 635 | 636 | void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, |
| 636 | 637 | unsigned long flags); |
| 637 | 638 | |
| 639 | +/** | |
| 640 | + * snd_pcm_stream_lock_irqsave_nested - Single-nested PCM stream locking | |
| 641 | + * @substream: PCM substream | |
| 642 | + * @flags: irq flags | |
| 643 | + * | |
| 644 | + * This locks the PCM stream like snd_pcm_stream_lock_irqsave() but with | |
| 645 | + * the single-depth lockdep subclass. | |
| 646 | + */ | |
| 647 | +#define snd_pcm_stream_lock_irqsave_nested(substream, flags) \ | |
| 648 | + do { \ | |
| 649 | + typecheck(unsigned long, flags); \ | |
| 650 | + flags = _snd_pcm_stream_lock_irqsave_nested(substream); \ | |
| 651 | + } while (0) | |
| 652 | + | |
| 638 | 653 | /** |
| 639 | 654 | * snd_pcm_group_for_each_entry - iterate over the linked substreams |
| 640 | 655 | * @s: the iterator |
| @@ -1624,9 +1624,6 @@ struct kvm_enc_region { · 1623 unmodified lines | ||
| 1624 | 1624 | #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) |
| 1625 | 1625 | #define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) |
| 1626 | 1626 | |
| 1627 | −/* Available with KVM_CAP_XSAVE2 */ | |
| 1628 | −#define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) | |
| 1629 | − | |
| 1630 | 1627 | struct kvm_s390_pv_sec_parm { |
| 1631 | 1628 | __u64 origin; |
| 1632 | 1629 | __u64 length; |
| @@ -2048,4 +2045,7 @@ struct kvm_stats_desc { · 415 unmodified lines | ||
| 2048 | 2045 | |
| 2049 | 2046 | #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) |
| 2050 | 2047 | |
| 2048 | +/* Available with KVM_CAP_XSAVE2 */ | |
| 2049 | +#define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) | |
| 2050 | + | |
| 2051 | 2051 | #endif /* __LINUX_KVM_H */ |
| @@ -106,7 +106,7 @@ enum ip_conntrack_status { · 105 unmodified lines | ||
| 106 | 106 | IPS_NAT_CLASH = IPS_UNTRACKED, |
| 107 | 107 | #endif |
| 108 | 108 | |
| 109 | − /* Conntrack got a helper explicitly attached via CT target. */ | |
| 109 | + /* Conntrack got a helper explicitly attached (ruleset, ctnetlink). */ | |
| 110 | 110 | IPS_HELPER_BIT = 13, |
| 111 | 111 | IPS_HELPER = (1 << IPS_HELPER_BIT), |
| 112 | 112 | |
| @@ -465,6 +465,8 @@ struct perf_event_attr { · 464 unmodified lines | ||
| 465 | 465 | /* |
| 466 | 466 | * User provided data if sigtrap=1, passed back to user via |
| 467 | 467 | * siginfo_t::si_perf_data, e.g. to permit user to identify the event. |
| 468 | + * Note, siginfo_t::si_perf_data is long-sized, and sig_data will be | |
| 469 | + * truncated accordingly on 32 bit architectures. | |
| 468 | 470 | */ |
| 469 | 471 | __u64 sig_data; |
| 470 | 472 | }; |
| @@ -56,8 +56,10 @@ · 55 unmodified lines | ||
| 56 | 56 | * * |
| 57 | 57 | ****************************************************************************/ |
| 58 | 58 | |
| 59 | +#define AES_IEC958_STATUS_SIZE 24 | |
| 60 | + | |
| 59 | 61 | struct snd_aes_iec958 { |
| 60 | − unsigned char status[24]; /* AES/IEC958 channel status bits */ | |
| 62 | + unsigned char status[AES_IEC958_STATUS_SIZE]; /* AES/IEC958 channel status bits */ | |
| 61 | 63 | unsigned char subcode[147]; /* AES/IEC958 subcode bits */ |
| 62 | 64 | unsigned char pad; /* nothing */ |
| 63 | 65 | unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ |
| @@ -47,7 +47,13 @@ struct ioctl_gntdev_grant_ref { · 46 unmodified lines | ||
| 47 | 47 | /* |
| 48 | 48 | * Inserts the grant references into the mapping table of an instance |
| 49 | 49 | * of gntdev. N.B. This does not perform the mapping, which is deferred |
| 50 | − * until mmap() is called with @index as the offset. | |
| 50 | + * until mmap() is called with @index as the offset. @index should be | |
| 51 | + * considered opaque to userspace, with one exception: if no grant | |
| 52 | + * references have ever been inserted into the mapping table of this | |
| 53 | + * instance, @index will be set to 0. This is necessary to use gntdev | |
| 54 | + * with userspace APIs that expect a file descriptor that can be | |
| 55 | + * mmap()'d at offset 0, such as Wayland. If @count is set to 0, this | |
| 56 | + * ioctl will fail. | |
| 51 | 57 | */ |
| 52 | 58 | #define IOCTL_GNTDEV_MAP_GRANT_REF \ |
| 53 | 59 | _IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref)) |
| @@ -1,6 +1,4 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | − * evtchn.h | |
| 3 | − * | |
| 4 | 2 | * Interface to /dev/xen/xenbus_backend. |
| 5 | 3 | * |
| 6 | 4 | * Copyright (c) 2011 Bastian Blank <waldi@debian.org> |
| @@ -1964,6 +1964,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid) · 1963 unmodified lines | ||
| 1964 | 1964 | */ |
| 1965 | 1965 | un = lookup_undo(ulp, semid); |
| 1966 | 1966 | if (un) { |
| 1967 | + spin_unlock(&ulp->lock); | |
| 1967 | 1968 | kvfree(new); |
| 1968 | 1969 | goto success; |
| 1969 | 1970 | } |
| @@ -1976,9 +1977,8 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid) · 6 unmodified lines | ||
| 1976 | 1977 | ipc_assert_locked_object(&sma->sem_perm); |
| 1977 | 1978 | list_add(&new->list_id, &sma->list_id); |
| 1978 | 1979 | un = new; |
| 1979 | − | |
| 1980 | −success: | |
| 1981 | 1980 | spin_unlock(&ulp->lock); |
| 1981 | +success: | |
| 1982 | 1982 | sem_unlock(sma, -1); |
| 1983 | 1983 | out: |
| 1984 | 1984 | return un; |
| @@ -185,7 +185,7 @@ static int audit_match_perm(struct audit_context *ctx, int mask) · 184 unmodified lines | ||
| 185 | 185 | case AUDITSC_EXECVE: |
| 186 | 186 | return mask & AUDIT_PERM_EXEC; |
| 187 | 187 | case AUDITSC_OPENAT2: |
| 188 | − return mask & ACC_MODE((u32)((struct open_how *)ctx->argv[2])->flags); | |
| 188 | + return mask & ACC_MODE((u32)ctx->openat2.flags); | |
| 189 | 189 | default: |
| 190 | 190 | return 0; |
| 191 | 191 | } |
| @@ -3238,6 +3238,15 @@ static int perf_event_modify_breakpoint(struct perf_event *bp, · 3237 unmodified lines | ||
| 3238 | 3238 | return err; |
| 3239 | 3239 | } |
| 3240 | 3240 | |
| 3241 | +/* | |
| 3242 | + * Copy event-type-independent attributes that may be modified. | |
| 3243 | + */ | |
| 3244 | +static void perf_event_modify_copy_attr(struct perf_event_attr *to, | |
| 3245 | + const struct perf_event_attr *from) | |
| 3246 | +{ | |
| 3247 | + to->sig_data = from->sig_data; | |
| 3248 | +} | |
| 3249 | + | |
| 3241 | 3250 | static int perf_event_modify_attr(struct perf_event *event, |
| 3242 | 3251 | struct perf_event_attr *attr) |
| 3243 | 3252 | { |
| @@ -3260,10 +3269,17 @@ static int perf_event_modify_attr(struct perf_event *event, · 16 unmodified lines | ||
| 3260 | 3269 | WARN_ON_ONCE(event->ctx->parent_ctx); |
| 3261 | 3270 | |
| 3262 | 3271 | mutex_lock(&event->child_mutex); |
| 3272 | + /* | |
| 3273 | + * Event-type-independent attributes must be copied before event-type | |
| 3274 | + * modification, which will validate that final attributes match the | |
| 3275 | + * source attributes after all relevant attributes have been copied. | |
| 3276 | + */ | |
| 3277 | + perf_event_modify_copy_attr(&event->attr, attr); | |
| 3263 | 3278 | err = func(event, attr); |
| 3264 | 3279 | if (err) |
| 3265 | 3280 | goto out; |
| 3266 | 3281 | list_for_each_entry(child, &event->child_list, child_list) { |
| 3282 | + perf_event_modify_copy_attr(&child->attr, attr); | |
| 3267 | 3283 | err = func(child, attr); |
| 3268 | 3284 | if (err) |
| 3269 | 3285 | goto out; |
| @@ -18,14 +18,14 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen) |
| 20 | 20 | { |
| 21 | − __blake2s_update(state, in, inlen, blake2s_compress); | |
| 21 | + __blake2s_update(state, in, inlen, false); | |
| 22 | 22 | } |
| 23 | 23 | EXPORT_SYMBOL(blake2s_update); |
| 24 | 24 | |
| 25 | 25 | void blake2s_final(struct blake2s_state *state, u8 *out) |
| 26 | 26 | { |
| 27 | 27 | WARN_ON(IS_ENABLED(DEBUG) && !out); |
| 28 | − __blake2s_final(state, out, blake2s_compress); | |
| 28 | + __blake2s_final(state, out, false); | |
| 29 | 29 | memzero_explicit(state, sizeof(*state)); |
| 30 | 30 | } |
| 31 | 31 | EXPORT_SYMBOL(blake2s_final); |
| @@ -171,6 +171,8 @@ static void __init pte_advanced_tests(struct pgtable_debug_args *args) · 170 unmodified lines | ||
| 171 | 171 | ptep_test_and_clear_young(args->vma, args->vaddr, args->ptep); |
| 172 | 172 | pte = ptep_get(args->ptep); |
| 173 | 173 | WARN_ON(pte_young(pte)); |
| 174 | + | |
| 175 | + ptep_get_and_clear_full(args->mm, args->vaddr, args->ptep, 1); | |
| 174 | 176 | } |
| 175 | 177 | |
| 176 | 178 | static void __init pte_savedwrite_tests(struct pgtable_debug_args *args) |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/hashtable.h> |
| 17 | 17 | #include <linux/userfaultfd_k.h> |
| 18 | 18 | #include <linux/page_idle.h> |
| 19 | +#include <linux/page_table_check.h> | |
| 19 | 20 | #include <linux/swapops.h> |
| 20 | 21 | #include <linux/shmem_fs.h> |
| 21 | 22 | |
| @@ -1416,6 +1417,21 @@ static int khugepaged_add_pte_mapped_thp(struct mm_struct *mm, · 1394 unmodified lines | ||
| 1416 | 1417 | return 0; |
| 1417 | 1418 | } |
| 1418 | 1419 | |
| 1420 | +static void collapse_and_free_pmd(struct mm_struct *mm, struct vm_area_struct *vma, | |
| 1421 | + unsigned long addr, pmd_t *pmdp) | |
| 1422 | +{ | |
| 1423 | + spinlock_t *ptl; | |
| 1424 | + pmd_t pmd; | |
| 1425 | + | |
| 1426 | + mmap_assert_write_locked(mm); | |
| 1427 | + ptl = pmd_lock(vma->vm_mm, pmdp); | |
| 1428 | + pmd = pmdp_collapse_flush(vma, addr, pmdp); | |
| 1429 | + spin_unlock(ptl); | |
| 1430 | + mm_dec_nr_ptes(mm); | |
| 1431 | + page_table_check_pte_clear_range(mm, addr, pmd); | |
| 1432 | + pte_free(mm, pmd_pgtable(pmd)); | |
| 1433 | +} | |
| 1434 | + | |
| 1419 | 1435 | /** |
| 1420 | 1436 | * collapse_pte_mapped_thp - Try to collapse a pte-mapped THP for mm at |
| 1421 | 1437 | * address haddr. |
| @@ -1433,7 +1449,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr) · 11 unmodified lines | ||
| 1433 | 1449 | struct vm_area_struct *vma = find_vma(mm, haddr); |
| 1434 | 1450 | struct page *hpage; |
| 1435 | 1451 | pte_t *start_pte, *pte; |
| 1436 | − pmd_t *pmd, _pmd; | |
| 1452 | + pmd_t *pmd; | |
| 1437 | 1453 | spinlock_t *ptl; |
| 1438 | 1454 | int count = 0; |
| 1439 | 1455 | int i; |
| @@ -1509,12 +1525,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr) · 69 unmodified lines | ||
| 1509 | 1525 | } |
| 1510 | 1526 | |
| 1511 | 1527 | /* step 4: collapse pmd */ |
| 1512 | − ptl = pmd_lock(vma->vm_mm, pmd); | |
| 1513 | − _pmd = pmdp_collapse_flush(vma, haddr, pmd); | |
| 1514 | − spin_unlock(ptl); | |
| 1515 | − mm_dec_nr_ptes(mm); | |
| 1516 | − pte_free(mm, pmd_pgtable(_pmd)); | |
| 1517 | − | |
| 1528 | + collapse_and_free_pmd(mm, vma, haddr, pmd); | |
| 1518 | 1529 | drop_hpage: |
| 1519 | 1530 | unlock_page(hpage); |
| 1520 | 1531 | put_page(hpage); |
| @@ -1552,7 +1563,7 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff) · 31 unmodified lines | ||
| 1552 | 1563 | struct vm_area_struct *vma; |
| 1553 | 1564 | struct mm_struct *mm; |
| 1554 | 1565 | unsigned long addr; |
| 1555 | − pmd_t *pmd, _pmd; | |
| 1566 | + pmd_t *pmd; | |
| 1556 | 1567 | |
| 1557 | 1568 | i_mmap_lock_write(mapping); |
| 1558 | 1569 | vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) { |
| @@ -1591,14 +1602,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff) · 32 unmodified lines | ||
| 1591 | 1602 | * reverse order. Trylock is a way to avoid deadlock. |
| 1592 | 1603 | */ |
| 1593 | 1604 | if (mmap_write_trylock(mm)) { |
| 1594 | − if (!khugepaged_test_exit(mm)) { | |
| 1595 | − spinlock_t *ptl = pmd_lock(mm, pmd); | |
| 1596 | − /* assume page table is clear */ | |
| 1597 | − _pmd = pmdp_collapse_flush(vma, addr, pmd); | |
| 1598 | − spin_unlock(ptl); | |
| 1599 | − mm_dec_nr_ptes(mm); | |
| 1600 | − pte_free(mm, pmd_pgtable(_pmd)); | |
| 1601 | − } | |
| 1605 | + if (!khugepaged_test_exit(mm)) | |
| 1606 | + collapse_and_free_pmd(mm, vma, addr, pmd); | |
| 1602 | 1607 | mmap_write_unlock(mm); |
| 1603 | 1608 | } else { |
| 1604 | 1609 | /* Try again later */ |
| @@ -1410,7 +1410,8 @@ static void kmemleak_scan(void) · 1409 unmodified lines | ||
| 1410 | 1410 | { |
| 1411 | 1411 | unsigned long flags; |
| 1412 | 1412 | struct kmemleak_object *object; |
| 1413 | − int i; | |
| 1413 | + struct zone *zone; | |
| 1414 | + int __maybe_unused i; | |
| 1414 | 1415 | int new_leaks = 0; |
| 1415 | 1416 | |
| 1416 | 1417 | jiffies_last_scan = jiffies; |
| @@ -1450,9 +1451,9 @@ static void kmemleak_scan(void) · 33 unmodified lines | ||
| 1450 | 1451 | * Struct page scanning for each node. |
| 1451 | 1452 | */ |
| 1452 | 1453 | get_online_mems(); |
| 1453 | − for_each_online_node(i) { | |
| 1454 | − unsigned long start_pfn = node_start_pfn(i); | |
| 1455 | − unsigned long end_pfn = node_end_pfn(i); | |
| 1454 | + for_each_populated_zone(zone) { | |
| 1455 | + unsigned long start_pfn = zone->zone_start_pfn; | |
| 1456 | + unsigned long end_pfn = zone_end_pfn(zone); | |
| 1456 | 1457 | unsigned long pfn; |
| 1457 | 1458 | |
| 1458 | 1459 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { |
| @@ -1461,8 +1462,8 @@ static void kmemleak_scan(void) · 2 unmodified lines | ||
| 1461 | 1462 | if (!page) |
| 1462 | 1463 | continue; |
| 1463 | 1464 | |
| 1464 | − /* only scan pages belonging to this node */ | |
| 1465 | − if (page_to_nid(page) != i) | |
| 1465 | + /* only scan pages belonging to this zone */ | |
| 1466 | + if (page_zone(page) != zone) | |
| 1466 | 1467 | continue; |
| 1467 | 1468 | /* only scan if page is in use */ |
| 1468 | 1469 | if (page_count(page) == 0) |
| @@ -115,7 +115,7 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype) · 114 unmodified lines | ||
| 115 | 115 | * onlining - just onlined memory won't immediately be considered for |
| 116 | 116 | * allocation. |
| 117 | 117 | */ |
| 118 | − if (!isolated_page && PageBuddy(page)) { | |
| 118 | + if (!isolated_page) { | |
| 119 | 119 | nr_pages = move_freepages_block(zone, page, migratetype, NULL); |
| 120 | 120 | __mod_zone_freepage_state(zone, nr_pages, migratetype); |
| 121 | 121 | } |
| @@ -86,8 +86,8 @@ static void page_table_check_clear(struct mm_struct *mm, unsigned long addr, · 85 unmodified lines | ||
| 86 | 86 | { |
| 87 | 87 | struct page_ext *page_ext; |
| 88 | 88 | struct page *page; |
| 89 | + unsigned long i; | |
| 89 | 90 | bool anon; |
| 90 | − int i; | |
| 91 | 91 | |
| 92 | 92 | if (!pfn_valid(pfn)) |
| 93 | 93 | return; |
| @@ -121,8 +121,8 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr, · 27 unmodified lines | ||
| 121 | 121 | { |
| 122 | 122 | struct page_ext *page_ext; |
| 123 | 123 | struct page *page; |
| 124 | + unsigned long i; | |
| 124 | 125 | bool anon; |
| 125 | − int i; | |
| 126 | 126 | |
| 127 | 127 | if (!pfn_valid(pfn)) |
| 128 | 128 | return; |
| @@ -152,10 +152,10 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr, · 23 unmodified lines | ||
| 152 | 152 | void __page_table_check_zero(struct page *page, unsigned int order) |
| 153 | 153 | { |
| 154 | 154 | struct page_ext *page_ext = lookup_page_ext(page); |
| 155 | − int i; | |
| 155 | + unsigned long i; | |
| 156 | 156 | |
| 157 | 157 | BUG_ON(!page_ext); |
| 158 | − for (i = 0; i < (1 << order); i++) { | |
| 158 | + for (i = 0; i < (1ul << order); i++) { | |
| 159 | 159 | struct page_table_check *ptc = get_page_table_check(page_ext); |
| 160 | 160 | |
| 161 | 161 | BUG_ON(atomic_read(&ptc->anon_map_count)); |
| @@ -206,17 +206,10 @@ EXPORT_SYMBOL(__page_table_check_pud_clear); · 44 unmodified lines | ||
| 206 | 206 | void __page_table_check_pte_set(struct mm_struct *mm, unsigned long addr, |
| 207 | 207 | pte_t *ptep, pte_t pte) |
| 208 | 208 | { |
| 209 | − pte_t old_pte; | |
| 210 | − | |
| 211 | 209 | if (&init_mm == mm) |
| 212 | 210 | return; |
| 213 | 211 | |
| 214 | − old_pte = *ptep; | |
| 215 | − if (pte_user_accessible_page(old_pte)) { | |
| 216 | − page_table_check_clear(mm, addr, pte_pfn(old_pte), | |
| 217 | − PAGE_SIZE >> PAGE_SHIFT); | |
| 218 | − } | |
| 219 | − | |
| 212 | + __page_table_check_pte_clear(mm, addr, *ptep); | |
| 220 | 213 | if (pte_user_accessible_page(pte)) { |
| 221 | 214 | page_table_check_set(mm, addr, pte_pfn(pte), |
| 222 | 215 | PAGE_SIZE >> PAGE_SHIFT, |
| @@ -228,17 +221,10 @@ EXPORT_SYMBOL(__page_table_check_pte_set); · 5 unmodified lines | ||
| 228 | 221 | void __page_table_check_pmd_set(struct mm_struct *mm, unsigned long addr, |
| 229 | 222 | pmd_t *pmdp, pmd_t pmd) |
| 230 | 223 | { |
| 231 | − pmd_t old_pmd; | |
| 232 | − | |
| 233 | 224 | if (&init_mm == mm) |
| 234 | 225 | return; |
| 235 | 226 | |
| 236 | − old_pmd = *pmdp; | |
| 237 | − if (pmd_user_accessible_page(old_pmd)) { | |
| 238 | − page_table_check_clear(mm, addr, pmd_pfn(old_pmd), | |
| 239 | − PMD_PAGE_SIZE >> PAGE_SHIFT); | |
| 240 | − } | |
| 241 | − | |
| 227 | + __page_table_check_pmd_clear(mm, addr, *pmdp); | |
| 242 | 228 | if (pmd_user_accessible_page(pmd)) { |
| 243 | 229 | page_table_check_set(mm, addr, pmd_pfn(pmd), |
| 244 | 230 | PMD_PAGE_SIZE >> PAGE_SHIFT, |
| @@ -250,17 +236,10 @@ EXPORT_SYMBOL(__page_table_check_pmd_set); · 5 unmodified lines | ||
| 250 | 236 | void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, |
| 251 | 237 | pud_t *pudp, pud_t pud) |
| 252 | 238 | { |
| 253 | − pud_t old_pud; | |
| 254 | − | |
| 255 | 239 | if (&init_mm == mm) |
| 256 | 240 | return; |
| 257 | 241 | |
| 258 | − old_pud = *pudp; | |
| 259 | − if (pud_user_accessible_page(old_pud)) { | |
| 260 | − page_table_check_clear(mm, addr, pud_pfn(old_pud), | |
| 261 | − PUD_PAGE_SIZE >> PAGE_SHIFT); | |
| 262 | − } | |
| 263 | − | |
| 242 | + __page_table_check_pud_clear(mm, addr, *pudp); | |
| 264 | 243 | if (pud_user_accessible_page(pud)) { |
| 265 | 244 | page_table_check_set(mm, addr, pud_pfn(pud), |
| 266 | 245 | PUD_PAGE_SIZE >> PAGE_SHIFT, |
| @@ -268,3 +247,23 @@ void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, · 1 unmodified line | ||
| 268 | 247 | } |
| 269 | 248 | } |
| 270 | 249 | EXPORT_SYMBOL(__page_table_check_pud_set); |
| 250 | + | |
| 251 | +void __page_table_check_pte_clear_range(struct mm_struct *mm, | |
| 252 | + unsigned long addr, | |
| 253 | + pmd_t pmd) | |
| 254 | +{ | |
| 255 | + if (&init_mm == mm) | |
| 256 | + return; | |
| 257 | + | |
| 258 | + if (!pmd_bad(pmd) && !pmd_leaf(pmd)) { | |
| 259 | + pte_t *ptep = pte_offset_map(&pmd, addr); | |
| 260 | + unsigned long i; | |
| 261 | + | |
| 262 | + pte_unmap(ptep); | |
| 263 | + for (i = 0; i < PTRS_PER_PTE; i++) { | |
| 264 | + __page_table_check_pte_clear(mm, addr, *ptep); | |
| 265 | + addr += PAGE_SIZE; | |
| 266 | + ptep++; | |
| 267 | + } | |
| 268 | + } | |
| 269 | +} | |
| @@ -129,6 +129,7 @@ void vlan_dev_set_ingress_priority(const struct net_device *dev, · 128 unmodified lines | ||
| 129 | 129 | u32 skb_prio, u16 vlan_prio); |
| 130 | 130 | int vlan_dev_set_egress_priority(const struct net_device *dev, |
| 131 | 131 | u32 skb_prio, u16 vlan_prio); |
| 132 | +void vlan_dev_free_egress_priority(const struct net_device *dev); | |
| 132 | 133 | int vlan_dev_change_flags(const struct net_device *dev, u32 flag, u32 mask); |
| 133 | 134 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result, |
| 134 | 135 | size_t size); |
| @@ -139,7 +140,6 @@ int vlan_check_real_dev(struct net_device *real_dev, · 4 unmodified lines | ||
| 139 | 140 | void vlan_setup(struct net_device *dev); |
| 140 | 141 | int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack); |
| 141 | 142 | void unregister_vlan_dev(struct net_device *dev, struct list_head *head); |
| 142 | −void vlan_dev_uninit(struct net_device *dev); | |
| 143 | 143 | bool vlan_dev_inherit_address(struct net_device *dev, |
| 144 | 144 | struct net_device *real_dev); |
| 145 | 145 | |
| @@ -622,7 +622,7 @@ static int vlan_dev_init(struct net_device *dev) · 621 unmodified lines | ||
| 622 | 622 | } |
| 623 | 623 | |
| 624 | 624 | /* Note: this function might be called multiple times for the same device. */ |
| 625 | −void vlan_dev_uninit(struct net_device *dev) | |
| 625 | +void vlan_dev_free_egress_priority(const struct net_device *dev) | |
| 626 | 626 | { |
| 627 | 627 | struct vlan_priority_tci_mapping *pm; |
| 628 | 628 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); |
| @@ -636,6 +636,16 @@ void vlan_dev_uninit(struct net_device *dev) · 7 unmodified lines | ||
| 636 | 636 | } |
| 637 | 637 | } |
| 638 | 638 | |
| 639 | +static void vlan_dev_uninit(struct net_device *dev) | |
| 640 | +{ | |
| 641 | + struct vlan_dev_priv *vlan = vlan_dev_priv(dev); | |
| 642 | + | |
| 643 | + vlan_dev_free_egress_priority(dev); | |
| 644 | + | |
| 645 | + /* Get rid of the vlan's reference to real_dev */ | |
| 646 | + dev_put_track(vlan->real_dev, &vlan->dev_tracker); | |
| 647 | +} | |
| 648 | + | |
| 639 | 649 | static netdev_features_t vlan_dev_fix_features(struct net_device *dev, |
| 640 | 650 | netdev_features_t features) |
| 641 | 651 | { |
| @@ -846,9 +856,6 @@ static void vlan_dev_free(struct net_device *dev) · 204 unmodified lines | ||
| 846 | 856 | |
| 847 | 857 | free_percpu(vlan->vlan_pcpu_stats); |
| 848 | 858 | vlan->vlan_pcpu_stats = NULL; |
| 849 | − | |
| 850 | − /* Get rid of the vlan's reference to real_dev */ | |
| 851 | − dev_put_track(vlan->real_dev, &vlan->dev_tracker); | |
| 852 | 859 | } |
| 853 | 860 | |
| 854 | 861 | void vlan_setup(struct net_device *dev) |
| @@ -183,10 +183,11 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev, · 182 unmodified lines | ||
| 183 | 183 | return -EINVAL; |
| 184 | 184 | |
| 185 | 185 | err = vlan_changelink(dev, tb, data, extack); |
| 186 | − if (!err) | |
| 187 | − err = register_vlan_dev(dev, extack); | |
| 188 | 186 | if (err) |
| 189 | − vlan_dev_uninit(dev); | |
| 187 | + return err; | |
| 188 | + err = register_vlan_dev(dev, extack); | |
| 189 | + if (err) | |
| 190 | + vlan_dev_free_egress_priority(dev); | |
| 190 | 191 | return err; |
| 191 | 192 | } |
| 192 | 193 | |
| @@ -91,9 +91,10 @@ again: · 90 unmodified lines | ||
| 91 | 91 | spin_unlock_bh(&ax25_list_lock); |
| 92 | 92 | lock_sock(sk); |
| 93 | 93 | s->ax25_dev = NULL; |
| 94 | + dev_put_track(ax25_dev->dev, &ax25_dev->dev_tracker); | |
| 94 | 95 | ax25_dev_put(ax25_dev); |
| 95 | − release_sock(sk); | |
| 96 | 96 | ax25_disconnect(s, ENETUNREACH); |
| 97 | + release_sock(sk); | |
| 97 | 98 | spin_lock_bh(&ax25_list_lock); |
| 98 | 99 | sock_put(sk); |
| 99 | 100 | /* The entry could have been deleted from the |
| @@ -1116,8 +1117,10 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) · 1016 unmodified lines | ||
| 1116 | 1117 | } |
| 1117 | 1118 | } |
| 1118 | 1119 | |
| 1119 | − if (ax25_dev != NULL) | |
| 1120 | + if (ax25_dev) { | |
| 1120 | 1121 | ax25_fillin_cb(ax25, ax25_dev); |
| 1122 | + dev_hold_track(ax25_dev->dev, &ax25_dev->dev_tracker, GFP_ATOMIC); | |
| 1123 | + } | |
| 1121 | 1124 | |
| 1122 | 1125 | done: |
| 1123 | 1126 | ax25_cb_add(ax25); |
| @@ -56,6 +56,7 @@ · 55 unmodified lines | ||
| 56 | 56 | #include <linux/module.h> |
| 57 | 57 | #include <linux/init.h> |
| 58 | 58 | #include <linux/interrupt.h> |
| 59 | +#include <linux/spinlock.h> | |
| 59 | 60 | #include <linux/hrtimer.h> |
| 60 | 61 | #include <linux/wait.h> |
| 61 | 62 | #include <linux/uio.h> |
| @@ -145,6 +146,7 @@ struct isotp_sock { · 83 unmodified lines | ||
| 145 | 146 | struct tpcon rx, tx; |
| 146 | 147 | struct list_head notifier; |
| 147 | 148 | wait_queue_head_t wait; |
| 149 | + spinlock_t rx_lock; /* protect single thread state machine */ | |
| 148 | 150 | }; |
| 149 | 151 | |
| 150 | 152 | static LIST_HEAD(isotp_notifier_list); |
| @@ -615,11 +617,17 @@ static void isotp_rcv(struct sk_buff *skb, void *data) · 464 unmodified lines | ||
| 615 | 617 | |
| 616 | 618 | n_pci_type = cf->data[ae] & 0xF0; |
| 617 | 619 | |
| 620 | + /* Make sure the state changes and data structures stay consistent at | |
| 621 | + * CAN frame reception time. This locking is not needed in real world | |
| 622 | + * use cases but the inconsistency can be triggered with syzkaller. | |
| 623 | + */ | |
| 624 | + spin_lock(&so->rx_lock); | |
| 625 | + | |
| 618 | 626 | if (so->opt.flags & CAN_ISOTP_HALF_DUPLEX) { |
| 619 | 627 | /* check rx/tx path half duplex expectations */ |
| 620 | 628 | if ((so->tx.state != ISOTP_IDLE && n_pci_type != N_PCI_FC) || |
| 621 | 629 | (so->rx.state != ISOTP_IDLE && n_pci_type == N_PCI_FC)) |
| 622 | − return; | |
| 630 | + goto out_unlock; | |
| 623 | 631 | } |
| 624 | 632 | |
| 625 | 633 | switch (n_pci_type) { |
| @@ -668,6 +676,9 @@ static void isotp_rcv(struct sk_buff *skb, void *data) · 42 unmodified lines | ||
| 668 | 676 | isotp_rcv_cf(sk, cf, ae, skb); |
| 669 | 677 | break; |
| 670 | 678 | } |
| 679 | + | |
| 680 | +out_unlock: | |
| 681 | + spin_unlock(&so->rx_lock); | |
| 671 | 682 | } |
| 672 | 683 | |
| 673 | 684 | static void isotp_fill_dataframe(struct canfd_frame *cf, struct isotp_sock *so, |
| @@ -876,7 +887,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) · 202 unmodified lines | ||
| 876 | 887 | |
| 877 | 888 | if (!size || size > MAX_MSG_LENGTH) { |
| 878 | 889 | err = -EINVAL; |
| 879 | − goto err_out; | |
| 890 | + goto err_out_drop; | |
| 880 | 891 | } |
| 881 | 892 | |
| 882 | 893 | /* take care of a potential SF_DL ESC offset for TX_DL > 8 */ |
| @@ -886,24 +897,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) · 3 unmodified lines | ||
| 886 | 897 | if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) && |
| 887 | 898 | (size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) { |
| 888 | 899 | err = -EINVAL; |
| 889 | − goto err_out; | |
| 900 | + goto err_out_drop; | |
| 890 | 901 | } |
| 891 | 902 | |
| 892 | 903 | err = memcpy_from_msg(so->tx.buf, msg, size); |
| 893 | 904 | if (err < 0) |
| 894 | − goto err_out; | |
| 905 | + goto err_out_drop; | |
| 895 | 906 | |
| 896 | 907 | dev = dev_get_by_index(sock_net(sk), so->ifindex); |
| 897 | 908 | if (!dev) { |
| 898 | 909 | err = -ENXIO; |
| 899 | − goto err_out; | |
| 910 | + goto err_out_drop; | |
| 900 | 911 | } |
| 901 | 912 | |
| 902 | 913 | skb = sock_alloc_send_skb(sk, so->ll.mtu + sizeof(struct can_skb_priv), |
| 903 | 914 | msg->msg_flags & MSG_DONTWAIT, &err); |
| 904 | 915 | if (!skb) { |
| 905 | 916 | dev_put(dev); |
| 906 | − goto err_out; | |
| 917 | + goto err_out_drop; | |
| 907 | 918 | } |
| 908 | 919 | |
| 909 | 920 | can_skb_reserve(skb); |
| @@ -965,7 +976,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) · 55 unmodified lines | ||
| 965 | 976 | if (err) { |
| 966 | 977 | pr_notice_once("can-isotp: %s: can_send_ret %pe\n", |
| 967 | 978 | __func__, ERR_PTR(err)); |
| 968 | − goto err_out; | |
| 979 | + goto err_out_drop; | |
| 969 | 980 | } |
| 970 | 981 | |
| 971 | 982 | if (wait_tx_done) { |
| @@ -978,6 +989,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) · 6 unmodified lines | ||
| 978 | 989 | |
| 979 | 990 | return size; |
| 980 | 991 | |
| 992 | +err_out_drop: | |
| 993 | + /* drop this PDU and unlock a potential wait queue */ | |
| 994 | + old_state = ISOTP_IDLE; | |
| 981 | 995 | err_out: |
| 982 | 996 | so->tx.state = old_state; |
| 983 | 997 | if (so->tx.state == ISOTP_IDLE) |
| @@ -1444,6 +1458,7 @@ static int isotp_init(struct sock *sk) · 460 unmodified lines | ||
| 1444 | 1458 | so->txtimer.function = isotp_tx_timer_handler; |
| 1445 | 1459 | |
| 1446 | 1460 | init_waitqueue_head(&so->wait); |
| 1461 | + spin_lock_init(&so->rx_lock); | |
| 1447 | 1462 | |
| 1448 | 1463 | spin_lock(&isotp_notifier_lock); |
| 1449 | 1464 | list_add_tail(&so->notifier, &isotp_notifier_list); |
| @@ -246,6 +246,7 @@ enum { · 245 unmodified lines | ||
| 246 | 246 | Opt_cephx_sign_messages, |
| 247 | 247 | Opt_tcp_nodelay, |
| 248 | 248 | Opt_abort_on_full, |
| 249 | + Opt_rxbounce, | |
| 249 | 250 | }; |
| 250 | 251 | |
| 251 | 252 | enum { |
| @@ -295,6 +296,7 @@ static const struct fs_parameter_spec ceph_parameters[] = { · 43 unmodified lines | ||
| 295 | 296 | fsparam_u32 ("osdkeepalive", Opt_osdkeepalivetimeout), |
| 296 | 297 | fsparam_enum ("read_from_replica", Opt_read_from_replica, |
| 297 | 298 | ceph_param_read_from_replica), |
| 299 | + fsparam_flag ("rxbounce", Opt_rxbounce), | |
| 298 | 300 | fsparam_enum ("ms_mode", Opt_ms_mode, |
| 299 | 301 | ceph_param_ms_mode), |
| 300 | 302 | fsparam_string ("secret", Opt_secret), |
| @@ -584,6 +586,9 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt, · 283 unmodified lines | ||
| 584 | 586 | case Opt_abort_on_full: |
| 585 | 587 | opt->flags |= CEPH_OPT_ABORT_ON_FULL; |
| 586 | 588 | break; |
| 589 | + case Opt_rxbounce: | |
| 590 | + opt->flags |= CEPH_OPT_RXBOUNCE; | |
| 591 | + break; | |
| 587 | 592 | |
| 588 | 593 | default: |
| 589 | 594 | BUG(); |
| @@ -660,6 +665,8 @@ int ceph_print_client_options(struct seq_file *m, struct ceph_client *client, · 70 unmodified lines | ||
| 660 | 665 | seq_puts(m, "notcp_nodelay,"); |
| 661 | 666 | if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL)) |
| 662 | 667 | seq_puts(m, "abort_on_full,"); |
| 668 | + if (opt->flags & CEPH_OPT_RXBOUNCE) | |
| 669 | + seq_puts(m, "rxbounce,"); | |
| 663 | 670 | |
| 664 | 671 | if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT) |
| 665 | 672 | seq_printf(m, "mount_timeout=%d,", |
| @@ -515,6 +515,10 @@ static void ceph_con_reset_protocol(struct ceph_connection *con) · 514 unmodified lines | ||
| 515 | 515 | ceph_msg_put(con->out_msg); |
| 516 | 516 | con->out_msg = NULL; |
| 517 | 517 | } |
| 518 | + if (con->bounce_page) { | |
| 519 | + __free_page(con->bounce_page); | |
| 520 | + con->bounce_page = NULL; | |
| 521 | + } | |
| 518 | 522 | |
| 519 | 523 | if (ceph_msgr2(from_msgr(con->msgr))) |
| 520 | 524 | ceph_con_v2_reset_protocol(con); |
| @@ -992,8 +992,7 @@ static int read_partial_message_section(struct ceph_connection *con, · 991 unmodified lines | ||
| 992 | 992 | |
| 993 | 993 | static int read_partial_msg_data(struct ceph_connection *con) |
| 994 | 994 | { |
| 995 | − struct ceph_msg *msg = con->in_msg; | |
| 996 | − struct ceph_msg_data_cursor *cursor = &msg->cursor; | |
| 995 | + struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor; | |
| 997 | 996 | bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC); |
| 998 | 997 | struct page *page; |
| 999 | 998 | size_t page_offset; |
| @@ -1001,9 +1000,6 @@ static int read_partial_msg_data(struct ceph_connection *con) · 1 unmodified line | ||
| 1001 | 1000 | u32 crc = 0; |
| 1002 | 1001 | int ret; |
| 1003 | 1002 | |
| 1004 | − if (!msg->num_data_items) | |
| 1005 | − return -EIO; | |
| 1006 | − | |
| 1007 | 1003 | if (do_datacrc) |
| 1008 | 1004 | crc = con->in_data_crc; |
| 1009 | 1005 | while (cursor->total_resid) { |
| @@ -1031,6 +1027,46 @@ static int read_partial_msg_data(struct ceph_connection *con) · 21 unmodified lines | ||
| 1031 | 1027 | return 1; /* must return > 0 to indicate success */ |
| 1032 | 1028 | } |
| 1033 | 1029 | |
| 1030 | +static int read_partial_msg_data_bounce(struct ceph_connection *con) | |
| 1031 | +{ | |
| 1032 | + struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor; | |
| 1033 | + struct page *page; | |
| 1034 | + size_t off, len; | |
| 1035 | + u32 crc; | |
| 1036 | + int ret; | |
| 1037 | + | |
| 1038 | + if (unlikely(!con->bounce_page)) { | |
| 1039 | + con->bounce_page = alloc_page(GFP_NOIO); | |
| 1040 | + if (!con->bounce_page) { | |
| 1041 | + pr_err("failed to allocate bounce page\n"); | |
| 1042 | + return -ENOMEM; | |
| 1043 | + } | |
| 1044 | + } | |
| 1045 | + | |
| 1046 | + crc = con->in_data_crc; | |
| 1047 | + while (cursor->total_resid) { | |
| 1048 | + if (!cursor->resid) { | |
| 1049 | + ceph_msg_data_advance(cursor, 0); | |
| 1050 | + continue; | |
| 1051 | + } | |
| 1052 | + | |
| 1053 | + page = ceph_msg_data_next(cursor, &off, &len, NULL); | |
| 1054 | + ret = ceph_tcp_recvpage(con->sock, con->bounce_page, 0, len); | |
| 1055 | + if (ret <= 0) { | |
| 1056 | + con->in_data_crc = crc; | |
| 1057 | + return ret; | |
| 1058 | + } | |
| 1059 | + | |
| 1060 | + crc = crc32c(crc, page_address(con->bounce_page), ret); | |
| 1061 | + memcpy_to_page(page, off, page_address(con->bounce_page), ret); | |
| 1062 | + | |
| 1063 | + ceph_msg_data_advance(cursor, ret); | |
| 1064 | + } | |
| 1065 | + con->in_data_crc = crc; | |
| 1066 | + | |
| 1067 | + return 1; /* must return > 0 to indicate success */ | |
| 1068 | +} | |
| 1069 | + | |
| 1034 | 1070 | /* |
| 1035 | 1071 | * read (part of) a message. |
| 1036 | 1072 | */ |
| @@ -1141,7 +1177,13 @@ static int read_partial_message(struct ceph_connection *con) · 104 unmodified lines | ||
| 1141 | 1177 | |
| 1142 | 1178 | /* (page) data */ |
| 1143 | 1179 | if (data_len) { |
| 1144 | − ret = read_partial_msg_data(con); | |
| 1180 | + if (!m->num_data_items) | |
| 1181 | + return -EIO; | |
| 1182 | + | |
| 1183 | + if (ceph_test_opt(from_msgr(con->msgr), RXBOUNCE)) | |
| 1184 | + ret = read_partial_msg_data_bounce(con); | |
| 1185 | + else | |
| 1186 | + ret = read_partial_msg_data(con); | |
| 1145 | 1187 | if (ret <= 0) |
| 1146 | 1188 | return ret; |
| 1147 | 1189 | } |
| @@ -57,8 +57,9 @@ · 56 unmodified lines | ||
| 57 | 57 | #define IN_S_HANDLE_CONTROL_REMAINDER 3 |
| 58 | 58 | #define IN_S_PREPARE_READ_DATA 4 |
| 59 | 59 | #define IN_S_PREPARE_READ_DATA_CONT 5 |
| 60 | −#define IN_S_HANDLE_EPILOGUE 6 | |
| 61 | −#define IN_S_FINISH_SKIP 7 | |
| 60 | +#define IN_S_PREPARE_READ_ENC_PAGE 6 | |
| 61 | +#define IN_S_HANDLE_EPILOGUE 7 | |
| 62 | +#define IN_S_FINISH_SKIP 8 | |
| 62 | 63 | |
| 63 | 64 | #define OUT_S_QUEUE_DATA 1 |
| 64 | 65 | #define OUT_S_QUEUE_DATA_CONT 2 |
| @@ -1032,22 +1033,41 @@ static int decrypt_control_remainder(struct ceph_connection *con) · 967 unmodified lines | ||
| 1032 | 1033 | padded_len(rem_len) + CEPH_GCM_TAG_LEN); |
| 1033 | 1034 | } |
| 1034 | 1035 | |
| 1035 | −static int decrypt_message(struct ceph_connection *con) | |
| 1036 | +static int decrypt_tail(struct ceph_connection *con) | |
| 1036 | 1037 | { |
| 1038 | + struct sg_table enc_sgt = {}; | |
| 1037 | 1039 | struct sg_table sgt = {}; |
| 1040 | + int tail_len; | |
| 1038 | 1041 | int ret; |
| 1039 | 1042 | |
| 1043 | + tail_len = tail_onwire_len(con->in_msg, true); | |
| 1044 | + ret = sg_alloc_table_from_pages(&enc_sgt, con->v2.in_enc_pages, | |
| 1045 | + con->v2.in_enc_page_cnt, 0, tail_len, | |
| 1046 | + GFP_NOIO); | |
| 1047 | + if (ret) | |
| 1048 | + goto out; | |
| 1049 | + | |
| 1040 | 1050 | ret = setup_message_sgs(&sgt, con->in_msg, FRONT_PAD(con->v2.in_buf), |
| 1041 | 1051 | MIDDLE_PAD(con->v2.in_buf), DATA_PAD(con->v2.in_buf), |
| 1042 | 1052 | con->v2.in_buf, true); |
| 1043 | 1053 | if (ret) |
| 1044 | 1054 | goto out; |
| 1045 | 1055 | |
| 1046 | − ret = gcm_crypt(con, false, sgt.sgl, sgt.sgl, | |
| 1047 | − tail_onwire_len(con->in_msg, true)); | |
| 1056 | + dout("%s con %p msg %p enc_page_cnt %d sg_cnt %d\n", __func__, con, | |
| 1057 | + con->in_msg, con->v2.in_enc_page_cnt, sgt.orig_nents); | |
| 1058 | + ret = gcm_crypt(con, false, enc_sgt.sgl, sgt.sgl, tail_len); | |
| 1059 | + if (ret) | |
| 1060 | + goto out; | |
| 1061 | + | |
| 1062 | + WARN_ON(!con->v2.in_enc_page_cnt); | |
| 1063 | + ceph_release_page_vector(con->v2.in_enc_pages, | |
| 1064 | + con->v2.in_enc_page_cnt); | |
| 1065 | + con->v2.in_enc_pages = NULL; | |
| 1066 | + con->v2.in_enc_page_cnt = 0; | |
| 1048 | 1067 | |
| 1049 | 1068 | out: |
| 1050 | 1069 | sg_free_table(&sgt); |
| 1070 | + sg_free_table(&enc_sgt); | |
| 1051 | 1071 | return ret; |
| 1052 | 1072 | } |
| 1053 | 1073 | |
| @@ -1733,54 +1753,157 @@ static int prepare_read_control_remainder(struct ceph_connection *con) · 679 unmodified lines | ||
| 1733 | 1753 | return 0; |
| 1734 | 1754 | } |
| 1735 | 1755 | |
| 1736 | −static void prepare_read_data(struct ceph_connection *con) | |
| 1756 | +static int prepare_read_data(struct ceph_connection *con) | |
| 1737 | 1757 | { |
| 1738 | 1758 | struct bio_vec bv; |
| 1739 | 1759 | |
| 1740 | − if (!con_secure(con)) | |
| 1741 | − con->in_data_crc = -1; | |
| 1760 | + con->in_data_crc = -1; | |
| 1742 | 1761 | ceph_msg_data_cursor_init(&con->v2.in_cursor, con->in_msg, |
| 1743 | 1762 | data_len(con->in_msg)); |
| 1744 | 1763 | |
| 1745 | 1764 | get_bvec_at(&con->v2.in_cursor, &bv); |
| 1746 | − set_in_bvec(con, &bv); | |
| 1765 | + if (ceph_test_opt(from_msgr(con->msgr), RXBOUNCE)) { | |
| 1766 | + if (unlikely(!con->bounce_page)) { | |
| 1767 | + con->bounce_page = alloc_page(GFP_NOIO); | |
| 1768 | + if (!con->bounce_page) { | |
| 1769 | + pr_err("failed to allocate bounce page\n"); | |
| 1770 | + return -ENOMEM; | |
| 1771 | + } | |
| 1772 | + } | |
| 1773 | + | |
| 1774 | + bv.bv_page = con->bounce_page; | |
| 1775 | + bv.bv_offset = 0; | |
| 1776 | + set_in_bvec(con, &bv); | |
| 1777 | + } else { | |
| 1778 | + set_in_bvec(con, &bv); | |
| 1779 | + } | |
| 1747 | 1780 | con->v2.in_state = IN_S_PREPARE_READ_DATA_CONT; |
| 1781 | + return 0; | |
| 1748 | 1782 | } |
| 1749 | 1783 | |
| 1750 | 1784 | static void prepare_read_data_cont(struct ceph_connection *con) |
| 1751 | 1785 | { |
| 1752 | 1786 | struct bio_vec bv; |
| 1753 | 1787 | |
| 1754 | − if (!con_secure(con)) | |
| 1788 | + if (ceph_test_opt(from_msgr(con->msgr), RXBOUNCE)) { | |
| 1789 | + con->in_data_crc = crc32c(con->in_data_crc, | |
| 1790 | + page_address(con->bounce_page), | |
| 1791 | + con->v2.in_bvec.bv_len); | |
| 1792 | + | |
| 1793 | + get_bvec_at(&con->v2.in_cursor, &bv); | |
| 1794 | + memcpy_to_page(bv.bv_page, bv.bv_offset, | |
| 1795 | + page_address(con->bounce_page), | |
| 1796 | + con->v2.in_bvec.bv_len); | |
| 1797 | + } else { | |
| 1755 | 1798 | con->in_data_crc = ceph_crc32c_page(con->in_data_crc, |
| 1756 | 1799 | con->v2.in_bvec.bv_page, |
| 1757 | 1800 | con->v2.in_bvec.bv_offset, |
| 1758 | 1801 | con->v2.in_bvec.bv_len); |
| 1802 | + } | |
| 1759 | 1803 | |
| 1760 | 1804 | ceph_msg_data_advance(&con->v2.in_cursor, con->v2.in_bvec.bv_len); |
| 1761 | 1805 | if (con->v2.in_cursor.total_resid) { |
| 1762 | 1806 | get_bvec_at(&con->v2.in_cursor, &bv); |
| 1763 | − set_in_bvec(con, &bv); | |
| 1807 | + if (ceph_test_opt(from_msgr(con->msgr), RXBOUNCE)) { | |
| 1808 | + bv.bv_page = con->bounce_page; | |
| 1809 | + bv.bv_offset = 0; | |
| 1810 | + set_in_bvec(con, &bv); | |
| 1811 | + } else { | |
| 1812 | + set_in_bvec(con, &bv); | |
| 1813 | + } | |
| 1764 | 1814 | WARN_ON(con->v2.in_state != IN_S_PREPARE_READ_DATA_CONT); |
| 1765 | 1815 | return; |
| 1766 | 1816 | } |
| 1767 | 1817 | |
| 1768 | 1818 | /* |
| 1769 | − * We've read all data. Prepare to read data padding (if any) | |
| 1770 | − * and epilogue. | |
| 1819 | + * We've read all data. Prepare to read epilogue. | |
| 1771 | 1820 | */ |
| 1772 | 1821 | reset_in_kvecs(con); |
| 1773 | − if (con_secure(con)) { | |
| 1774 | − if (need_padding(data_len(con->in_msg))) | |
| 1775 | − add_in_kvec(con, DATA_PAD(con->v2.in_buf), | |
| 1776 | − padding_len(data_len(con->in_msg))); | |
| 1777 | − add_in_kvec(con, con->v2.in_buf, CEPH_EPILOGUE_SECURE_LEN); | |
| 1822 | + add_in_kvec(con, con->v2.in_buf, CEPH_EPILOGUE_PLAIN_LEN); | |
| 1823 | + con->v2.in_state = IN_S_HANDLE_EPILOGUE; | |
| 1824 | +} | |
| 1825 | + | |
| 1826 | +static int prepare_read_tail_plain(struct ceph_connection *con) | |
| 1827 | +{ | |
| 1828 | + struct ceph_msg *msg = con->in_msg; | |
| 1829 | + | |
| 1830 | + if (!front_len(msg) && !middle_len(msg)) { | |
| 1831 | + WARN_ON(!data_len(msg)); | |
| 1832 | + return prepare_read_data(con); | |
| 1833 | + } | |
| 1834 | + | |
| 1835 | + reset_in_kvecs(con); | |
| 1836 | + if (front_len(msg)) { | |
| 1837 | + add_in_kvec(con, msg->front.iov_base, front_len(msg)); | |
| 1838 | + WARN_ON(msg->front.iov_len != front_len(msg)); | |
| 1839 | + } | |
| 1840 | + if (middle_len(msg)) { | |
| 1841 | + add_in_kvec(con, msg->middle->vec.iov_base, middle_len(msg)); | |
| 1842 | + WARN_ON(msg->middle->vec.iov_len != middle_len(msg)); | |
| 1843 | + } | |
| 1844 | + | |
| 1845 | + if (data_len(msg)) { | |
| 1846 | + con->v2.in_state = IN_S_PREPARE_READ_DATA; | |
| 1778 | 1847 | } else { |
| 1779 | 1848 | add_in_kvec(con, con->v2.in_buf, CEPH_EPILOGUE_PLAIN_LEN); |
| 1849 | + con->v2.in_state = IN_S_HANDLE_EPILOGUE; | |
| 1780 | 1850 | } |
| 1851 | + return 0; | |
| 1852 | +} | |
| 1853 | + | |
| 1854 | +static void prepare_read_enc_page(struct ceph_connection *con) | |
| 1855 | +{ | |
| 1856 | + struct bio_vec bv; | |
| 1857 | + | |
| 1858 | + dout("%s con %p i %d resid %d\n", __func__, con, con->v2.in_enc_i, | |
| 1859 | + con->v2.in_enc_resid); | |
| 1860 | + WARN_ON(!con->v2.in_enc_resid); | |
| 1861 | + | |
| 1862 | + bv.bv_page = con->v2.in_enc_pages[con->v2.in_enc_i]; | |
| 1863 | + bv.bv_offset = 0; | |
| 1864 | + bv.bv_len = min(con->v2.in_enc_resid, (int)PAGE_SIZE); | |
| 1865 | + | |
| 1866 | + set_in_bvec(con, &bv); | |
| 1867 | + con->v2.in_enc_i++; | |
| 1868 | + con->v2.in_enc_resid -= bv.bv_len; | |
| 1869 | + | |
| 1870 | + if (con->v2.in_enc_resid) { | |
| 1871 | + con->v2.in_state = IN_S_PREPARE_READ_ENC_PAGE; | |
| 1872 | + return; | |
| 1873 | + } | |
| 1874 | + | |
| 1875 | + /* | |
| 1876 | + * We are set to read the last piece of ciphertext (ending | |
| 1877 | + * with epilogue) + auth tag. | |
| 1878 | + */ | |
| 1879 | + WARN_ON(con->v2.in_enc_i != con->v2.in_enc_page_cnt); | |
| 1781 | 1880 | con->v2.in_state = IN_S_HANDLE_EPILOGUE; |
| 1782 | 1881 | } |
| 1783 | 1882 | |
| 1883 | +static int prepare_read_tail_secure(struct ceph_connection *con) | |
| 1884 | +{ | |
| 1885 | + struct page **enc_pages; | |
| 1886 | + int enc_page_cnt; | |
| 1887 | + int tail_len; | |
| 1888 | + | |
| 1889 | + tail_len = tail_onwire_len(con->in_msg, true); | |
| 1890 | + WARN_ON(!tail_len); | |
| 1891 | + | |
| 1892 | + enc_page_cnt = calc_pages_for(0, tail_len); | |
| 1893 | + enc_pages = ceph_alloc_page_vector(enc_page_cnt, GFP_NOIO); | |
| 1894 | + if (IS_ERR(enc_pages)) | |
| 1895 | + return PTR_ERR(enc_pages); | |
| 1896 | + | |
| 1897 | + WARN_ON(con->v2.in_enc_pages || con->v2.in_enc_page_cnt); | |
| 1898 | + con->v2.in_enc_pages = enc_pages; | |
| 1899 | + con->v2.in_enc_page_cnt = enc_page_cnt; | |
| 1900 | + con->v2.in_enc_resid = tail_len; | |
| 1901 | + con->v2.in_enc_i = 0; | |
| 1902 | + | |
| 1903 | + prepare_read_enc_page(con); | |
| 1904 | + return 0; | |
| 1905 | +} | |
| 1906 | + | |
| 1784 | 1907 | static void __finish_skip(struct ceph_connection *con) |
| 1785 | 1908 | { |
| 1786 | 1909 | con->in_seq++; |
| @@ -2589,47 +2712,26 @@ static int __handle_control(struct ceph_connection *con, void *p) · 802 unmodified lines | ||
| 2589 | 2712 | } |
| 2590 | 2713 | |
| 2591 | 2714 | msg = con->in_msg; /* set in process_message_header() */ |
| 2592 | − if (!front_len(msg) && !middle_len(msg)) { | |
| 2593 | − if (!data_len(msg)) | |
| 2594 | − return process_message(con); | |
| 2595 | − | |
| 2596 | − prepare_read_data(con); | |
| 2597 | − return 0; | |
| 2598 | − } | |
| 2599 | − | |
| 2600 | − reset_in_kvecs(con); | |
| 2601 | 2715 | if (front_len(msg)) { |
| 2602 | 2716 | WARN_ON(front_len(msg) > msg->front_alloc_len); |
| 2603 | − add_in_kvec(con, msg->front.iov_base, front_len(msg)); | |
| 2604 | 2717 | msg->front.iov_len = front_len(msg); |
| 2605 | − | |
| 2606 | − if (con_secure(con) && need_padding(front_len(msg))) | |
| 2607 | − add_in_kvec(con, FRONT_PAD(con->v2.in_buf), | |
| 2608 | − padding_len(front_len(msg))); | |
| 2609 | 2718 | } else { |
| 2610 | 2719 | msg->front.iov_len = 0; |
| 2611 | 2720 | } |
| 2612 | 2721 | if (middle_len(msg)) { |
| 2613 | 2722 | WARN_ON(middle_len(msg) > msg->middle->alloc_len); |
| 2614 | − add_in_kvec(con, msg->middle->vec.iov_base, middle_len(msg)); | |
| 2615 | 2723 | msg->middle->vec.iov_len = middle_len(msg); |
| 2616 | − | |
| 2617 | − if (con_secure(con) && need_padding(middle_len(msg))) | |
| 2618 | − add_in_kvec(con, MIDDLE_PAD(con->v2.in_buf), | |
| 2619 | − padding_len(middle_len(msg))); | |
| 2620 | 2724 | } else if (msg->middle) { |
| 2621 | 2725 | msg->middle->vec.iov_len = 0; |
| 2622 | 2726 | } |
| 2623 | 2727 | |
| 2624 | − if (data_len(msg)) { | |
| 2625 | − con->v2.in_state = IN_S_PREPARE_READ_DATA; | |
| 2626 | − } else { | |
| 2627 | − add_in_kvec(con, con->v2.in_buf, | |
| 2628 | − con_secure(con) ? CEPH_EPILOGUE_SECURE_LEN : | |
| 2629 | − CEPH_EPILOGUE_PLAIN_LEN); | |
| 2630 | − con->v2.in_state = IN_S_HANDLE_EPILOGUE; | |
| 2631 | − } | |
| 2632 | − return 0; | |
| 2728 | + if (!front_len(msg) && !middle_len(msg) && !data_len(msg)) | |
| 2729 | + return process_message(con); | |
| 2730 | + | |
| 2731 | + if (con_secure(con)) | |
| 2732 | + return prepare_read_tail_secure(con); | |
| 2733 | + | |
| 2734 | + return prepare_read_tail_plain(con); | |
| 2633 | 2735 | } |
| 2634 | 2736 | |
| 2635 | 2737 | static int handle_preamble(struct ceph_connection *con) |
| @@ -2717,7 +2819,7 @@ static int handle_epilogue(struct ceph_connection *con) · 81 unmodified lines | ||
| 2717 | 2819 | int ret; |
| 2718 | 2820 | |
| 2719 | 2821 | if (con_secure(con)) { |
| 2720 | − ret = decrypt_message(con); | |
| 2822 | + ret = decrypt_tail(con); | |
| 2721 | 2823 | if (ret) { |
| 2722 | 2824 | if (ret == -EBADMSG) |
| 2723 | 2825 | con->error_msg = "integrity error, bad epilogue auth tag"; |
| @@ -2785,13 +2887,16 @@ static int populate_in_iter(struct ceph_connection *con) · 61 unmodified lines | ||
| 2785 | 2887 | ret = handle_control_remainder(con); |
| 2786 | 2888 | break; |
| 2787 | 2889 | case IN_S_PREPARE_READ_DATA: |
| 2788 | − prepare_read_data(con); | |
| 2789 | − ret = 0; | |
| 2890 | + ret = prepare_read_data(con); | |
| 2790 | 2891 | break; |
| 2791 | 2892 | case IN_S_PREPARE_READ_DATA_CONT: |
| 2792 | 2893 | prepare_read_data_cont(con); |
| 2793 | 2894 | ret = 0; |
| 2794 | 2895 | break; |
| 2896 | + case IN_S_PREPARE_READ_ENC_PAGE: | |
| 2897 | + prepare_read_enc_page(con); | |
| 2898 | + ret = 0; | |
| 2899 | + break; | |
| 2795 | 2900 | case IN_S_HANDLE_EPILOGUE: |
| 2796 | 2901 | ret = handle_epilogue(con); |
| 2797 | 2902 | break; |
| @@ -3326,20 +3431,16 @@ void ceph_con_v2_revoke(struct ceph_connection *con) · 528 unmodified lines | ||
| 3326 | 3431 | |
| 3327 | 3432 | static void revoke_at_prepare_read_data(struct ceph_connection *con) |
| 3328 | 3433 | { |
| 3329 | − int remaining; /* data + [data padding] + epilogue */ | |
| 3434 | + int remaining; | |
| 3330 | 3435 | int resid; |
| 3331 | 3436 | |
| 3437 | + WARN_ON(con_secure(con)); | |
| 3332 | 3438 | WARN_ON(!data_len(con->in_msg)); |
| 3333 | 3439 | WARN_ON(!iov_iter_is_kvec(&con->v2.in_iter)); |
| 3334 | 3440 | resid = iov_iter_count(&con->v2.in_iter); |
| 3335 | 3441 | WARN_ON(!resid); |
| 3336 | 3442 | |
| 3337 | − if (con_secure(con)) | |
| 3338 | − remaining = padded_len(data_len(con->in_msg)) + | |
| 3339 | − CEPH_EPILOGUE_SECURE_LEN; | |
| 3340 | − else | |
| 3341 | − remaining = data_len(con->in_msg) + CEPH_EPILOGUE_PLAIN_LEN; | |
| 3342 | − | |
| 3443 | + remaining = data_len(con->in_msg) + CEPH_EPILOGUE_PLAIN_LEN; | |
| 3343 | 3444 | dout("%s con %p resid %d remaining %d\n", __func__, con, resid, |
| 3344 | 3445 | remaining); |
| 3345 | 3446 | con->v2.in_iter.count -= resid; |
| @@ -3350,8 +3451,9 @@ static void revoke_at_prepare_read_data(struct ceph_connection *con) · 4 unmodified lines | ||
| 3350 | 3451 | static void revoke_at_prepare_read_data_cont(struct ceph_connection *con) |
| 3351 | 3452 | { |
| 3352 | 3453 | int recved, resid; /* current piece of data */ |
| 3353 | − int remaining; /* [data padding] + epilogue */ | |
| 3454 | + int remaining; | |
| 3354 | 3455 | |
| 3456 | + WARN_ON(con_secure(con)); | |
| 3355 | 3457 | WARN_ON(!data_len(con->in_msg)); |
| 3356 | 3458 | WARN_ON(!iov_iter_is_bvec(&con->v2.in_iter)); |
| 3357 | 3459 | resid = iov_iter_count(&con->v2.in_iter); |
| @@ -3363,12 +3465,7 @@ static void revoke_at_prepare_read_data_cont(struct ceph_connection *con) · 5 unmodified lines | ||
| 3363 | 3465 | ceph_msg_data_advance(&con->v2.in_cursor, recved); |
| 3364 | 3466 | WARN_ON(resid > con->v2.in_cursor.total_resid); |
| 3365 | 3467 | |
| 3366 | − if (con_secure(con)) | |
| 3367 | − remaining = padding_len(data_len(con->in_msg)) + | |
| 3368 | − CEPH_EPILOGUE_SECURE_LEN; | |
| 3369 | − else | |
| 3370 | − remaining = CEPH_EPILOGUE_PLAIN_LEN; | |
| 3371 | − | |
| 3468 | + remaining = CEPH_EPILOGUE_PLAIN_LEN; | |
| 3372 | 3469 | dout("%s con %p total_resid %zu remaining %d\n", __func__, con, |
| 3373 | 3470 | con->v2.in_cursor.total_resid, remaining); |
| 3374 | 3471 | con->v2.in_iter.count -= resid; |
| @@ -3376,11 +3473,26 @@ static void revoke_at_prepare_read_data_cont(struct ceph_connection *con) · 1 unmodified line | ||
| 3376 | 3473 | con->v2.in_state = IN_S_FINISH_SKIP; |
| 3377 | 3474 | } |
| 3378 | 3475 | |
| 3476 | +static void revoke_at_prepare_read_enc_page(struct ceph_connection *con) | |
| 3477 | +{ | |
| 3478 | + int resid; /* current enc page (not necessarily data) */ | |
| 3479 | + | |
| 3480 | + WARN_ON(!con_secure(con)); | |
| 3481 | + WARN_ON(!iov_iter_is_bvec(&con->v2.in_iter)); | |
| 3482 | + resid = iov_iter_count(&con->v2.in_iter); | |
| 3483 | + WARN_ON(!resid || resid > con->v2.in_bvec.bv_len); | |
| 3484 | + | |
| 3485 | + dout("%s con %p resid %d enc_resid %d\n", __func__, con, resid, | |
| 3486 | + con->v2.in_enc_resid); | |
| 3487 | + con->v2.in_iter.count -= resid; | |
| 3488 | + set_in_skip(con, resid + con->v2.in_enc_resid); | |
| 3489 | + con->v2.in_state = IN_S_FINISH_SKIP; | |
| 3490 | +} | |
| 3491 | + | |
| 3379 | 3492 | static void revoke_at_handle_epilogue(struct ceph_connection *con) |
| 3380 | 3493 | { |
| 3381 | 3494 | int resid; |
| 3382 | 3495 | |
| 3383 | − WARN_ON(!iov_iter_is_kvec(&con->v2.in_iter)); | |
| 3384 | 3496 | resid = iov_iter_count(&con->v2.in_iter); |
| 3385 | 3497 | WARN_ON(!resid); |
| 3386 | 3498 | |
| @@ -3399,6 +3511,9 @@ void ceph_con_v2_revoke_incoming(struct ceph_connection *con) · 12 unmodified lines | ||
| 3399 | 3511 | case IN_S_PREPARE_READ_DATA_CONT: |
| 3400 | 3512 | revoke_at_prepare_read_data_cont(con); |
| 3401 | 3513 | break; |
| 3514 | + case IN_S_PREPARE_READ_ENC_PAGE: | |
| 3515 | + revoke_at_prepare_read_enc_page(con); | |
| 3516 | + break; | |
| 3402 | 3517 | case IN_S_HANDLE_EPILOGUE: |
| 3403 | 3518 | revoke_at_handle_epilogue(con); |
| 3404 | 3519 | break; |
| @@ -3432,6 +3547,13 @@ void ceph_con_v2_reset_protocol(struct ceph_connection *con) · 27 unmodified lines | ||
| 3432 | 3547 | clear_out_sign_kvecs(con); |
| 3433 | 3548 | free_conn_bufs(con); |
| 3434 | 3549 | |
| 3550 | + if (con->v2.in_enc_pages) { | |
| 3551 | + WARN_ON(!con->v2.in_enc_page_cnt); | |
| 3552 | + ceph_release_page_vector(con->v2.in_enc_pages, | |
| 3553 | + con->v2.in_enc_page_cnt); | |
| 3554 | + con->v2.in_enc_pages = NULL; | |
| 3555 | + con->v2.in_enc_page_cnt = 0; | |
| 3556 | + } | |
| 3435 | 3557 | if (con->v2.out_enc_pages) { |
| 3436 | 3558 | WARN_ON(!con->v2.out_enc_page_cnt); |
| 3437 | 3559 | ceph_release_page_vector(con->v2.out_enc_pages, |
| @@ -681,7 +681,7 @@ exit: · 680 unmodified lines | ||
| 681 | 681 | * while trying to recycle fragments on __skb_frag_unref() we need |
| 682 | 682 | * to make one SKB responsible for triggering the recycle path. |
| 683 | 683 | * So disable the recycling bit if an SKB is cloned and we have |
| 684 | − * additional references to to the fragmented part of the SKB. | |
| 684 | + * additional references to the fragmented part of the SKB. | |
| 685 | 685 | * Eventually the last SKB will have the recycling bit set and it's |
| 686 | 686 | * dataref set to 0, which will trigger the recycling |
| 687 | 687 | */ |
| @@ -1784,7 +1784,6 @@ EXPORT_SYMBOL_GPL(dsa_unregister_switch); · 1783 unmodified lines | ||
| 1784 | 1784 | void dsa_switch_shutdown(struct dsa_switch *ds) |
| 1785 | 1785 | { |
| 1786 | 1786 | struct net_device *master, *slave_dev; |
| 1787 | − LIST_HEAD(unregister_list); | |
| 1788 | 1787 | struct dsa_port *dp; |
| 1789 | 1788 | |
| 1790 | 1789 | mutex_lock(&dsa2_mutex); |
| @@ -1795,25 +1794,13 @@ void dsa_switch_shutdown(struct dsa_switch *ds) · 4 unmodified lines | ||
| 1795 | 1794 | slave_dev = dp->slave; |
| 1796 | 1795 | |
| 1797 | 1796 | netdev_upper_dev_unlink(master, slave_dev); |
| 1798 | − /* Just unlinking ourselves as uppers of the master is not | |
| 1799 | − * sufficient. When the master net device unregisters, that will | |
| 1800 | − * also call dev_close, which we will catch as NETDEV_GOING_DOWN | |
| 1801 | − * and trigger a dev_close on our own devices (dsa_slave_close). | |
| 1802 | − * In turn, that will call dev_mc_unsync on the master's net | |
| 1803 | − * device. If the master is also a DSA switch port, this will | |
| 1804 | − * trigger dsa_slave_set_rx_mode which will call dev_mc_sync on | |
| 1805 | − * its own master. Lockdep will complain about the fact that | |
| 1806 | − * all cascaded masters have the same dsa_master_addr_list_lock_key, | |
| 1807 | − * which it normally would not do if the cascaded masters would | |
| 1808 | − * be in a proper upper/lower relationship, which we've just | |
| 1809 | − * destroyed. | |
| 1810 | − * To suppress the lockdep warnings, let's actually unregister | |
| 1811 | − * the DSA slave interfaces too, to avoid the nonsensical | |
| 1812 | − * multicast address list synchronization on shutdown. | |
| 1813 | − */ | |
| 1814 | − unregister_netdevice_queue(slave_dev, &unregister_list); | |
| 1815 | 1797 | } |
| 1816 | − unregister_netdevice_many(&unregister_list); | |
| 1798 | + | |
| 1799 | + /* Disconnect from further netdevice notifiers on the master, | |
| 1800 | + * since netdev_uses_dsa() will now return false. | |
| 1801 | + */ | |
| 1802 | + dsa_switch_for_each_cpu_port(dp, ds) | |
| 1803 | + dp->master->dsa_ptr = NULL; | |
| 1817 | 1804 | |
| 1818 | 1805 | rtnl_unlock(); |
| 1819 | 1806 | mutex_unlock(&dsa2_mutex); |
| @@ -256,7 +256,9 @@ static int __net_init ipmr_rules_init(struct net *net) · 255 unmodified lines | ||
| 256 | 256 | return 0; |
| 257 | 257 | |
| 258 | 258 | err2: |
| 259 | + rtnl_lock(); | |
| 259 | 260 | ipmr_free_table(mrt); |
| 261 | + rtnl_unlock(); | |
| 260 | 262 | err1: |
| 261 | 263 | fib_rules_unregister(ops); |
| 262 | 264 | return err; |
| @@ -936,6 +936,22 @@ void tcp_remove_empty_skb(struct sock *sk) · 935 unmodified lines | ||
| 936 | 936 | } |
| 937 | 937 | } |
| 938 | 938 | |
| 939 | +/* skb changing from pure zc to mixed, must charge zc */ | |
| 940 | +static int tcp_downgrade_zcopy_pure(struct sock *sk, struct sk_buff *skb) | |
| 941 | +{ | |
| 942 | + if (unlikely(skb_zcopy_pure(skb))) { | |
| 943 | + u32 extra = skb->truesize - | |
| 944 | + SKB_TRUESIZE(skb_end_offset(skb)); | |
| 945 | + | |
| 946 | + if (!sk_wmem_schedule(sk, extra)) | |
| 947 | + return -ENOMEM; | |
| 948 | + | |
| 949 | + sk_mem_charge(sk, extra); | |
| 950 | + skb_shinfo(skb)->flags &= ~SKBFL_PURE_ZEROCOPY; | |
| 951 | + } | |
| 952 | + return 0; | |
| 953 | +} | |
| 954 | + | |
| 939 | 955 | static struct sk_buff *tcp_build_frag(struct sock *sk, int size_goal, int flags, |
| 940 | 956 | struct page *page, int offset, size_t *size) |
| 941 | 957 | { |
| @@ -971,7 +987,7 @@ new_segment: · 29 unmodified lines | ||
| 971 | 987 | tcp_mark_push(tp, skb); |
| 972 | 988 | goto new_segment; |
| 973 | 989 | } |
| 974 | − if (!sk_wmem_schedule(sk, copy)) | |
| 990 | + if (tcp_downgrade_zcopy_pure(sk, skb) || !sk_wmem_schedule(sk, copy)) | |
| 975 | 991 | return NULL; |
| 976 | 992 | |
| 977 | 993 | if (can_coalesce) { |
| @@ -1319,19 +1335,8 @@ new_segment: · 341 unmodified lines | ||
| 1319 | 1335 | |
| 1320 | 1336 | copy = min_t(int, copy, pfrag->size - pfrag->offset); |
| 1321 | 1337 | |
| 1322 | − /* skb changing from pure zc to mixed, must charge zc */ | |
| 1323 | − if (unlikely(skb_zcopy_pure(skb))) { | |
| 1324 | − u32 extra = skb->truesize - | |
| 1325 | − SKB_TRUESIZE(skb_end_offset(skb)); | |
| 1326 | − | |
| 1327 | − if (!sk_wmem_schedule(sk, extra)) | |
| 1328 | − goto wait_for_space; | |
| 1329 | − | |
| 1330 | − sk_mem_charge(sk, extra); | |
| 1331 | − skb_shinfo(skb)->flags &= ~SKBFL_PURE_ZEROCOPY; | |
| 1332 | − } | |
| 1333 | − | |
| 1334 | − if (!sk_wmem_schedule(sk, copy)) | |
| 1338 | + if (tcp_downgrade_zcopy_pure(sk, skb) || | |
| 1339 | + !sk_wmem_schedule(sk, copy)) | |
| 1335 | 1340 | goto wait_for_space; |
| 1336 | 1341 | |
| 1337 | 1342 | err = skb_copy_to_page_nocache(sk, &msg->msg_iter, skb, |
| @@ -243,7 +243,9 @@ static int __net_init ip6mr_rules_init(struct net *net) · 242 unmodified lines | ||
| 243 | 243 | return 0; |
| 244 | 244 | |
| 245 | 245 | err2: |
| 246 | + rtnl_lock(); | |
| 246 | 247 | ip6mr_free_table(mrt); |
| 248 | + rtnl_unlock(); | |
| 247 | 249 | err1: |
| 248 | 250 | fib_rules_unregister(ops); |
| 249 | 251 | return err; |
| @@ -1607,6 +1607,7 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, · 1606 unmodified lines | ||
| 1607 | 1607 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
| 1608 | 1608 | struct mpls_dev *mdev; |
| 1609 | 1609 | unsigned int flags; |
| 1610 | + int err; | |
| 1610 | 1611 | |
| 1611 | 1612 | if (event == NETDEV_REGISTER) { |
| 1612 | 1613 | mdev = mpls_add_dev(dev); |
| @@ -1621,7 +1622,6 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, · 8 unmodified lines | ||
| 1621 | 1622 | return NOTIFY_OK; |
| 1622 | 1623 | |
| 1623 | 1624 | switch (event) { |
| 1624 | − int err; | |
| 1625 | 1625 | |
| 1626 | 1626 | case NETDEV_DOWN: |
| 1627 | 1627 | err = mpls_ifdown(dev, event); |
| @@ -925,6 +925,7 @@ out: · 924 unmodified lines | ||
| 925 | 925 | static int mptcp_pm_nl_create_listen_socket(struct sock *sk, |
| 926 | 926 | struct mptcp_pm_addr_entry *entry) |
| 927 | 927 | { |
| 928 | + int addrlen = sizeof(struct sockaddr_in); | |
| 928 | 929 | struct sockaddr_storage addr; |
| 929 | 930 | struct mptcp_sock *msk; |
| 930 | 931 | struct socket *ssock; |
| @@ -949,8 +950,11 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk, · 18 unmodified lines | ||
| 949 | 950 | } |
| 950 | 951 | |
| 951 | 952 | mptcp_info2sockaddr(&entry->addr, &addr, entry->addr.family); |
| 952 | − err = kernel_bind(ssock, (struct sockaddr *)&addr, | |
| 953 | − sizeof(struct sockaddr_in)); | |
| 953 | +#if IS_ENABLED(CONFIG_MPTCP_IPV6) | |
| 954 | + if (entry->addr.family == AF_INET6) | |
| 955 | + addrlen = sizeof(struct sockaddr_in6); | |
| 956 | +#endif | |
| 957 | + err = kernel_bind(ssock, (struct sockaddr *)&addr, addrlen); | |
| 954 | 958 | if (err) { |
| 955 | 959 | pr_warn("kernel_bind error, err=%d", err); |
| 956 | 960 | goto out; |
| @@ -2321,7 +2321,8 @@ ctnetlink_create_conntrack(struct net *net, · 2320 unmodified lines | ||
| 2321 | 2321 | if (helper->from_nlattr) |
| 2322 | 2322 | helper->from_nlattr(helpinfo, ct); |
| 2323 | 2323 | |
| 2324 | − /* not in hash table yet so not strictly necessary */ | |
| 2324 | + /* disable helper auto-assignment for this entry */ | |
| 2325 | + ct->status |= IPS_HELPER; | |
| 2325 | 2326 | RCU_INIT_POINTER(help->helper, helper); |
| 2326 | 2327 | } |
| 2327 | 2328 | } else { |
| @@ -489,6 +489,15 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 488 unmodified lines | ||
| 489 | 489 | pr_debug("Setting vtag %x for dir %d\n", |
| 490 | 490 | ih->init_tag, !dir); |
| 491 | 491 | ct->proto.sctp.vtag[!dir] = ih->init_tag; |
| 492 | + | |
| 493 | + /* don't renew timeout on init retransmit so | |
| 494 | + * port reuse by client or NAT middlebox cannot | |
| 495 | + * keep entry alive indefinitely (incl. nat info). | |
| 496 | + */ | |
| 497 | + if (new_state == SCTP_CONNTRACK_CLOSED && | |
| 498 | + old_state == SCTP_CONNTRACK_CLOSED && | |
| 499 | + nf_ct_is_confirmed(ct)) | |
| 500 | + ignore = true; | |
| 492 | 501 | } |
| 493 | 502 | |
| 494 | 503 | ct->proto.sctp.state = new_state; |
| @@ -446,6 +446,32 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, · 445 unmodified lines | ||
| 446 | 446 | } |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | +static void tcp_init_sender(struct ip_ct_tcp_state *sender, | |
| 450 | + struct ip_ct_tcp_state *receiver, | |
| 451 | + const struct sk_buff *skb, | |
| 452 | + unsigned int dataoff, | |
| 453 | + const struct tcphdr *tcph, | |
| 454 | + u32 end, u32 win) | |
| 455 | +{ | |
| 456 | + /* SYN-ACK in reply to a SYN | |
| 457 | + * or SYN from reply direction in simultaneous open. | |
| 458 | + */ | |
| 459 | + sender->td_end = | |
| 460 | + sender->td_maxend = end; | |
| 461 | + sender->td_maxwin = (win == 0 ? 1 : win); | |
| 462 | + | |
| 463 | + tcp_options(skb, dataoff, tcph, sender); | |
| 464 | + /* RFC 1323: | |
| 465 | + * Both sides must send the Window Scale option | |
| 466 | + * to enable window scaling in either direction. | |
| 467 | + */ | |
| 468 | + if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE && | |
| 469 | + receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE)) { | |
| 470 | + sender->td_scale = 0; | |
| 471 | + receiver->td_scale = 0; | |
| 472 | + } | |
| 473 | +} | |
| 474 | + | |
| 449 | 475 | static bool tcp_in_window(struct nf_conn *ct, |
| 450 | 476 | enum ip_conntrack_dir dir, |
| 451 | 477 | unsigned int index, |
| @@ -499,24 +525,9 @@ static bool tcp_in_window(struct nf_conn *ct, · 47 unmodified lines | ||
| 499 | 525 | * Initialize sender data. |
| 500 | 526 | */ |
| 501 | 527 | if (tcph->syn) { |
| 502 | − /* | |
| 503 | − * SYN-ACK in reply to a SYN | |
| 504 | − * or SYN from reply direction in simultaneous open. | |
| 505 | − */ | |
| 506 | − sender->td_end = | |
| 507 | − sender->td_maxend = end; | |
| 508 | − sender->td_maxwin = (win == 0 ? 1 : win); | |
| 509 | − | |
| 510 | − tcp_options(skb, dataoff, tcph, sender); | |
| 511 | − /* | |
| 512 | − * RFC 1323: | |
| 513 | − * Both sides must send the Window Scale option | |
| 514 | − * to enable window scaling in either direction. | |
| 515 | − */ | |
| 516 | − if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE | |
| 517 | − && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE)) | |
| 518 | − sender->td_scale = | |
| 519 | − receiver->td_scale = 0; | |
| 528 | + tcp_init_sender(sender, receiver, | |
| 529 | + skb, dataoff, tcph, | |
| 530 | + end, win); | |
| 520 | 531 | if (!tcph->ack) |
| 521 | 532 | /* Simultaneous open */ |
| 522 | 533 | return true; |
| @@ -560,6 +571,18 @@ static bool tcp_in_window(struct nf_conn *ct, · 37 unmodified lines | ||
| 560 | 571 | sender->td_maxwin = (win == 0 ? 1 : win); |
| 561 | 572 | |
| 562 | 573 | tcp_options(skb, dataoff, tcph, sender); |
| 574 | + } else if (tcph->syn && dir == IP_CT_DIR_REPLY && | |
| 575 | + state->state == TCP_CONNTRACK_SYN_SENT) { | |
| 576 | + /* Retransmitted syn-ack, or syn (simultaneous open). | |
| 577 | + * | |
| 578 | + * Re-init state for this direction, just like for the first | |
| 579 | + * syn(-ack) reply, it might differ in seq, ack or tcp options. | |
| 580 | + */ | |
| 581 | + tcp_init_sender(sender, receiver, | |
| 582 | + skb, dataoff, tcph, | |
| 583 | + end, win); | |
| 584 | + if (!tcph->ack) | |
| 585 | + return true; | |
| 563 | 586 | } |
| 564 | 587 | |
| 565 | 588 | if (!(tcph->ack)) { |
| @@ -167,7 +167,7 @@ nft_tcp_header_pointer(const struct nft_pktinfo *pkt, · 166 unmodified lines | ||
| 167 | 167 | { |
| 168 | 168 | struct tcphdr *tcph; |
| 169 | 169 | |
| 170 | − if (pkt->tprot != IPPROTO_TCP) | |
| 170 | + if (pkt->tprot != IPPROTO_TCP || pkt->fragoff) | |
| 171 | 171 | return NULL; |
| 172 | 172 | |
| 173 | 173 | tcph = skb_header_pointer(pkt->skb, nft_thoff(pkt), sizeof(*tcph), buffer); |
| @@ -83,7 +83,7 @@ static int __nft_payload_inner_offset(struct nft_pktinfo *pkt) · 82 unmodified lines | ||
| 83 | 83 | { |
| 84 | 84 | unsigned int thoff = nft_thoff(pkt); |
| 85 | 85 | |
| 86 | − if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) | |
| 86 | + if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff) | |
| 87 | 87 | return -1; |
| 88 | 88 | |
| 89 | 89 | switch (pkt->tprot) { |
| @@ -147,7 +147,7 @@ void nft_payload_eval(const struct nft_expr *expr, · 57 unmodified lines | ||
| 147 | 147 | offset = skb_network_offset(skb); |
| 148 | 148 | break; |
| 149 | 149 | case NFT_PAYLOAD_TRANSPORT_HEADER: |
| 150 | − if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) | |
| 150 | + if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff) | |
| 151 | 151 | goto err; |
| 152 | 152 | offset = nft_thoff(pkt); |
| 153 | 153 | break; |
| @@ -688,7 +688,7 @@ static void nft_payload_set_eval(const struct nft_expr *expr, · 534 unmodified lines | ||
| 688 | 688 | offset = skb_network_offset(skb); |
| 689 | 689 | break; |
| 690 | 690 | case NFT_PAYLOAD_TRANSPORT_HEADER: |
| 691 | − if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) | |
| 691 | + if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff) | |
| 692 | 692 | goto err; |
| 693 | 693 | offset = nft_thoff(pkt); |
| 694 | 694 | break; |
| @@ -728,7 +728,8 @@ static void nft_payload_set_eval(const struct nft_expr *expr, · 33 unmodified lines | ||
| 728 | 728 | if (priv->csum_type == NFT_PAYLOAD_CSUM_SCTP && |
| 729 | 729 | pkt->tprot == IPPROTO_SCTP && |
| 730 | 730 | skb->ip_summed != CHECKSUM_PARTIAL) { |
| 731 | − if (nft_payload_csum_sctp(skb, nft_thoff(pkt))) | |
| 731 | + if (pkt->fragoff == 0 && | |
| 732 | + nft_payload_csum_sctp(skb, nft_thoff(pkt))) | |
| 732 | 733 | goto err; |
| 733 | 734 | } |
| 734 | 735 | |
| @@ -368,9 +368,6 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net, · 367 unmodified lines | ||
| 368 | 368 | new_pe->type = SMC_PNET_ETH; |
| 369 | 369 | memcpy(new_pe->pnet_name, pnet_name, SMC_MAX_PNETID_LEN); |
| 370 | 370 | strncpy(new_pe->eth_name, eth_name, IFNAMSIZ); |
| 371 | − new_pe->ndev = ndev; | |
| 372 | − if (ndev) | |
| 373 | − netdev_tracker_alloc(ndev, &new_pe->dev_tracker, GFP_KERNEL); | |
| 374 | 371 | rc = -EEXIST; |
| 375 | 372 | new_netdev = true; |
| 376 | 373 | write_lock(&pnettable->lock); |
| @@ -382,6 +379,11 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net, · 5 unmodified lines | ||
| 382 | 379 | } |
| 383 | 380 | } |
| 384 | 381 | if (new_netdev) { |
| 382 | + if (ndev) { | |
| 383 | + new_pe->ndev = ndev; | |
| 384 | + netdev_tracker_alloc(ndev, &new_pe->dev_tracker, | |
| 385 | + GFP_ATOMIC); | |
| 386 | + } | |
| 385 | 387 | list_add_tail(&new_pe->list, &pnettable->pnetlist); |
| 386 | 388 | write_unlock(&pnettable->lock); |
| 387 | 389 | } else { |
| @@ -115,11 +115,14 @@ static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj, · 114 unmodified lines | ||
| 115 | 115 | } |
| 116 | 116 | |
| 117 | 117 | sock = container_of(xprt, struct sock_xprt, xprt); |
| 118 | − if (kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0) | |
| 118 | + mutex_lock(&sock->recv_mutex); | |
| 119 | + if (sock->sock == NULL || | |
| 120 | + kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0) | |
| 119 | 121 | goto out; |
| 120 | 122 | |
| 121 | 123 | ret = sprintf(buf, "%pISc\n", &saddr); |
| 122 | 124 | out: |
| 125 | + mutex_unlock(&sock->recv_mutex); | |
| 123 | 126 | xprt_put(xprt); |
| 124 | 127 | return ret + 1; |
| 125 | 128 | } |
| @@ -413,6 +413,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt) · 412 unmodified lines | ||
| 413 | 413 | IB_POLL_WORKQUEUE); |
| 414 | 414 | if (IS_ERR(ep->re_attr.send_cq)) { |
| 415 | 415 | rc = PTR_ERR(ep->re_attr.send_cq); |
| 416 | + ep->re_attr.send_cq = NULL; | |
| 416 | 417 | goto out_destroy; |
| 417 | 418 | } |
| 418 | 419 | |
| @@ -421,6 +422,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt) · 2 unmodified lines | ||
| 421 | 422 | IB_POLL_WORKQUEUE); |
| 422 | 423 | if (IS_ERR(ep->re_attr.recv_cq)) { |
| 423 | 424 | rc = PTR_ERR(ep->re_attr.recv_cq); |
| 425 | + ep->re_attr.recv_cq = NULL; | |
| 424 | 426 | goto out_destroy; |
| 425 | 427 | } |
| 426 | 428 | ep->re_receive_count = 0; |
| @@ -459,6 +461,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt) · 32 unmodified lines | ||
| 459 | 461 | ep->re_pd = ib_alloc_pd(device, 0); |
| 460 | 462 | if (IS_ERR(ep->re_pd)) { |
| 461 | 463 | rc = PTR_ERR(ep->re_pd); |
| 464 | + ep->re_pd = NULL; | |
| 462 | 465 | goto out_destroy; |
| 463 | 466 | } |
| 464 | 467 | |
| @@ -1641,7 +1641,12 @@ static int xs_get_srcport(struct sock_xprt *transport) · 1640 unmodified lines | ||
| 1641 | 1641 | unsigned short get_srcport(struct rpc_xprt *xprt) |
| 1642 | 1642 | { |
| 1643 | 1643 | struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt); |
| 1644 | − return xs_sock_getport(sock->sock); | |
| 1644 | + unsigned short ret = 0; | |
| 1645 | + mutex_lock(&sock->recv_mutex); | |
| 1646 | + if (sock->sock) | |
| 1647 | + ret = xs_sock_getport(sock->sock); | |
| 1648 | + mutex_unlock(&sock->recv_mutex); | |
| 1649 | + return ret; | |
| 1645 | 1650 | } |
| 1646 | 1651 | EXPORT_SYMBOL(get_srcport); |
| 1647 | 1652 | |
| @@ -2200,7 +2200,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, · 2199 unmodified lines | ||
| 2200 | 2200 | struct tipc_msg *hdr = buf_msg(skb); |
| 2201 | 2201 | struct tipc_gap_ack_blks *ga = NULL; |
| 2202 | 2202 | bool reply = msg_probe(hdr), retransmitted = false; |
| 2203 | − u16 dlen = msg_data_sz(hdr), glen = 0; | |
| 2203 | + u32 dlen = msg_data_sz(hdr), glen = 0; | |
| 2204 | 2204 | u16 peers_snd_nxt = msg_next_sent(hdr); |
| 2205 | 2205 | u16 peers_tol = msg_link_tolerance(hdr); |
| 2206 | 2206 | u16 peers_prio = msg_linkprio(hdr); |
| @@ -2214,6 +2214,10 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, · 7 unmodified lines | ||
| 2214 | 2214 | void *data; |
| 2215 | 2215 | |
| 2216 | 2216 | trace_tipc_proto_rcv(skb, false, l->name); |
| 2217 | + | |
| 2218 | + if (dlen > U16_MAX) | |
| 2219 | + goto exit; | |
| 2220 | + | |
| 2217 | 2221 | if (tipc_link_is_blocked(l) || !xmitq) |
| 2218 | 2222 | goto exit; |
| 2219 | 2223 | |
| @@ -2309,7 +2313,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, · 89 unmodified lines | ||
| 2309 | 2313 | |
| 2310 | 2314 | /* Receive Gap ACK blocks from peer if any */ |
| 2311 | 2315 | glen = tipc_get_gap_ack_blks(&ga, l, hdr, true); |
| 2312 | − | |
| 2316 | + if(glen > dlen) | |
| 2317 | + break; | |
| 2313 | 2318 | tipc_mon_rcv(l->net, data + glen, dlen - glen, l->addr, |
| 2314 | 2319 | &l->mon_state, l->bearer_id); |
| 2315 | 2320 | |
| @@ -496,6 +496,8 @@ void tipc_mon_rcv(struct net *net, void *data, u16 dlen, u32 addr, · 495 unmodified lines | ||
| 496 | 496 | state->probing = false; |
| 497 | 497 | |
| 498 | 498 | /* Sanity check received domain record */ |
| 499 | + if (new_member_cnt > MAX_MON_DOMAIN) | |
| 500 | + return; | |
| 499 | 501 | if (dlen < dom_rec_len(arrv_dom, 0)) |
| 500 | 502 | return; |
| 501 | 503 | if (dlen != dom_rec_len(arrv_dom, new_member_cnt)) |
| @@ -313,7 +313,7 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, · 312 unmodified lines | ||
| 313 | 313 | pr_warn_ratelimited("Failed to remove binding %u,%u from %u\n", |
| 314 | 314 | ua.sr.type, ua.sr.lower, node); |
| 315 | 315 | } else { |
| 316 | − pr_warn("Unrecognized name table message received\n"); | |
| 316 | + pr_warn_ratelimited("Unknown name table message received\n"); | |
| 317 | 317 | } |
| 318 | 318 | return false; |
| 319 | 319 | } |
| @@ -109,22 +109,25 @@ int asymmetric_verify(struct key *keyring, const char *sig, · 108 unmodified lines | ||
| 109 | 109 | |
| 110 | 110 | pk = asymmetric_key_public_key(key); |
| 111 | 111 | pks.pkey_algo = pk->pkey_algo; |
| 112 | − if (!strcmp(pk->pkey_algo, "rsa")) | |
| 112 | + if (!strcmp(pk->pkey_algo, "rsa")) { | |
| 113 | 113 | pks.encoding = "pkcs1"; |
| 114 | − else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) | |
| 114 | + } else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) { | |
| 115 | 115 | /* edcsa-nist-p192 etc. */ |
| 116 | 116 | pks.encoding = "x962"; |
| 117 | − else if (!strcmp(pk->pkey_algo, "ecrdsa") || | |
| 118 | − !strcmp(pk->pkey_algo, "sm2")) | |
| 117 | + } else if (!strcmp(pk->pkey_algo, "ecrdsa") || | |
| 118 | + !strcmp(pk->pkey_algo, "sm2")) { | |
| 119 | 119 | pks.encoding = "raw"; |
| 120 | − else | |
| 121 | − return -ENOPKG; | |
| 120 | + } else { | |
| 121 | + ret = -ENOPKG; | |
| 122 | + goto out; | |
| 123 | + } | |
| 122 | 124 | |
| 123 | 125 | pks.digest = (u8 *)data; |
| 124 | 126 | pks.digest_size = datalen; |
| 125 | 127 | pks.s = hdr->sig; |
| 126 | 128 | pks.s_size = siglen; |
| 127 | 129 | ret = verify_signature(key, &pks); |
| 130 | +out: | |
| 128 | 131 | key_put(key); |
| 129 | 132 | pr_debug("%s() = %d\n", __func__, ret); |
| 130 | 133 | return ret; |
| @@ -496,12 +496,12 @@ int __init ima_fs_init(void) · 495 unmodified lines | ||
| 496 | 496 | |
| 497 | 497 | return 0; |
| 498 | 498 | out: |
| 499 | + securityfs_remove(ima_policy); | |
| 499 | 500 | securityfs_remove(violations); |
| 500 | 501 | securityfs_remove(runtime_measurements_count); |
| 501 | 502 | securityfs_remove(ascii_runtime_measurements); |
| 502 | 503 | securityfs_remove(binary_runtime_measurements); |
| 503 | 504 | securityfs_remove(ima_symlink); |
| 504 | 505 | securityfs_remove(ima_dir); |
| 505 | − securityfs_remove(ima_policy); | |
| 506 | 506 | return -1; |
| 507 | 507 | } |
| @@ -1967,6 +1967,14 @@ int ima_policy_show(struct seq_file *m, void *v) · 1966 unmodified lines | ||
| 1967 | 1967 | |
| 1968 | 1968 | rcu_read_lock(); |
| 1969 | 1969 | |
| 1970 | + /* Do not print rules with inactive LSM labels */ | |
| 1971 | + for (i = 0; i < MAX_LSM_RULES; i++) { | |
| 1972 | + if (entry->lsm[i].args_p && !entry->lsm[i].rule) { | |
| 1973 | + rcu_read_unlock(); | |
| 1974 | + return 0; | |
| 1975 | + } | |
| 1976 | + } | |
| 1977 | + | |
| 1970 | 1978 | if (entry->action & MEASURE) |
| 1971 | 1979 | seq_puts(m, pt(Opt_measure)); |
| 1972 | 1980 | if (entry->action & DONT_MEASURE) |
| @@ -29,6 +29,7 @@ static struct ima_template_desc builtin_templates[] = { · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | static LIST_HEAD(defined_templates); |
| 31 | 31 | static DEFINE_SPINLOCK(template_list); |
| 32 | +static int template_setup_done; | |
| 32 | 33 | |
| 33 | 34 | static const struct ima_template_field supported_fields[] = { |
| 34 | 35 | {.field_id = "d", .field_init = ima_eventdigest_init, |
| @@ -101,10 +102,11 @@ static int __init ima_template_setup(char *str) · 66 unmodified lines | ||
| 101 | 102 | struct ima_template_desc *template_desc; |
| 102 | 103 | int template_len = strlen(str); |
| 103 | 104 | |
| 104 | − if (ima_template) | |
| 105 | + if (template_setup_done) | |
| 105 | 106 | return 1; |
| 106 | 107 | |
| 107 | − ima_init_template_list(); | |
| 108 | + if (!ima_template) | |
| 109 | + ima_init_template_list(); | |
| 108 | 110 | |
| 109 | 111 | /* |
| 110 | 112 | * Verify that a template with the supplied name exists. |
| @@ -128,6 +130,7 @@ static int __init ima_template_setup(char *str) · 17 unmodified lines | ||
| 128 | 130 | } |
| 129 | 131 | |
| 130 | 132 | ima_template = template_desc; |
| 133 | + template_setup_done = 1; | |
| 131 | 134 | return 1; |
| 132 | 135 | } |
| 133 | 136 | __setup("ima_template=", ima_template_setup); |
| @@ -136,7 +139,7 @@ static int __init ima_template_fmt_setup(char *str) · 2 unmodified lines | ||
| 136 | 139 | { |
| 137 | 140 | int num_templates = ARRAY_SIZE(builtin_templates); |
| 138 | 141 | |
| 139 | − if (ima_template) | |
| 142 | + if (template_setup_done) | |
| 140 | 143 | return 1; |
| 141 | 144 | |
| 142 | 145 | if (template_desc_init_fields(str, NULL, NULL) < 0) { |
| @@ -147,6 +150,7 @@ static int __init ima_template_fmt_setup(char *str) · 4 unmodified lines | ||
| 147 | 150 | |
| 148 | 151 | builtin_templates[num_templates - 1].fmt = str; |
| 149 | 152 | ima_template = builtin_templates + num_templates - 1; |
| 153 | + template_setup_done = 1; | |
| 150 | 154 | |
| 151 | 155 | return 1; |
| 152 | 156 | } |
| @@ -45,6 +45,8 @@ void integrity_audit_message(int audit_msgno, struct inode *inode, · 44 unmodified lines | ||
| 45 | 45 | return; |
| 46 | 46 | |
| 47 | 47 | ab = audit_log_start(audit_context(), GFP_KERNEL, audit_msgno); |
| 48 | + if (!ab) | |
| 49 | + return; | |
| 48 | 50 | audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", |
| 49 | 51 | task_pid_nr(current), |
| 50 | 52 | from_kuid(&init_user_ns, current_uid()), |
| @@ -172,6 +172,19 @@ unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream) · 171 unmodified lines | ||
| 172 | 172 | } |
| 173 | 173 | EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); |
| 174 | 174 | |
| 175 | +unsigned long _snd_pcm_stream_lock_irqsave_nested(struct snd_pcm_substream *substream) | |
| 176 | +{ | |
| 177 | + unsigned long flags = 0; | |
| 178 | + if (substream->pcm->nonatomic) | |
| 179 | + mutex_lock_nested(&substream->self_group.mutex, | |
| 180 | + SINGLE_DEPTH_NESTING); | |
| 181 | + else | |
| 182 | + spin_lock_irqsave_nested(&substream->self_group.lock, flags, | |
| 183 | + SINGLE_DEPTH_NESTING); | |
| 184 | + return flags; | |
| 185 | +} | |
| 186 | +EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave_nested); | |
| 187 | + | |
| 175 | 188 | /** |
| 176 | 189 | * snd_pcm_stream_unlock_irqrestore - Unlock the PCM stream |
| 177 | 190 | * @substream: PCM substream |
| @@ -50,11 +50,11 @@ static bool is_link_enabled(struct fwnode_handle *fw_node, int i) · 49 unmodified lines | ||
| 50 | 50 | static int |
| 51 | 51 | sdw_intel_scan_controller(struct sdw_intel_acpi_info *info) |
| 52 | 52 | { |
| 53 | − struct acpi_device *adev; | |
| 53 | + struct acpi_device *adev = acpi_fetch_acpi_dev(info->handle); | |
| 54 | 54 | int ret, i; |
| 55 | 55 | u8 count; |
| 56 | 56 | |
| 57 | − if (acpi_bus_get_device(info->handle, &adev)) | |
| 57 | + if (!adev) | |
| 58 | 58 | return -EINVAL; |
| 59 | 59 | |
| 60 | 60 | /* Found controller, find links supported */ |
| @@ -119,7 +119,6 @@ static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level, · 58 unmodified lines | ||
| 119 | 119 | void *cdata, void **return_value) |
| 120 | 120 | { |
| 121 | 121 | struct sdw_intel_acpi_info *info = cdata; |
| 122 | − struct acpi_device *adev; | |
| 123 | 122 | acpi_status status; |
| 124 | 123 | u64 adr; |
| 125 | 124 | |
| @@ -127,7 +126,7 @@ static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level, · 1 unmodified line | ||
| 127 | 126 | if (ACPI_FAILURE(status)) |
| 128 | 127 | return AE_OK; /* keep going */ |
| 129 | 128 | |
| 130 | − if (acpi_bus_get_device(handle, &adev)) { | |
| 129 | + if (!acpi_fetch_acpi_dev(handle)) { | |
| 131 | 130 | pr_err("%s: Couldn't find ACPI handle\n", __func__); |
| 132 | 131 | return AE_NOT_FOUND; |
| 133 | 132 | } |
| @@ -981,7 +981,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec, · 980 unmodified lines | ||
| 981 | 981 | int id = HDA_FIXUP_ID_NOT_SET; |
| 982 | 982 | const char *name = NULL; |
| 983 | 983 | const char *type = NULL; |
| 984 | − int vendor, device; | |
| 984 | + unsigned int vendor, device; | |
| 985 | 985 | |
| 986 | 986 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) |
| 987 | 987 | return; |
| @@ -3000,6 +3000,10 @@ void snd_hda_codec_shutdown(struct hda_codec *codec) · 2999 unmodified lines | ||
| 3000 | 3000 | { |
| 3001 | 3001 | struct hda_pcm *cpcm; |
| 3002 | 3002 | |
| 3003 | + /* Skip the shutdown if codec is not registered */ | |
| 3004 | + if (!codec->registered) | |
| 3005 | + return; | |
| 3006 | + | |
| 3003 | 3007 | list_for_each_entry(cpcm, &codec->pcm_list_head, list) |
| 3004 | 3008 | snd_pcm_suspend_all(cpcm->pcm); |
| 3005 | 3009 | |
| @@ -91,6 +91,12 @@ static void snd_hda_gen_spec_free(struct hda_gen_spec *spec) · 90 unmodified lines | ||
| 91 | 91 | free_kctls(spec); |
| 92 | 92 | snd_array_free(&spec->paths); |
| 93 | 93 | snd_array_free(&spec->loopback_list); |
| 94 | +#ifdef CONFIG_SND_HDA_GENERIC_LEDS | |
| 95 | + if (spec->led_cdevs[LED_AUDIO_MUTE]) | |
| 96 | + led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MUTE]); | |
| 97 | + if (spec->led_cdevs[LED_AUDIO_MICMUTE]) | |
| 98 | + led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MICMUTE]); | |
| 99 | +#endif | |
| 94 | 100 | } |
| 95 | 101 | |
| 96 | 102 | /* |
| @@ -3922,7 +3928,10 @@ static int create_mute_led_cdev(struct hda_codec *codec, · 3825 unmodified lines | ||
| 3922 | 3928 | enum led_brightness), |
| 3923 | 3929 | bool micmute) |
| 3924 | 3930 | { |
| 3931 | + struct hda_gen_spec *spec = codec->spec; | |
| 3925 | 3932 | struct led_classdev *cdev; |
| 3933 | + int idx = micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE; | |
| 3934 | + int err; | |
| 3926 | 3935 | |
| 3927 | 3936 | cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL); |
| 3928 | 3937 | if (!cdev) |
| @@ -3932,10 +3941,14 @@ static int create_mute_led_cdev(struct hda_codec *codec, · 3 unmodified lines | ||
| 3932 | 3941 | cdev->max_brightness = 1; |
| 3933 | 3942 | cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute"; |
| 3934 | 3943 | cdev->brightness_set_blocking = callback; |
| 3935 | − cdev->brightness = ledtrig_audio_get(micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE); | |
| 3944 | + cdev->brightness = ledtrig_audio_get(idx); | |
| 3936 | 3945 | cdev->flags = LED_CORE_SUSPENDRESUME; |
| 3937 | 3946 | |
| 3938 | − return devm_led_classdev_register(&codec->core.dev, cdev); | |
| 3947 | + err = led_classdev_register(&codec->core.dev, cdev); | |
| 3948 | + if (err < 0) | |
| 3949 | + return err; | |
| 3950 | + spec->led_cdevs[idx] = cdev; | |
| 3951 | + return 0; | |
| 3939 | 3952 | } |
| 3940 | 3953 | |
| 3941 | 3954 | /** |
| @@ -294,6 +294,9 @@ struct hda_gen_spec { · 293 unmodified lines | ||
| 294 | 294 | struct hda_jack_callback *cb); |
| 295 | 295 | void (*mic_autoswitch_hook)(struct hda_codec *codec, |
| 296 | 296 | struct hda_jack_callback *cb); |
| 297 | + | |
| 298 | + /* leds */ | |
| 299 | + struct led_classdev *led_cdevs[NUM_AUDIO_LEDS]; | |
| 297 | 300 | }; |
| 298 | 301 | |
| 299 | 302 | /* values for add_stereo_mix_input flag */ |
| @@ -98,6 +98,7 @@ struct alc_spec { · 97 unmodified lines | ||
| 98 | 98 | unsigned int gpio_mic_led_mask; |
| 99 | 99 | struct alc_coef_led mute_led_coef; |
| 100 | 100 | struct alc_coef_led mic_led_coef; |
| 101 | + struct mutex coef_mutex; | |
| 101 | 102 | |
| 102 | 103 | hda_nid_t headset_mic_pin; |
| 103 | 104 | hda_nid_t headphone_mic_pin; |
| @@ -137,8 +138,8 @@ struct alc_spec { · 33 unmodified lines | ||
| 137 | 138 | * COEF access helper functions |
| 138 | 139 | */ |
| 139 | 140 | |
| 140 | −static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | |
| 141 | − unsigned int coef_idx) | |
| 141 | +static int __alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | |
| 142 | + unsigned int coef_idx) | |
| 142 | 143 | { |
| 143 | 144 | unsigned int val; |
| 144 | 145 | |
| @@ -147,28 +148,61 @@ static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, · 2 unmodified lines | ||
| 147 | 148 | return val; |
| 148 | 149 | } |
| 149 | 150 | |
| 151 | +static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | |
| 152 | + unsigned int coef_idx) | |
| 153 | +{ | |
| 154 | + struct alc_spec *spec = codec->spec; | |
| 155 | + unsigned int val; | |
| 156 | + | |
| 157 | + mutex_lock(&spec->coef_mutex); | |
| 158 | + val = __alc_read_coefex_idx(codec, nid, coef_idx); | |
| 159 | + mutex_unlock(&spec->coef_mutex); | |
| 160 | + return val; | |
| 161 | +} | |
| 162 | + | |
| 150 | 163 | #define alc_read_coef_idx(codec, coef_idx) \ |
| 151 | 164 | alc_read_coefex_idx(codec, 0x20, coef_idx) |
| 152 | 165 | |
| 153 | −static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | |
| 154 | − unsigned int coef_idx, unsigned int coef_val) | |
| 166 | +static void __alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | |
| 167 | + unsigned int coef_idx, unsigned int coef_val) | |
| 155 | 168 | { |
| 156 | 169 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx); |
| 157 | 170 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, coef_val); |
| 158 | 171 | } |
| 159 | 172 | |
| 173 | +static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | |
| 174 | + unsigned int coef_idx, unsigned int coef_val) | |
| 175 | +{ | |
| 176 | + struct alc_spec *spec = codec->spec; | |
| 177 | + | |
| 178 | + mutex_lock(&spec->coef_mutex); | |
| 179 | + __alc_write_coefex_idx(codec, nid, coef_idx, coef_val); | |
| 180 | + mutex_unlock(&spec->coef_mutex); | |
| 181 | +} | |
| 182 | + | |
| 160 | 183 | #define alc_write_coef_idx(codec, coef_idx, coef_val) \ |
| 161 | 184 | alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val) |
| 162 | 185 | |
| 186 | +static void __alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, | |
| 187 | + unsigned int coef_idx, unsigned int mask, | |
| 188 | + unsigned int bits_set) | |
| 189 | +{ | |
| 190 | + unsigned int val = __alc_read_coefex_idx(codec, nid, coef_idx); | |
| 191 | + | |
| 192 | + if (val != -1) | |
| 193 | + __alc_write_coefex_idx(codec, nid, coef_idx, | |
| 194 | + (val & ~mask) | bits_set); | |
| 195 | +} | |
| 196 | + | |
| 163 | 197 | static void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, |
| 164 | 198 | unsigned int coef_idx, unsigned int mask, |
| 165 | 199 | unsigned int bits_set) |
| 166 | 200 | { |
| 167 | − unsigned int val = alc_read_coefex_idx(codec, nid, coef_idx); | |
| 201 | + struct alc_spec *spec = codec->spec; | |
| 168 | 202 | |
| 169 | − if (val != -1) | |
| 170 | − alc_write_coefex_idx(codec, nid, coef_idx, | |
| 171 | − (val & ~mask) | bits_set); | |
| 203 | + mutex_lock(&spec->coef_mutex); | |
| 204 | + __alc_update_coefex_idx(codec, nid, coef_idx, mask, bits_set); | |
| 205 | + mutex_unlock(&spec->coef_mutex); | |
| 172 | 206 | } |
| 173 | 207 | |
| 174 | 208 | #define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \ |
| @@ -201,13 +235,17 @@ struct coef_fw { · 26 unmodified lines | ||
| 201 | 235 | static void alc_process_coef_fw(struct hda_codec *codec, |
| 202 | 236 | const struct coef_fw *fw) |
| 203 | 237 | { |
| 238 | + struct alc_spec *spec = codec->spec; | |
| 239 | + | |
| 240 | + mutex_lock(&spec->coef_mutex); | |
| 204 | 241 | for (; fw->nid; fw++) { |
| 205 | 242 | if (fw->mask == (unsigned short)-1) |
| 206 | − alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val); | |
| 243 | + __alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val); | |
| 207 | 244 | else |
| 208 | − alc_update_coefex_idx(codec, fw->nid, fw->idx, | |
| 209 | − fw->mask, fw->val); | |
| 245 | + __alc_update_coefex_idx(codec, fw->nid, fw->idx, | |
| 246 | + fw->mask, fw->val); | |
| 210 | 247 | } |
| 248 | + mutex_unlock(&spec->coef_mutex); | |
| 211 | 249 | } |
| 212 | 250 | |
| 213 | 251 | /* |
| @@ -1153,6 +1191,7 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid) · 939 unmodified lines | ||
| 1153 | 1191 | codec->spdif_status_reset = 1; |
| 1154 | 1192 | codec->forced_resume = 1; |
| 1155 | 1193 | codec->patch_ops = alc_patch_ops; |
| 1194 | + mutex_init(&spec->coef_mutex); | |
| 1156 | 1195 | |
| 1157 | 1196 | err = alc_codec_rename_from_preset(codec); |
| 1158 | 1197 | if (err < 0) { |
| @@ -2125,6 +2164,7 @@ static void alc1220_fixup_gb_x570(struct hda_codec *codec, · 966 unmodified lines | ||
| 2125 | 2164 | { |
| 2126 | 2165 | static const hda_nid_t conn1[] = { 0x0c }; |
| 2127 | 2166 | static const struct coef_fw gb_x570_coefs[] = { |
| 2167 | + WRITE_COEF(0x07, 0x03c0), | |
| 2128 | 2168 | WRITE_COEF(0x1a, 0x01c1), |
| 2129 | 2169 | WRITE_COEF(0x1b, 0x0202), |
| 2130 | 2170 | WRITE_COEF(0x43, 0x3005), |
| @@ -2551,7 +2591,8 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { · 420 unmodified lines | ||
| 2551 | 2591 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), |
| 2552 | 2592 | SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), |
| 2553 | 2593 | SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_GB_X570), |
| 2554 | − SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_CLEVO_P950), | |
| 2594 | + SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_GB_X570), | |
| 2595 | + SND_PCI_QUIRK(0x1458, 0xa0d5, "Gigabyte X570S Aorus Master", ALC1220_FIXUP_GB_X570), | |
| 2555 | 2596 | SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950), |
| 2556 | 2597 | SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), |
| 2557 | 2598 | SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950), |
| @@ -2626,6 +2667,7 @@ static const struct hda_model_fixup alc882_fixup_models[] = { · 68 unmodified lines | ||
| 2626 | 2667 | {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"}, |
| 2627 | 2668 | {.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"}, |
| 2628 | 2669 | {.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"}, |
| 2670 | + {.id = ALC1220_FIXUP_GB_X570, .name = "gb-x570"}, | |
| 2629 | 2671 | {.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"}, |
| 2630 | 2672 | {} |
| 2631 | 2673 | }; |
| @@ -8969,6 +9011,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 6337 unmodified lines | ||
| 8969 | 9011 | SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), |
| 8970 | 9012 | SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), |
| 8971 | 9013 | SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), |
| 9014 | + SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), | |
| 8972 | 9015 | SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), |
| 8973 | 9016 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
| 8974 | 9017 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), |
| @@ -303,11 +303,11 @@ static const struct snd_soc_dapm_route rt1019_map_lr[] = { · 302 unmodified lines | ||
| 303 | 303 | |
| 304 | 304 | static struct snd_soc_codec_conf rt1019_conf[] = { |
| 305 | 305 | { |
| 306 | − .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"), | |
| 306 | + .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"), | |
| 307 | 307 | .name_prefix = "Left", |
| 308 | 308 | }, |
| 309 | 309 | { |
| 310 | − .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"), | |
| 310 | + .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"), | |
| 311 | 311 | .name_prefix = "Right", |
| 312 | 312 | }, |
| 313 | 313 | }; |
| @@ -1667,6 +1667,8 @@ static int cpcap_codec_probe(struct platform_device *pdev) · 1666 unmodified lines | ||
| 1667 | 1667 | { |
| 1668 | 1668 | struct device_node *codec_node = |
| 1669 | 1669 | of_get_child_by_name(pdev->dev.parent->of_node, "audio-codec"); |
| 1670 | + if (!codec_node) | |
| 1671 | + return -ENODEV; | |
| 1670 | 1672 | |
| 1671 | 1673 | pdev->dev.of_node = codec_node; |
| 1672 | 1674 | |
| @@ -277,7 +277,7 @@ struct hdmi_codec_priv { · 276 unmodified lines | ||
| 277 | 277 | bool busy; |
| 278 | 278 | struct snd_soc_jack *jack; |
| 279 | 279 | unsigned int jack_status; |
| 280 | − u8 iec_status[5]; | |
| 280 | + u8 iec_status[AES_IEC958_STATUS_SIZE]; | |
| 281 | 281 | }; |
| 282 | 282 | |
| 283 | 283 | static const struct snd_soc_dapm_widget hdmi_widgets[] = { |
| @@ -2688,8 +2688,8 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, · 2687 unmodified lines | ||
| 2688 | 2688 | int reg, b2_reg; |
| 2689 | 2689 | |
| 2690 | 2690 | /* Address does not automatically update if reading */ |
| 2691 | − reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx; | |
| 2692 | − b2_reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx; | |
| 2691 | + reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx; | |
| 2692 | + b2_reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx; | |
| 2693 | 2693 | |
| 2694 | 2694 | snd_soc_component_write(component, reg, |
| 2695 | 2695 | ((band_idx * BAND_MAX + coeff_idx) * |
| @@ -2718,7 +2718,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, · 22 unmodified lines | ||
| 2718 | 2718 | static void set_iir_band_coeff(struct snd_soc_component *component, |
| 2719 | 2719 | int iir_idx, int band_idx, uint32_t value) |
| 2720 | 2720 | { |
| 2721 | − int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx; | |
| 2721 | + int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx; | |
| 2722 | 2722 | |
| 2723 | 2723 | snd_soc_component_write(component, reg, (value & 0xFF)); |
| 2724 | 2724 | snd_soc_component_write(component, reg, (value >> 8) & 0xFF); |
| @@ -2739,7 +2739,7 @@ static int rx_macro_put_iir_band_audio_mixer( · 14 unmodified lines | ||
| 2739 | 2739 | int iir_idx = ctl->iir_idx; |
| 2740 | 2740 | int band_idx = ctl->band_idx; |
| 2741 | 2741 | u32 coeff[BAND_MAX]; |
| 2742 | − int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx; | |
| 2742 | + int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx; | |
| 2743 | 2743 | |
| 2744 | 2744 | memcpy(&coeff[0], ucontrol->value.bytes.data, params->max); |
| 2745 | 2745 | |
| @@ -64,7 +64,8 @@ static int speaker_gain_control_put(struct snd_kcontrol *kcontrol, · 63 unmodified lines | ||
| 64 | 64 | struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); |
| 65 | 65 | struct max9759 *priv = snd_soc_component_get_drvdata(c); |
| 66 | 66 | |
| 67 | − if (ucontrol->value.integer.value[0] > 3) | |
| 67 | + if (ucontrol->value.integer.value[0] < 0 || | |
| 68 | + ucontrol->value.integer.value[0] > 3) | |
| 68 | 69 | return -EINVAL; |
| 69 | 70 | |
| 70 | 71 | priv->gain = ucontrol->value.integer.value[0]; |
| @@ -59,18 +59,12 @@ static void rt5682_jd_check_handler(struct work_struct *work) · 58 unmodified lines | ||
| 59 | 59 | struct rt5682_priv *rt5682 = container_of(work, struct rt5682_priv, |
| 60 | 60 | jd_check_work.work); |
| 61 | 61 | |
| 62 | − if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) | |
| 63 | − & RT5682_JDH_RS_MASK) { | |
| 62 | + if (snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) & RT5682_JDH_RS_MASK) | |
| 64 | 63 | /* jack out */ |
| 65 | − rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); | |
| 66 | − | |
| 67 | − snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, | |
| 68 | − SND_JACK_HEADSET | | |
| 69 | − SND_JACK_BTN_0 | SND_JACK_BTN_1 | | |
| 70 | − SND_JACK_BTN_2 | SND_JACK_BTN_3); | |
| 71 | − } else { | |
| 64 | + mod_delayed_work(system_power_efficient_wq, | |
| 65 | + &rt5682->jack_detect_work, 0); | |
| 66 | + else | |
| 72 | 67 | schedule_delayed_work(&rt5682->jd_check_work, 500); |
| 73 | − } | |
| 74 | 68 | } |
| 75 | 69 | |
| 76 | 70 | static irqreturn_t rt5682_irq(int irq, void *data) |
| @@ -198,7 +192,6 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, · 121 unmodified lines | ||
| 198 | 192 | } |
| 199 | 193 | |
| 200 | 194 | mutex_init(&rt5682->calibrate_mutex); |
| 201 | − mutex_init(&rt5682->jdet_mutex); | |
| 202 | 195 | rt5682_calibrate(rt5682); |
| 203 | 196 | |
| 204 | 197 | rt5682_apply_patch_list(rt5682, &i2c->dev); |
| @@ -922,15 +922,13 @@ static void rt5682_enable_push_button_irq(struct snd_soc_component *component, · 921 unmodified lines | ||
| 922 | 922 | * |
| 923 | 923 | * Returns detect status. |
| 924 | 924 | */ |
| 925 | −int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) | |
| 925 | +static int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) | |
| 926 | 926 | { |
| 927 | 927 | struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); |
| 928 | 928 | struct snd_soc_dapm_context *dapm = &component->dapm; |
| 929 | 929 | unsigned int val, count; |
| 930 | 930 | |
| 931 | 931 | if (jack_insert) { |
| 932 | − snd_soc_dapm_mutex_lock(dapm); | |
| 933 | − | |
| 934 | 932 | snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, |
| 935 | 933 | RT5682_PWR_VREF2 | RT5682_PWR_MB, |
| 936 | 934 | RT5682_PWR_VREF2 | RT5682_PWR_MB); |
| @@ -981,8 +979,6 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) · 44 unmodified lines | ||
| 981 | 979 | snd_soc_component_update_bits(component, RT5682_MICBIAS_2, |
| 982 | 980 | RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, |
| 983 | 981 | RT5682_PWR_CLK25M_PU | RT5682_PWR_CLK1M_PU); |
| 984 | − | |
| 985 | − snd_soc_dapm_mutex_unlock(dapm); | |
| 986 | 982 | } else { |
| 987 | 983 | rt5682_enable_push_button_irq(component, false); |
| 988 | 984 | snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, |
| @@ -1011,7 +1007,6 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) · 22 unmodified lines | ||
| 1011 | 1007 | dev_dbg(component->dev, "jack_type = %d\n", rt5682->jack_type); |
| 1012 | 1008 | return rt5682->jack_type; |
| 1013 | 1009 | } |
| 1014 | −EXPORT_SYMBOL_GPL(rt5682_headset_detect); | |
| 1015 | 1010 | |
| 1016 | 1011 | static int rt5682_set_jack_detect(struct snd_soc_component *component, |
| 1017 | 1012 | struct snd_soc_jack *hs_jack, void *data) |
| @@ -1094,6 +1089,7 @@ void rt5682_jack_detect_handler(struct work_struct *work) · 76 unmodified lines | ||
| 1094 | 1089 | { |
| 1095 | 1090 | struct rt5682_priv *rt5682 = |
| 1096 | 1091 | container_of(work, struct rt5682_priv, jack_detect_work.work); |
| 1092 | + struct snd_soc_dapm_context *dapm; | |
| 1097 | 1093 | int val, btn_type; |
| 1098 | 1094 | |
| 1099 | 1095 | while (!rt5682->component) |
| @@ -1102,7 +1098,9 @@ void rt5682_jack_detect_handler(struct work_struct *work) · 2 unmodified lines | ||
| 1102 | 1098 | while (!rt5682->component->card->instantiated) |
| 1103 | 1099 | usleep_range(10000, 15000); |
| 1104 | 1100 | |
| 1105 | − mutex_lock(&rt5682->jdet_mutex); | |
| 1101 | + dapm = snd_soc_component_get_dapm(rt5682->component); | |
| 1102 | + | |
| 1103 | + snd_soc_dapm_mutex_lock(dapm); | |
| 1106 | 1104 | mutex_lock(&rt5682->calibrate_mutex); |
| 1107 | 1105 | |
| 1108 | 1106 | val = snd_soc_component_read(rt5682->component, RT5682_AJD1_CTRL) |
| @@ -1162,6 +1160,9 @@ void rt5682_jack_detect_handler(struct work_struct *work) · 53 unmodified lines | ||
| 1162 | 1160 | rt5682->irq_work_delay_time = 50; |
| 1163 | 1161 | } |
| 1164 | 1162 | |
| 1163 | + mutex_unlock(&rt5682->calibrate_mutex); | |
| 1164 | + snd_soc_dapm_mutex_unlock(dapm); | |
| 1165 | + | |
| 1165 | 1166 | snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, |
| 1166 | 1167 | SND_JACK_HEADSET | |
| 1167 | 1168 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
| @@ -1174,9 +1175,6 @@ void rt5682_jack_detect_handler(struct work_struct *work) · 6 unmodified lines | ||
| 1174 | 1175 | else |
| 1175 | 1176 | cancel_delayed_work_sync(&rt5682->jd_check_work); |
| 1176 | 1177 | } |
| 1177 | − | |
| 1178 | − mutex_unlock(&rt5682->calibrate_mutex); | |
| 1179 | − mutex_unlock(&rt5682->jdet_mutex); | |
| 1180 | 1178 | } |
| 1181 | 1179 | EXPORT_SYMBOL_GPL(rt5682_jack_detect_handler); |
| 1182 | 1180 | |
| @@ -1526,7 +1524,6 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w, · 343 unmodified lines | ||
| 1526 | 1524 | { |
| 1527 | 1525 | struct snd_soc_component *component = |
| 1528 | 1526 | snd_soc_dapm_to_component(w->dapm); |
| 1529 | − struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); | |
| 1530 | 1527 | |
| 1531 | 1528 | switch (event) { |
| 1532 | 1529 | case SND_SOC_DAPM_PRE_PMU: |
| @@ -1538,17 +1535,12 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w, · 5 unmodified lines | ||
| 1538 | 1535 | RT5682_DEPOP_1, 0x60, 0x60); |
| 1539 | 1536 | snd_soc_component_update_bits(component, |
| 1540 | 1537 | RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0080); |
| 1541 | − | |
| 1542 | − mutex_lock(&rt5682->jdet_mutex); | |
| 1543 | − | |
| 1544 | 1538 | snd_soc_component_update_bits(component, RT5682_HP_CTRL_2, |
| 1545 | 1539 | RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN, |
| 1546 | 1540 | RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN); |
| 1547 | 1541 | usleep_range(5000, 10000); |
| 1548 | 1542 | snd_soc_component_update_bits(component, RT5682_CHARGE_PUMP_1, |
| 1549 | 1543 | RT5682_CP_SW_SIZE_MASK, RT5682_CP_SW_SIZE_L); |
| 1550 | − | |
| 1551 | − mutex_unlock(&rt5682->jdet_mutex); | |
| 1552 | 1544 | break; |
| 1553 | 1545 | |
| 1554 | 1546 | case SND_SOC_DAPM_POST_PMD: |
| @@ -1463,7 +1463,6 @@ struct rt5682_priv { · 1462 unmodified lines | ||
| 1463 | 1463 | |
| 1464 | 1464 | int jack_type; |
| 1465 | 1465 | int irq_work_delay_time; |
| 1466 | − struct mutex jdet_mutex; | |
| 1467 | 1466 | }; |
| 1468 | 1467 | |
| 1469 | 1468 | extern const char *rt5682_supply_names[RT5682_NUM_SUPPLIES]; |
| @@ -1473,7 +1472,6 @@ int rt5682_sel_asrc_clk_src(struct snd_soc_component *component, · 3 unmodified lines | ||
| 1473 | 1472 | |
| 1474 | 1473 | void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev); |
| 1475 | 1474 | |
| 1476 | −int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert); | |
| 1477 | 1475 | void rt5682_jack_detect_handler(struct work_struct *work); |
| 1478 | 1476 | |
| 1479 | 1477 | bool rt5682_volatile_register(struct device *dev, unsigned int reg); |
| @@ -1432,14 +1432,10 @@ static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info, · 1431 unmodified lines | ||
| 1432 | 1432 | return 0; |
| 1433 | 1433 | } |
| 1434 | 1434 | |
| 1435 | −static int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 ch_id, u8 enable) | |
| 1435 | +static int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 port_num, u8 ch_id, u8 enable) | |
| 1436 | 1436 | { |
| 1437 | − u8 port_num; | |
| 1438 | − | |
| 1439 | − port_num = wcd->ch_info[ch_id].port_num; | |
| 1440 | − | |
| 1441 | 1437 | return wcd938x_sdw_connect_port(&wcd->ch_info[ch_id], |
| 1442 | − &wcd->port_config[port_num], | |
| 1438 | + &wcd->port_config[port_num - 1], | |
| 1443 | 1439 | enable); |
| 1444 | 1440 | } |
| 1445 | 1441 | |
| @@ -2563,7 +2559,7 @@ static int wcd938x_ear_pa_put_gain(struct snd_kcontrol *kcontrol, · 1117 unmodified lines | ||
| 2563 | 2559 | WCD938X_EAR_GAIN_MASK, |
| 2564 | 2560 | ucontrol->value.integer.value[0]); |
| 2565 | 2561 | |
| 2566 | − return 0; | |
| 2562 | + return 1; | |
| 2567 | 2563 | } |
| 2568 | 2564 | |
| 2569 | 2565 | static int wcd938x_get_compander(struct snd_kcontrol *kcontrol, |
| @@ -2593,6 +2589,7 @@ static int wcd938x_set_compander(struct snd_kcontrol *kcontrol, · 23 unmodified lines | ||
| 2593 | 2589 | struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); |
| 2594 | 2590 | struct wcd938x_sdw_priv *wcd; |
| 2595 | 2591 | int value = ucontrol->value.integer.value[0]; |
| 2592 | + int portidx; | |
| 2596 | 2593 | struct soc_mixer_control *mc; |
| 2597 | 2594 | bool hphr; |
| 2598 | 2595 | |
| @@ -2606,12 +2603,14 @@ static int wcd938x_set_compander(struct snd_kcontrol *kcontrol, · 7 unmodified lines | ||
| 2606 | 2603 | else |
| 2607 | 2604 | wcd938x->comp1_enable = value; |
| 2608 | 2605 | |
| 2606 | + portidx = wcd->ch_info[mc->reg].port_num; | |
| 2607 | + | |
| 2609 | 2608 | if (value) |
| 2610 | − wcd938x_connect_port(wcd, mc->reg, true); | |
| 2609 | + wcd938x_connect_port(wcd, portidx, mc->reg, true); | |
| 2611 | 2610 | else |
| 2612 | − wcd938x_connect_port(wcd, mc->reg, false); | |
| 2611 | + wcd938x_connect_port(wcd, portidx, mc->reg, false); | |
| 2613 | 2612 | |
| 2614 | − return 0; | |
| 2613 | + return 1; | |
| 2615 | 2614 | } |
| 2616 | 2615 | |
| 2617 | 2616 | static int wcd938x_ldoh_get(struct snd_kcontrol *kcontrol, |
| @@ -2882,9 +2881,11 @@ static int wcd938x_get_swr_port(struct snd_kcontrol *kcontrol, · 264 unmodified lines | ||
| 2882 | 2881 | struct wcd938x_sdw_priv *wcd; |
| 2883 | 2882 | struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; |
| 2884 | 2883 | int dai_id = mixer->shift; |
| 2885 | − int portidx = mixer->reg; | |
| 2884 | + int portidx, ch_idx = mixer->reg; | |
| 2885 | + | |
| 2886 | 2886 | |
| 2887 | 2887 | wcd = wcd938x->sdw_priv[dai_id]; |
| 2888 | + portidx = wcd->ch_info[ch_idx].port_num; | |
| 2888 | 2889 | |
| 2889 | 2890 | ucontrol->value.integer.value[0] = wcd->port_enable[portidx]; |
| 2890 | 2891 | |
| @@ -2899,12 +2900,14 @@ static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol, · 8 unmodified lines | ||
| 2899 | 2900 | struct wcd938x_sdw_priv *wcd; |
| 2900 | 2901 | struct soc_mixer_control *mixer = |
| 2901 | 2902 | (struct soc_mixer_control *)kcontrol->private_value; |
| 2902 | − int portidx = mixer->reg; | |
| 2903 | + int ch_idx = mixer->reg; | |
| 2904 | + int portidx; | |
| 2903 | 2905 | int dai_id = mixer->shift; |
| 2904 | 2906 | bool enable; |
| 2905 | 2907 | |
| 2906 | 2908 | wcd = wcd938x->sdw_priv[dai_id]; |
| 2907 | 2909 | |
| 2910 | + portidx = wcd->ch_info[ch_idx].port_num; | |
| 2908 | 2911 | if (ucontrol->value.integer.value[0]) |
| 2909 | 2912 | enable = true; |
| 2910 | 2913 | else |
| @@ -2912,9 +2915,9 @@ static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol, · 1 unmodified line | ||
| 2912 | 2915 | |
| 2913 | 2916 | wcd->port_enable[portidx] = enable; |
| 2914 | 2917 | |
| 2915 | − wcd938x_connect_port(wcd, portidx, enable); | |
| 2918 | + wcd938x_connect_port(wcd, portidx, ch_idx, enable); | |
| 2916 | 2919 | |
| 2917 | − return 0; | |
| 2920 | + return 1; | |
| 2918 | 2921 | |
| 2919 | 2922 | } |
| 2920 | 2923 | |
| @@ -93,16 +93,21 @@ static int pcm030_fabric_probe(struct platform_device *op) · 92 unmodified lines | ||
| 93 | 93 | dev_err(&op->dev, "platform_device_alloc() failed\n"); |
| 94 | 94 | |
| 95 | 95 | ret = platform_device_add(pdata->codec_device); |
| 96 | − if (ret) | |
| 96 | + if (ret) { | |
| 97 | 97 | dev_err(&op->dev, "platform_device_add() failed: %d\n", ret); |
| 98 | + platform_device_put(pdata->codec_device); | |
| 99 | + } | |
| 98 | 100 | |
| 99 | 101 | ret = snd_soc_register_card(card); |
| 100 | − if (ret) | |
| 102 | + if (ret) { | |
| 101 | 103 | dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); |
| 104 | + platform_device_del(pdata->codec_device); | |
| 105 | + platform_device_put(pdata->codec_device); | |
| 106 | + } | |
| 102 | 107 | |
| 103 | 108 | platform_set_drvdata(op, pdata); |
| 104 | − | |
| 105 | 109 | return ret; |
| 110 | + | |
| 106 | 111 | } |
| 107 | 112 | |
| 108 | 113 | static int pcm030_fabric_remove(struct platform_device *op) |
| @@ -28,6 +28,30 @@ static const struct snd_soc_ops simple_ops = { · 27 unmodified lines | ||
| 28 | 28 | .hw_params = asoc_simple_hw_params, |
| 29 | 29 | }; |
| 30 | 30 | |
| 31 | +static int asoc_simple_parse_platform(struct device_node *node, | |
| 32 | + struct snd_soc_dai_link_component *dlc) | |
| 33 | +{ | |
| 34 | + struct of_phandle_args args; | |
| 35 | + int ret; | |
| 36 | + | |
| 37 | + if (!node) | |
| 38 | + return 0; | |
| 39 | + | |
| 40 | + /* | |
| 41 | + * Get node via "sound-dai = <&phandle port>" | |
| 42 | + * it will be used as xxx_of_node on soc_bind_dai_link() | |
| 43 | + */ | |
| 44 | + ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args); | |
| 45 | + if (ret) | |
| 46 | + return ret; | |
| 47 | + | |
| 48 | + /* dai_name is not required and may not exist for plat component */ | |
| 49 | + | |
| 50 | + dlc->of_node = args.np; | |
| 51 | + | |
| 52 | + return 0; | |
| 53 | +} | |
| 54 | + | |
| 31 | 55 | static int asoc_simple_parse_dai(struct device_node *node, |
| 32 | 56 | struct snd_soc_dai_link_component *dlc, |
| 33 | 57 | int *is_single_link) |
| @@ -289,7 +313,7 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, · 255 unmodified lines | ||
| 289 | 313 | if (ret < 0) |
| 290 | 314 | goto dai_link_of_err; |
| 291 | 315 | |
| 292 | − ret = asoc_simple_parse_dai(plat, platforms, NULL); | |
| 316 | + ret = asoc_simple_parse_platform(plat, platforms); | |
| 293 | 317 | if (ret < 0) |
| 294 | 318 | goto dai_link_of_err; |
| 295 | 319 | |
| @@ -216,7 +216,7 @@ config SND_SOC_MT8195_MT6359_RT1019_RT5682 · 215 unmodified lines | ||
| 216 | 216 | |
| 217 | 217 | config SND_SOC_MT8195_MT6359_RT1011_RT5682 |
| 218 | 218 | tristate "ASoC Audio driver for MT8195 with MT6359 RT1011 RT5682 codec" |
| 219 | − depends on I2C | |
| 219 | + depends on I2C && GPIOLIB | |
| 220 | 220 | depends on SND_SOC_MT8195 && MTK_PMIC_WRAP |
| 221 | 221 | select SND_SOC_MT6359 |
| 222 | 222 | select SND_SOC_RT1011 |
| @@ -308,8 +308,11 @@ static int q6apm_dai_close(struct snd_soc_component *component, · 307 unmodified lines | ||
| 308 | 308 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 309 | 309 | struct q6apm_dai_rtd *prtd = runtime->private_data; |
| 310 | 310 | |
| 311 | − q6apm_graph_stop(prtd->graph); | |
| 312 | − q6apm_unmap_memory_regions(prtd->graph, substream->stream); | |
| 311 | + if (prtd->state) { /* only stop graph that is started */ | |
| 312 | + q6apm_graph_stop(prtd->graph); | |
| 313 | + q6apm_unmap_memory_regions(prtd->graph, substream->stream); | |
| 314 | + } | |
| 315 | + | |
| 313 | 316 | q6apm_graph_close(prtd->graph); |
| 314 | 317 | prtd->graph = NULL; |
| 315 | 318 | kfree(prtd); |
| @@ -55,16 +55,13 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_find_machine); · 54 unmodified lines | ||
| 55 | 55 | static acpi_status snd_soc_acpi_find_package(acpi_handle handle, u32 level, |
| 56 | 56 | void *context, void **ret) |
| 57 | 57 | { |
| 58 | − struct acpi_device *adev; | |
| 58 | + struct acpi_device *adev = acpi_fetch_acpi_dev(handle); | |
| 59 | 59 | acpi_status status; |
| 60 | 60 | struct snd_soc_acpi_package_context *pkg_ctx = context; |
| 61 | 61 | |
| 62 | 62 | pkg_ctx->data_valid = false; |
| 63 | 63 | |
| 64 | − if (acpi_bus_get_device(handle, &adev)) | |
| 65 | − return AE_OK; | |
| 66 | − | |
| 67 | − if (adev->status.present && adev->status.functional) { | |
| 64 | + if (adev && adev->status.present && adev->status.functional) { | |
| 68 | 65 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
| 69 | 66 | union acpi_object *myobj = NULL; |
| 70 | 67 | |
| @@ -316,13 +316,27 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, · 315 unmodified lines | ||
| 316 | 316 | if (sign_bit) |
| 317 | 317 | mask = BIT(sign_bit + 1) - 1; |
| 318 | 318 | |
| 319 | − val = ((ucontrol->value.integer.value[0] + min) & mask); | |
| 319 | + if (ucontrol->value.integer.value[0] < 0) | |
| 320 | + return -EINVAL; | |
| 321 | + val = ucontrol->value.integer.value[0]; | |
| 322 | + if (mc->platform_max && val > mc->platform_max) | |
| 323 | + return -EINVAL; | |
| 324 | + if (val > max - min) | |
| 325 | + return -EINVAL; | |
| 326 | + val = (val + min) & mask; | |
| 320 | 327 | if (invert) |
| 321 | 328 | val = max - val; |
| 322 | 329 | val_mask = mask << shift; |
| 323 | 330 | val = val << shift; |
| 324 | 331 | if (snd_soc_volsw_is_stereo(mc)) { |
| 325 | − val2 = ((ucontrol->value.integer.value[1] + min) & mask); | |
| 332 | + if (ucontrol->value.integer.value[1] < 0) | |
| 333 | + return -EINVAL; | |
| 334 | + val2 = ucontrol->value.integer.value[1]; | |
| 335 | + if (mc->platform_max && val2 > mc->platform_max) | |
| 336 | + return -EINVAL; | |
| 337 | + if (val2 > max - min) | |
| 338 | + return -EINVAL; | |
| 339 | + val2 = (val2 + min) & mask; | |
| 326 | 340 | if (invert) |
| 327 | 341 | val2 = max - val2; |
| 328 | 342 | if (reg == reg2) { |
| @@ -409,8 +423,15 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, · 80 unmodified lines | ||
| 409 | 423 | int err = 0; |
| 410 | 424 | unsigned int val, val_mask; |
| 411 | 425 | |
| 426 | + if (ucontrol->value.integer.value[0] < 0) | |
| 427 | + return -EINVAL; | |
| 428 | + val = ucontrol->value.integer.value[0]; | |
| 429 | + if (mc->platform_max && val > mc->platform_max) | |
| 430 | + return -EINVAL; | |
| 431 | + if (val > max - min) | |
| 432 | + return -EINVAL; | |
| 412 | 433 | val_mask = mask << shift; |
| 413 | − val = (ucontrol->value.integer.value[0] + min) & mask; | |
| 434 | + val = (val + min) & mask; | |
| 414 | 435 | val = val << shift; |
| 415 | 436 | |
| 416 | 437 | err = snd_soc_component_update_bits(component, reg, val_mask, val); |
| @@ -858,6 +879,8 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, · 441 unmodified lines | ||
| 858 | 879 | long val = ucontrol->value.integer.value[0]; |
| 859 | 880 | unsigned int i; |
| 860 | 881 | |
| 882 | + if (val < mc->min || val > mc->max) | |
| 883 | + return -EINVAL; | |
| 861 | 884 | if (invert) |
| 862 | 885 | val = max - val; |
| 863 | 886 | val &= mask; |
| @@ -46,8 +46,8 @@ static inline void snd_soc_dpcm_stream_lock_irq(struct snd_soc_pcm_runtime *rtd, · 45 unmodified lines | ||
| 46 | 46 | snd_pcm_stream_lock_irq(snd_soc_dpcm_get_substream(rtd, stream)); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | −#define snd_soc_dpcm_stream_lock_irqsave(rtd, stream, flags) \ | |
| 50 | − snd_pcm_stream_lock_irqsave(snd_soc_dpcm_get_substream(rtd, stream), flags) | |
| 49 | +#define snd_soc_dpcm_stream_lock_irqsave_nested(rtd, stream, flags) \ | |
| 50 | + snd_pcm_stream_lock_irqsave_nested(snd_soc_dpcm_get_substream(rtd, stream), flags) | |
| 51 | 51 | |
| 52 | 52 | static inline void snd_soc_dpcm_stream_unlock_irq(struct snd_soc_pcm_runtime *rtd, |
| 53 | 53 | int stream) |
| @@ -1268,6 +1268,7 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe, · 1214 unmodified lines | ||
| 1268 | 1268 | void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) |
| 1269 | 1269 | { |
| 1270 | 1270 | struct snd_soc_dpcm *dpcm, *d; |
| 1271 | + LIST_HEAD(deleted_dpcms); | |
| 1271 | 1272 | |
| 1272 | 1273 | snd_soc_dpcm_mutex_assert_held(fe); |
| 1273 | 1274 | |
| @@ -1287,13 +1288,18 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) · 13 unmodified lines | ||
| 1287 | 1288 | /* BEs still alive need new FE */ |
| 1288 | 1289 | dpcm_be_reparent(fe, dpcm->be, stream); |
| 1289 | 1290 | |
| 1290 | − dpcm_remove_debugfs_state(dpcm); | |
| 1291 | − | |
| 1292 | 1291 | list_del(&dpcm->list_be); |
| 1292 | + list_move(&dpcm->list_fe, &deleted_dpcms); | |
| 1293 | + } | |
| 1294 | + snd_soc_dpcm_stream_unlock_irq(fe, stream); | |
| 1295 | + | |
| 1296 | + while (!list_empty(&deleted_dpcms)) { | |
| 1297 | + dpcm = list_first_entry(&deleted_dpcms, struct snd_soc_dpcm, | |
| 1298 | + list_fe); | |
| 1293 | 1299 | list_del(&dpcm->list_fe); |
| 1300 | + dpcm_remove_debugfs_state(dpcm); | |
| 1294 | 1301 | kfree(dpcm); |
| 1295 | 1302 | } |
| 1296 | − snd_soc_dpcm_stream_unlock_irq(fe, stream); | |
| 1297 | 1303 | } |
| 1298 | 1304 | |
| 1299 | 1305 | /* get BE for DAI widget and stream */ |
| @@ -2094,7 +2100,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, · 794 unmodified lines | ||
| 2094 | 2100 | be = dpcm->be; |
| 2095 | 2101 | be_substream = snd_soc_dpcm_get_substream(be, stream); |
| 2096 | 2102 | |
| 2097 | − snd_soc_dpcm_stream_lock_irqsave(be, stream, flags); | |
| 2103 | + snd_soc_dpcm_stream_lock_irqsave_nested(be, stream, flags); | |
| 2098 | 2104 | |
| 2099 | 2105 | /* is this op for this BE ? */ |
| 2100 | 2106 | if (!snd_soc_dpcm_be_can_update(fe, be, stream)) |
| @@ -37,6 +37,7 @@ · 36 unmodified lines | ||
| 37 | 37 | #define XLNX_AUD_XFER_COUNT 0x28 |
| 38 | 38 | #define XLNX_AUD_CH_STS_START 0x2C |
| 39 | 39 | #define XLNX_BYTES_PER_CH 0x44 |
| 40 | +#define XLNX_AUD_ALIGN_BYTES 64 | |
| 40 | 41 | |
| 41 | 42 | #define AUD_STS_IOC_IRQ_MASK BIT(31) |
| 42 | 43 | #define AUD_STS_CH_STS_MASK BIT(29) |
| @@ -368,12 +369,32 @@ static int xlnx_formatter_pcm_open(struct snd_soc_component *component, · 325 unmodified lines | ||
| 368 | 369 | snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware); |
| 369 | 370 | runtime->private_data = stream_data; |
| 370 | 371 | |
| 371 | − /* Resize the period size divisible by 64 */ | |
| 372 | + /* Resize the period bytes as divisible by 64 */ | |
| 372 | 373 | err = snd_pcm_hw_constraint_step(runtime, 0, |
| 373 | − SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64); | |
| 374 | + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | |
| 375 | + XLNX_AUD_ALIGN_BYTES); | |
| 374 | 376 | if (err) { |
| 375 | 377 | dev_err(component->dev, |
| 376 | − "unable to set constraint on period bytes\n"); | |
| 378 | + "Unable to set constraint on period bytes\n"); | |
| 379 | + return err; | |
| 380 | + } | |
| 381 | + | |
| 382 | + /* Resize the buffer bytes as divisible by 64 */ | |
| 383 | + err = snd_pcm_hw_constraint_step(runtime, 0, | |
| 384 | + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | |
| 385 | + XLNX_AUD_ALIGN_BYTES); | |
| 386 | + if (err) { | |
| 387 | + dev_err(component->dev, | |
| 388 | + "Unable to set constraint on buffer bytes\n"); | |
| 389 | + return err; | |
| 390 | + } | |
| 391 | + | |
| 392 | + /* Set periods as integer multiple */ | |
| 393 | + err = snd_pcm_hw_constraint_integer(runtime, | |
| 394 | + SNDRV_PCM_HW_PARAM_PERIODS); | |
| 395 | + if (err < 0) { | |
| 396 | + dev_err(component->dev, | |
| 397 | + "Unable to set constraint on periods to be integer\n"); | |
| 377 | 398 | return err; |
| 378 | 399 | } |
| 379 | 400 | |
| @@ -1527,6 +1527,10 @@ error: · 1526 unmodified lines | ||
| 1527 | 1527 | usb_audio_err(chip, |
| 1528 | 1528 | "cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
| 1529 | 1529 | UAC_GET_CUR, validx, idx, cval->val_type); |
| 1530 | + | |
| 1531 | + if (val) | |
| 1532 | + *val = 0; | |
| 1533 | + | |
| 1530 | 1534 | return filter_error(cval, ret); |
| 1531 | 1535 | } |
| 1532 | 1536 | |
| @@ -84,7 +84,7 @@ · 83 unmodified lines | ||
| 84 | 84 | * combination. |
| 85 | 85 | */ |
| 86 | 86 | { |
| 87 | − USB_DEVICE(0x041e, 0x4095), | |
| 87 | + USB_AUDIO_DEVICE(0x041e, 0x4095), | |
| 88 | 88 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { |
| 89 | 89 | .ifnum = QUIRK_ANY_INTERFACE, |
| 90 | 90 | .type = QUIRK_COMPOSITE, |
| @@ -299,7 +299,9 @@ · 298 unmodified lines | ||
| 299 | 299 | /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ |
| 300 | 300 | #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ |
| 301 | 301 | #define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */ |
| 302 | +#define X86_FEATURE_AMX_BF16 (18*32+22) /* AMX bf16 Support */ | |
| 302 | 303 | #define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */ |
| 304 | +#define X86_FEATURE_AMX_INT8 (18*32+25) /* AMX int8 Support */ | |
| 303 | 305 | |
| 304 | 306 | /* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */ |
| 305 | 307 | #define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */ |
| @@ -1624,9 +1624,6 @@ struct kvm_enc_region { · 1623 unmodified lines | ||
| 1624 | 1624 | #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) |
| 1625 | 1625 | #define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) |
| 1626 | 1626 | |
| 1627 | −/* Available with KVM_CAP_XSAVE2 */ | |
| 1628 | −#define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) | |
| 1629 | − | |
| 1630 | 1627 | struct kvm_s390_pv_sec_parm { |
| 1631 | 1628 | __u64 origin; |
| 1632 | 1629 | __u64 length; |
| @@ -2048,4 +2045,7 @@ struct kvm_stats_desc { · 415 unmodified lines | ||
| 2048 | 2045 | |
| 2049 | 2046 | #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) |
| 2050 | 2047 | |
| 2048 | +/* Available with KVM_CAP_XSAVE2 */ | |
| 2049 | +#define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) | |
| 2050 | + | |
| 2051 | 2051 | #endif /* __LINUX_KVM_H */ |
| @@ -1332,9 +1332,9 @@ union perf_mem_data_src { · 1331 unmodified lines | ||
| 1332 | 1332 | |
| 1333 | 1333 | /* hop level */ |
| 1334 | 1334 | #define PERF_MEM_HOPS_0 0x01 /* remote core, same node */ |
| 1335 | −#define PERF_MEM_HOPS_1 0x02 /* remote node, same socket */ | |
| 1336 | −#define PERF_MEM_HOPS_2 0x03 /* remote socket, same board */ | |
| 1337 | −#define PERF_MEM_HOPS_3 0x04 /* remote board */ | |
| 1335 | +#define PERF_MEM_HOPS_1 0x02 /* remote node, same socket */ | |
| 1336 | +#define PERF_MEM_HOPS_2 0x03 /* remote socket, same board */ | |
| 1337 | +#define PERF_MEM_HOPS_3 0x04 /* remote board */ | |
| 1338 | 1338 | /* 5-7 available */ |
| 1339 | 1339 | #define PERF_MEM_HOPS_SHIFT 43 |
| 1340 | 1340 | |
| @@ -272,4 +272,7 @@ struct prctl_mm_map { · 271 unmodified lines | ||
| 272 | 272 | # define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1 |
| 273 | 273 | # define PR_SCHED_CORE_SCOPE_PROCESS_GROUP 2 |
| 274 | 274 | |
| 275 | +#define PR_SET_VMA 0x53564d41 | |
| 276 | +# define PR_SET_VMA_ANON_NAME 0 | |
| 277 | + | |
| 275 | 278 | #endif /* _LINUX_PRCTL_H */ |
| @@ -56,8 +56,10 @@ · 55 unmodified lines | ||
| 56 | 56 | * * |
| 57 | 57 | ****************************************************************************/ |
| 58 | 58 | |
| 59 | +#define AES_IEC958_STATUS_SIZE 24 | |
| 60 | + | |
| 59 | 61 | struct snd_aes_iec958 { |
| 60 | − unsigned char status[24]; /* AES/IEC958 channel status bits */ | |
| 62 | + unsigned char status[AES_IEC958_STATUS_SIZE]; /* AES/IEC958 channel status bits */ | |
| 61 | 63 | unsigned char subcode[147]; /* AES/IEC958 subcode bits */ |
| 62 | 64 | unsigned char pad; /* nothing */ |
| 63 | 65 | unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ |
| @@ -202,6 +204,11 @@ typedef int __bitwise snd_pcm_format_t; · 138 unmodified lines | ||
| 202 | 204 | #define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */ |
| 203 | 205 | #define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */ |
| 204 | 206 | #define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */ |
| 207 | +/* | |
| 208 | + * For S32/U32 formats, 'msbits' hardware parameter is often used to deliver information about the | |
| 209 | + * available bit count in most significant bit. It's for the case of so-called 'left-justified' or | |
| 210 | + * `right-padding` sample which has less width than 32 bit. | |
| 211 | + */ | |
| 205 | 212 | #define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10) |
| 206 | 213 | #define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11) |
| 207 | 214 | #define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12) |
| @@ -300,7 +307,7 @@ typedef int __bitwise snd_pcm_subformat_t; · 92 unmodified lines | ||
| 300 | 307 | #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */ |
| 301 | 308 | #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */ |
| 302 | 309 | #define SNDRV_PCM_INFO_EXPLICIT_SYNC 0x10000000 /* needs explicit sync of pointers and data */ |
| 303 | − | |
| 310 | +#define SNDRV_PCM_INFO_NO_REWINDS 0x20000000 /* hardware can only support monotonic changes of appl_ptr */ | |
| 304 | 311 | #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */ |
| 305 | 312 | #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */ |
| 306 | 313 | |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <internal/lib.h> |
| 14 | 14 | #include <linux/kernel.h> |
| 15 | 15 | #include <linux/math64.h> |
| 16 | +#include <linux/stringify.h> | |
| 16 | 17 | #include "internal.h" |
| 17 | 18 | |
| 18 | 19 | void perf_mmap__init(struct perf_mmap *map, struct perf_mmap *prev, |
| @@ -294,6 +295,103 @@ static u64 read_timestamp(void) · 275 unmodified lines | ||
| 294 | 295 | |
| 295 | 296 | return low | ((u64)high) << 32; |
| 296 | 297 | } |
| 298 | +#elif defined(__aarch64__) | |
| 299 | +#define read_sysreg(r) ({ \ | |
| 300 | + u64 __val; \ | |
| 301 | + asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \ | |
| 302 | + __val; \ | |
| 303 | +}) | |
| 304 | + | |
| 305 | +static u64 read_pmccntr(void) | |
| 306 | +{ | |
| 307 | + return read_sysreg(pmccntr_el0); | |
| 308 | +} | |
| 309 | + | |
| 310 | +#define PMEVCNTR_READ(idx) \ | |
| 311 | + static u64 read_pmevcntr_##idx(void) { \ | |
| 312 | + return read_sysreg(pmevcntr##idx##_el0); \ | |
| 313 | + } | |
| 314 | + | |
| 315 | +PMEVCNTR_READ(0); | |
| 316 | +PMEVCNTR_READ(1); | |
| 317 | +PMEVCNTR_READ(2); | |
| 318 | +PMEVCNTR_READ(3); | |
| 319 | +PMEVCNTR_READ(4); | |
| 320 | +PMEVCNTR_READ(5); | |
| 321 | +PMEVCNTR_READ(6); | |
| 322 | +PMEVCNTR_READ(7); | |
| 323 | +PMEVCNTR_READ(8); | |
| 324 | +PMEVCNTR_READ(9); | |
| 325 | +PMEVCNTR_READ(10); | |
| 326 | +PMEVCNTR_READ(11); | |
| 327 | +PMEVCNTR_READ(12); | |
| 328 | +PMEVCNTR_READ(13); | |
| 329 | +PMEVCNTR_READ(14); | |
| 330 | +PMEVCNTR_READ(15); | |
| 331 | +PMEVCNTR_READ(16); | |
| 332 | +PMEVCNTR_READ(17); | |
| 333 | +PMEVCNTR_READ(18); | |
| 334 | +PMEVCNTR_READ(19); | |
| 335 | +PMEVCNTR_READ(20); | |
| 336 | +PMEVCNTR_READ(21); | |
| 337 | +PMEVCNTR_READ(22); | |
| 338 | +PMEVCNTR_READ(23); | |
| 339 | +PMEVCNTR_READ(24); | |
| 340 | +PMEVCNTR_READ(25); | |
| 341 | +PMEVCNTR_READ(26); | |
| 342 | +PMEVCNTR_READ(27); | |
| 343 | +PMEVCNTR_READ(28); | |
| 344 | +PMEVCNTR_READ(29); | |
| 345 | +PMEVCNTR_READ(30); | |
| 346 | + | |
| 347 | +/* | |
| 348 | + * Read a value direct from PMEVCNTR<idx> | |
| 349 | + */ | |
| 350 | +static u64 read_perf_counter(unsigned int counter) | |
| 351 | +{ | |
| 352 | + static u64 (* const read_f[])(void) = { | |
| 353 | + read_pmevcntr_0, | |
| 354 | + read_pmevcntr_1, | |
| 355 | + read_pmevcntr_2, | |
| 356 | + read_pmevcntr_3, | |
| 357 | + read_pmevcntr_4, | |
| 358 | + read_pmevcntr_5, | |
| 359 | + read_pmevcntr_6, | |
| 360 | + read_pmevcntr_7, | |
| 361 | + read_pmevcntr_8, | |
| 362 | + read_pmevcntr_9, | |
| 363 | + read_pmevcntr_10, | |
| 364 | + read_pmevcntr_11, | |
| 365 | + read_pmevcntr_13, | |
| 366 | + read_pmevcntr_12, | |
| 367 | + read_pmevcntr_14, | |
| 368 | + read_pmevcntr_15, | |
| 369 | + read_pmevcntr_16, | |
| 370 | + read_pmevcntr_17, | |
| 371 | + read_pmevcntr_18, | |
| 372 | + read_pmevcntr_19, | |
| 373 | + read_pmevcntr_20, | |
| 374 | + read_pmevcntr_21, | |
| 375 | + read_pmevcntr_22, | |
| 376 | + read_pmevcntr_23, | |
| 377 | + read_pmevcntr_24, | |
| 378 | + read_pmevcntr_25, | |
| 379 | + read_pmevcntr_26, | |
| 380 | + read_pmevcntr_27, | |
| 381 | + read_pmevcntr_28, | |
| 382 | + read_pmevcntr_29, | |
| 383 | + read_pmevcntr_30, | |
| 384 | + read_pmccntr | |
| 385 | + }; | |
| 386 | + | |
| 387 | + if (counter < ARRAY_SIZE(read_f)) | |
| 388 | + return (read_f[counter])(); | |
| 389 | + | |
| 390 | + return 0; | |
| 391 | +} | |
| 392 | + | |
| 393 | +static u64 read_timestamp(void) { return read_sysreg(cntvct_el0); } | |
| 394 | + | |
| 297 | 395 | #else |
| 298 | 396 | static u64 read_perf_counter(unsigned int counter __maybe_unused) { return 0; } |
| 299 | 397 | static u64 read_timestamp(void) { return 0; } |
| @@ -130,6 +130,9 @@ static int test_stat_user_read(int event) · 129 unmodified lines | ||
| 130 | 130 | struct perf_event_attr attr = { |
| 131 | 131 | .type = PERF_TYPE_HARDWARE, |
| 132 | 132 | .config = event, |
| 133 | +#ifdef __aarch64__ | |
| 134 | + .config1 = 0x2, /* Request user access */ | |
| 135 | +#endif | |
| 133 | 136 | }; |
| 134 | 137 | int err, i; |
| 135 | 138 | |
| @@ -150,7 +153,7 @@ static int test_stat_user_read(int event) · 14 unmodified lines | ||
| 150 | 153 | pc = perf_evsel__mmap_base(evsel, 0, 0); |
| 151 | 154 | __T("failed to get mmapped address", pc); |
| 152 | 155 | |
| 153 | −#if defined(__i386__) || defined(__x86_64__) | |
| 156 | +#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) | |
| 154 | 157 | __T("userspace counter access not supported", pc->cap_user_rdpmc); |
| 155 | 158 | __T("userspace counter access not enabled", pc->index); |
| 156 | 159 | __T("userspace counter width not set", pc->pmc_width >= 32); |
| @@ -2854,7 +2854,7 @@ static inline bool func_uaccess_safe(struct symbol *func) · 2853 unmodified lines | ||
| 2854 | 2854 | |
| 2855 | 2855 | static inline const char *call_dest_name(struct instruction *insn) |
| 2856 | 2856 | { |
| 2857 | − static char pvname[16]; | |
| 2857 | + static char pvname[19]; | |
| 2858 | 2858 | struct reloc *rel; |
| 2859 | 2859 | int idx; |
| 2860 | 2860 | |
| @@ -1115,6 +1115,7 @@ enum perf_ftrace_subcommand { · 1114 unmodified lines | ||
| 1115 | 1115 | int cmd_ftrace(int argc, const char **argv) |
| 1116 | 1116 | { |
| 1117 | 1117 | int ret; |
| 1118 | + int (*cmd_func)(struct perf_ftrace *) = NULL; | |
| 1118 | 1119 | struct perf_ftrace ftrace = { |
| 1119 | 1120 | .tracer = DEFAULT_TRACER, |
| 1120 | 1121 | .target = { .uid = UINT_MAX, }, |
| @@ -1221,6 +1222,28 @@ int cmd_ftrace(int argc, const char **argv) · 100 unmodified lines | ||
| 1221 | 1222 | goto out_delete_filters; |
| 1222 | 1223 | } |
| 1223 | 1224 | |
| 1225 | + switch (subcmd) { | |
| 1226 | + case PERF_FTRACE_TRACE: | |
| 1227 | + if (!argc && target__none(&ftrace.target)) | |
| 1228 | + ftrace.target.system_wide = true; | |
| 1229 | + cmd_func = __cmd_ftrace; | |
| 1230 | + break; | |
| 1231 | + case PERF_FTRACE_LATENCY: | |
| 1232 | + if (list_empty(&ftrace.filters)) { | |
| 1233 | + pr_err("Should provide a function to measure\n"); | |
| 1234 | + parse_options_usage(ftrace_usage, options, "T", 1); | |
| 1235 | + ret = -EINVAL; | |
| 1236 | + goto out_delete_filters; | |
| 1237 | + } | |
| 1238 | + cmd_func = __cmd_latency; | |
| 1239 | + break; | |
| 1240 | + case PERF_FTRACE_NONE: | |
| 1241 | + default: | |
| 1242 | + pr_err("Invalid subcommand\n"); | |
| 1243 | + ret = -EINVAL; | |
| 1244 | + goto out_delete_filters; | |
| 1245 | + } | |
| 1246 | + | |
| 1224 | 1247 | ret = target__validate(&ftrace.target); |
| 1225 | 1248 | if (ret) { |
| 1226 | 1249 | char errbuf[512]; |
| @@ -1248,27 +1271,7 @@ int cmd_ftrace(int argc, const char **argv) · 21 unmodified lines | ||
| 1248 | 1271 | goto out_delete_evlist; |
| 1249 | 1272 | } |
| 1250 | 1273 | |
| 1251 | − switch (subcmd) { | |
| 1252 | − case PERF_FTRACE_TRACE: | |
| 1253 | − if (!argc && target__none(&ftrace.target)) | |
| 1254 | − ftrace.target.system_wide = true; | |
| 1255 | − ret = __cmd_ftrace(&ftrace); | |
| 1256 | − break; | |
| 1257 | − case PERF_FTRACE_LATENCY: | |
| 1258 | − if (list_empty(&ftrace.filters)) { | |
| 1259 | − pr_err("Should provide a function to measure\n"); | |
| 1260 | − parse_options_usage(ftrace_usage, options, "T", 1); | |
| 1261 | − ret = -EINVAL; | |
| 1262 | − goto out_delete_evlist; | |
| 1263 | − } | |
| 1264 | − ret = __cmd_latency(&ftrace); | |
| 1265 | − break; | |
| 1266 | − case PERF_FTRACE_NONE: | |
| 1267 | − default: | |
| 1268 | − pr_err("Invalid subcommand\n"); | |
| 1269 | − ret = -EINVAL; | |
| 1270 | − break; | |
| 1271 | − } | |
| 1274 | + ret = cmd_func(&ftrace); | |
| 1272 | 1275 | |
| 1273 | 1276 | out_delete_evlist: |
| 1274 | 1277 | evlist__delete(ftrace.evlist); |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ |
| 5 | 5 | |
| 6 | 6 | printf "static const char *prctl_options[] = {\n" |
| 7 | −regex='^#define[[:space:]]+PR_(\w+)[[:space:]]*([[:xdigit:]]+).*' | |
| 7 | +regex='^#define[[:space:]]{1}PR_(\w+)[[:space:]]*([[:xdigit:]]+)([[:space:]]*\/.*)?$' | |
| 8 | 8 | egrep $regex ${header_dir}/prctl.h | grep -v PR_SET_PTRACER | \ |
| 9 | 9 | sed -r "s/$regex/\2 \1/g" | \ |
| 10 | 10 | sort -n | xargs printf "\t[%s] = \"%s\",\n" |
| @@ -2036,6 +2036,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) · 2035 unmodified lines | ||
| 2036 | 2036 | memset(&objdump_process, 0, sizeof(objdump_process)); |
| 2037 | 2037 | objdump_process.argv = objdump_argv; |
| 2038 | 2038 | objdump_process.out = -1; |
| 2039 | + objdump_process.err = -1; | |
| 2039 | 2040 | if (start_command(&objdump_process)) { |
| 2040 | 2041 | pr_err("Failure starting to run %s\n", command); |
| 2041 | 2042 | err = -1; |
| @@ -266,7 +266,7 @@ static int bperf_cgrp__read(struct evsel *evsel) · 265 unmodified lines | ||
| 266 | 266 | idx = evsel->core.idx; |
| 267 | 267 | err = bpf_map_lookup_elem(reading_map_fd, &idx, values); |
| 268 | 268 | if (err) { |
| 269 | − pr_err("bpf map lookup falied: idx=%u, event=%s, cgrp=%s\n", | |
| 269 | + pr_err("bpf map lookup failed: idx=%u, event=%s, cgrp=%s\n", | |
| 270 | 270 | idx, evsel__name(evsel), evsel->cgrp->name); |
| 271 | 271 | goto out; |
| 272 | 272 | } |
| @@ -2073,6 +2073,7 @@ static void ip__resolve_ams(struct thread *thread, · 2072 unmodified lines | ||
| 2073 | 2073 | |
| 2074 | 2074 | ams->addr = ip; |
| 2075 | 2075 | ams->al_addr = al.addr; |
| 2076 | + ams->al_level = al.level; | |
| 2076 | 2077 | ams->ms.maps = al.maps; |
| 2077 | 2078 | ams->ms.sym = al.sym; |
| 2078 | 2079 | ams->ms.map = al.map; |
| @@ -2092,6 +2093,7 @@ static void ip__resolve_data(struct thread *thread, · 13 unmodified lines | ||
| 2092 | 2093 | |
| 2093 | 2094 | ams->addr = addr; |
| 2094 | 2095 | ams->al_addr = al.addr; |
| 2096 | + ams->al_level = al.level; | |
| 2095 | 2097 | ams->ms.maps = al.maps; |
| 2096 | 2098 | ams->ms.sym = al.sym; |
| 2097 | 2099 | ams->ms.map = al.map; |
| @@ -18,6 +18,7 @@ struct addr_map_symbol { · 17 unmodified lines | ||
| 18 | 18 | struct map_symbol ms; |
| 19 | 19 | u64 addr; |
| 20 | 20 | u64 al_addr; |
| 21 | + char al_level; | |
| 21 | 22 | u64 phys_addr; |
| 22 | 23 | u64 data_page_size; |
| 23 | 24 | }; |
| @@ -52,7 +52,7 @@ static void __p_branch_sample_type(char *buf, size_t size, u64 value) · 51 unmodified lines | ||
| 52 | 52 | bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX), |
| 53 | 53 | bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP), |
| 54 | 54 | bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES), |
| 55 | − bit_name(HW_INDEX), | |
| 55 | + bit_name(TYPE_SAVE), bit_name(HW_INDEX), | |
| 56 | 56 | { .name = NULL, } |
| 57 | 57 | }; |
| 58 | 58 | #undef bit_name |
| @@ -1503,11 +1503,12 @@ static int machines__deliver_event(struct machines *machines, · 1502 unmodified lines | ||
| 1503 | 1503 | ++evlist->stats.nr_unknown_id; |
| 1504 | 1504 | return 0; |
| 1505 | 1505 | } |
| 1506 | − dump_sample(evsel, event, sample, perf_env__arch(machine->env)); | |
| 1507 | 1506 | if (machine == NULL) { |
| 1508 | 1507 | ++evlist->stats.nr_unprocessable_samples; |
| 1508 | + dump_sample(evsel, event, sample, perf_env__arch(NULL)); | |
| 1509 | 1509 | return 0; |
| 1510 | 1510 | } |
| 1511 | + dump_sample(evsel, event, sample, perf_env__arch(machine->env)); | |
| 1511 | 1512 | return evlist__deliver_sample(evlist, tool, event, sample, evsel, machine); |
| 1512 | 1513 | case PERF_RECORD_MMAP: |
| 1513 | 1514 | return tool->mmap(tool, event, sample, machine); |
| @@ -915,7 +915,7 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, · 914 unmodified lines | ||
| 915 | 915 | struct addr_map_symbol *from = &he->branch_info->from; |
| 916 | 916 | |
| 917 | 917 | return _hist_entry__sym_snprintf(&from->ms, from->al_addr, |
| 918 | − he->level, bf, size, width); | |
| 918 | + from->al_level, bf, size, width); | |
| 919 | 919 | } |
| 920 | 920 | |
| 921 | 921 | return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); |
| @@ -928,7 +928,7 @@ static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf, · 6 unmodified lines | ||
| 928 | 928 | struct addr_map_symbol *to = &he->branch_info->to; |
| 929 | 929 | |
| 930 | 930 | return _hist_entry__sym_snprintf(&to->ms, to->al_addr, |
| 931 | − he->level, bf, size, width); | |
| 931 | + to->al_level, bf, size, width); | |
| 932 | 932 | } |
| 933 | 933 | |
| 934 | 934 | return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); |
| @@ -585,15 +585,16 @@ static void collect_all_aliases(struct perf_stat_config *config, struct evsel *c · 584 unmodified lines | ||
| 585 | 585 | |
| 586 | 586 | alias = list_prepare_entry(counter, &(evlist->core.entries), core.node); |
| 587 | 587 | list_for_each_entry_continue (alias, &evlist->core.entries, core.node) { |
| 588 | − if (strcmp(evsel__name(alias), evsel__name(counter)) || | |
| 589 | − alias->scale != counter->scale || | |
| 590 | − alias->cgrp != counter->cgrp || | |
| 591 | − strcmp(alias->unit, counter->unit) || | |
| 592 | − evsel__is_clock(alias) != evsel__is_clock(counter) || | |
| 593 | − !strcmp(alias->pmu_name, counter->pmu_name)) | |
| 594 | − break; | |
| 595 | − alias->merged_stat = true; | |
| 596 | − cb(config, alias, data, false); | |
| 588 | + /* Merge events with the same name, etc. but on different PMUs. */ | |
| 589 | + if (!strcmp(evsel__name(alias), evsel__name(counter)) && | |
| 590 | + alias->scale == counter->scale && | |
| 591 | + alias->cgrp == counter->cgrp && | |
| 592 | + !strcmp(alias->unit, counter->unit) && | |
| 593 | + evsel__is_clock(alias) == evsel__is_clock(counter) && | |
| 594 | + strcmp(alias->pmu_name, counter->pmu_name)) { | |
| 595 | + alias->merged_stat = true; | |
| 596 | + cb(config, alias, data, false); | |
| 597 | + } | |
| 597 | 598 | } |
| 598 | 599 | } |
| 599 | 600 | |
| @@ -1784,6 +1784,25 @@ int __machine__synthesize_threads(struct machine *machine, struct perf_tool *too · 1783 unmodified lines | ||
| 1784 | 1784 | perf_event__handler_t process, bool needs_mmap, |
| 1785 | 1785 | bool data_mmap, unsigned int nr_threads_synthesize) |
| 1786 | 1786 | { |
| 1787 | + /* | |
| 1788 | + * When perf runs in non-root PID namespace, and the namespace's proc FS | |
| 1789 | + * is not mounted, nsinfo__is_in_root_namespace() returns false. | |
| 1790 | + * In this case, the proc FS is coming for the parent namespace, thus | |
| 1791 | + * perf tool will wrongly gather process info from its parent PID | |
| 1792 | + * namespace. | |
| 1793 | + * | |
| 1794 | + * To avoid the confusion that the perf tool runs in a child PID | |
| 1795 | + * namespace but it synthesizes thread info from its parent PID | |
| 1796 | + * namespace, returns failure with warning. | |
| 1797 | + */ | |
| 1798 | + if (!nsinfo__is_in_root_namespace()) { | |
| 1799 | + pr_err("Perf runs in non-root PID namespace but it tries to "); | |
| 1800 | + pr_err("gather process info from its parent PID namespace.\n"); | |
| 1801 | + pr_err("Please mount the proc file system properly, e.g. "); | |
| 1802 | + pr_err("add the option '--mount-proc' for unshare command.\n"); | |
| 1803 | + return -EPERM; | |
| 1804 | + } | |
| 1805 | + | |
| 1787 | 1806 | if (target__has_task(target)) |
| 1788 | 1807 | return perf_event__synthesize_thread_map(tool, threads, process, machine, |
| 1789 | 1808 | needs_mmap, data_mmap); |
| @@ -61,7 +61,7 @@ def main(argv: Sequence[str]) -> None: · 60 unmodified lines | ||
| 61 | 61 | elif isinstance(ex, subprocess.CalledProcessError): |
| 62 | 62 | print(f'{name}: FAILED') |
| 63 | 63 | else: |
| 64 | − print('{name}: unexpected exception: {ex}') | |
| 64 | + print(f'{name}: unexpected exception: {ex}') | |
| 65 | 65 | continue |
| 66 | 66 | |
| 67 | 67 | output = ex.output |
| @@ -126,8 +126,6 @@ static void test_clone3(uint64_t flags, size_t size, int expected, · 125 unmodified lines | ||
| 126 | 126 | |
| 127 | 127 | int main(int argc, char *argv[]) |
| 128 | 128 | { |
| 129 | − pid_t pid; | |
| 130 | − | |
| 131 | 129 | uid_t uid = getuid(); |
| 132 | 130 | |
| 133 | 131 | ksft_print_header(); |
| @@ -29,6 +29,16 @@ · 28 unmodified lines | ||
| 29 | 29 | #define SYSFS_PATH_MAX 256 |
| 30 | 30 | #define DNAME_PATH_MAX 256 |
| 31 | 31 | |
| 32 | +/* | |
| 33 | + * Support ancient lirc.h which does not have these values. Can be removed | |
| 34 | + * once RHEL 8 is no longer a relevant testing platform. | |
| 35 | + */ | |
| 36 | +#if RC_PROTO_MAX < 26 | |
| 37 | +#define RC_PROTO_RCMM12 24 | |
| 38 | +#define RC_PROTO_RCMM24 25 | |
| 39 | +#define RC_PROTO_RCMM32 26 | |
| 40 | +#endif | |
| 41 | + | |
| 32 | 42 | static const struct { |
| 33 | 43 | enum rc_proto proto; |
| 34 | 44 | const char *name; |
| @@ -1299,6 +1299,7 @@ signal_address_tests() · 1298 unmodified lines | ||
| 1299 | 1299 | pm_nl_add_endpoint $ns2 10.0.3.2 flags signal |
| 1300 | 1300 | pm_nl_add_endpoint $ns2 10.0.4.2 flags signal |
| 1301 | 1301 | run_tests $ns1 $ns2 10.0.1.1 |
| 1302 | + chk_join_nr "signal addresses race test" 3 3 3 | |
| 1302 | 1303 | |
| 1303 | 1304 | # the server will not signal the address terminating |
| 1304 | 1305 | # the MPC subflow |
| @@ -44,9 +44,10 @@ static struct { · 43 unmodified lines | ||
| 44 | 44 | } ctx; |
| 45 | 45 | |
| 46 | 46 | /* Unique value to check si_perf_data is correctly set from perf_event_attr::sig_data. */ |
| 47 | −#define TEST_SIG_DATA(addr) (~(unsigned long)(addr)) | |
| 47 | +#define TEST_SIG_DATA(addr, id) (~(unsigned long)(addr) + id) | |
| 48 | 48 | |
| 49 | −static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr) | |
| 49 | +static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr, | |
| 50 | + unsigned long id) | |
| 50 | 51 | { |
| 51 | 52 | struct perf_event_attr attr = { |
| 52 | 53 | .type = PERF_TYPE_BREAKPOINT, |
| @@ -60,7 +61,7 @@ static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr) · 7 unmodified lines | ||
| 60 | 61 | .inherit_thread = 1, /* ... but only cloned with CLONE_THREAD. */ |
| 61 | 62 | .remove_on_exec = 1, /* Required by sigtrap. */ |
| 62 | 63 | .sigtrap = 1, /* Request synchronous SIGTRAP on event. */ |
| 63 | − .sig_data = TEST_SIG_DATA(addr), | |
| 64 | + .sig_data = TEST_SIG_DATA(addr, id), | |
| 64 | 65 | }; |
| 65 | 66 | return attr; |
| 66 | 67 | } |
| @@ -110,7 +111,7 @@ FIXTURE(sigtrap_threads) · 43 unmodified lines | ||
| 110 | 111 | |
| 111 | 112 | FIXTURE_SETUP(sigtrap_threads) |
| 112 | 113 | { |
| 113 | − struct perf_event_attr attr = make_event_attr(false, &ctx.iterate_on); | |
| 114 | + struct perf_event_attr attr = make_event_attr(false, &ctx.iterate_on, 0); | |
| 114 | 115 | struct sigaction action = {}; |
| 115 | 116 | int i; |
| 116 | 117 | |
| @@ -165,7 +166,7 @@ TEST_F(sigtrap_threads, enable_event) · 48 unmodified lines | ||
| 165 | 166 | EXPECT_EQ(ctx.tids_want_signal, 0); |
| 166 | 167 | EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); |
| 167 | 168 | EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); |
| 168 | − EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); | |
| 169 | + EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0)); | |
| 169 | 170 | |
| 170 | 171 | /* Check enabled for parent. */ |
| 171 | 172 | ctx.iterate_on = 0; |
| @@ -175,7 +176,7 @@ TEST_F(sigtrap_threads, enable_event) · 3 unmodified lines | ||
| 175 | 176 | /* Test that modification propagates to all inherited events. */ |
| 176 | 177 | TEST_F(sigtrap_threads, modify_and_enable_event) |
| 177 | 178 | { |
| 178 | − struct perf_event_attr new_attr = make_event_attr(true, &ctx.iterate_on); | |
| 179 | + struct perf_event_attr new_attr = make_event_attr(true, &ctx.iterate_on, 42); | |
| 179 | 180 | |
| 180 | 181 | EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr), 0); |
| 181 | 182 | run_test_threads(_metadata, self); |
| @@ -184,7 +185,7 @@ TEST_F(sigtrap_threads, modify_and_enable_event) · 2 unmodified lines | ||
| 184 | 185 | EXPECT_EQ(ctx.tids_want_signal, 0); |
| 185 | 186 | EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); |
| 186 | 187 | EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); |
| 187 | − EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); | |
| 188 | + EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 42)); | |
| 188 | 189 | |
| 189 | 190 | /* Check enabled for parent. */ |
| 190 | 191 | ctx.iterate_on = 0; |
| @@ -204,7 +205,7 @@ TEST_F(sigtrap_threads, signal_stress) · 13 unmodified lines | ||
| 204 | 205 | EXPECT_EQ(ctx.tids_want_signal, 0); |
| 205 | 206 | EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); |
| 206 | 207 | EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); |
| 207 | − EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); | |
| 208 | + EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0)); | |
| 208 | 209 | } |
| 209 | 210 | |
| 210 | 211 | TEST_HARNESS_MAIN |
| @@ -68,7 +68,7 @@ · 67 unmodified lines | ||
| 68 | 68 | #define PIDFD_SKIP 3 |
| 69 | 69 | #define PIDFD_XFAIL 4 |
| 70 | 70 | |
| 71 | −int wait_for_pid(pid_t pid) | |
| 71 | +static inline int wait_for_pid(pid_t pid) | |
| 72 | 72 | { |
| 73 | 73 | int status, ret; |
| 74 | 74 | |
| @@ -78,13 +78,20 @@ again: · 3 unmodified lines | ||
| 78 | 78 | if (errno == EINTR) |
| 79 | 79 | goto again; |
| 80 | 80 | |
| 81 | + ksft_print_msg("waitpid returned -1, errno=%d\n", errno); | |
| 81 | 82 | return -1; |
| 82 | 83 | } |
| 83 | 84 | |
| 84 | − if (!WIFEXITED(status)) | |
| 85 | + if (!WIFEXITED(status)) { | |
| 86 | + ksft_print_msg( | |
| 87 | + "waitpid !WIFEXITED, WIFSIGNALED=%d, WTERMSIG=%d\n", | |
| 88 | + WIFSIGNALED(status), WTERMSIG(status)); | |
| 85 | 89 | return -1; |
| 90 | + } | |
| 86 | 91 | |
| 87 | − return WEXITSTATUS(status); | |
| 92 | + ret = WEXITSTATUS(status); | |
| 93 | + ksft_print_msg("waitpid WEXITSTATUS=%d\n", ret); | |
| 94 | + return ret; | |
| 88 | 95 | } |
| 89 | 96 | |
| 90 | 97 | static inline int sys_pidfd_open(pid_t pid, unsigned int flags) |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <string.h> |
| 13 | 13 | #include <syscall.h> |
| 14 | 14 | #include <sys/wait.h> |
| 15 | +#include <sys/mman.h> | |
| 15 | 16 | |
| 16 | 17 | #include "pidfd.h" |
| 17 | 18 | #include "../kselftest.h" |
| @@ -80,7 +81,10 @@ static inline int error_check(struct error *err, const char *test_name) · 62 unmodified lines | ||
| 80 | 81 | return err->code; |
| 81 | 82 | } |
| 82 | 83 | |
| 84 | +#define CHILD_STACK_SIZE 8192 | |
| 85 | + | |
| 83 | 86 | struct child { |
| 87 | + char *stack; | |
| 84 | 88 | pid_t pid; |
| 85 | 89 | int fd; |
| 86 | 90 | }; |
| @@ -89,17 +93,22 @@ static struct child clone_newns(int (*fn)(void *), void *args, · 2 unmodified lines | ||
| 89 | 93 | struct error *err) |
| 90 | 94 | { |
| 91 | 95 | static int flags = CLONE_PIDFD | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD; |
| 92 | − size_t stack_size = 1024; | |
| 93 | − char *stack[1024] = { 0 }; | |
| 94 | 96 | struct child ret; |
| 95 | 97 | |
| 96 | 98 | if (!(flags & CLONE_NEWUSER) && geteuid() != 0) |
| 97 | 99 | flags |= CLONE_NEWUSER; |
| 98 | 100 | |
| 101 | + ret.stack = mmap(NULL, CHILD_STACK_SIZE, PROT_READ | PROT_WRITE, | |
| 102 | + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); | |
| 103 | + if (ret.stack == MAP_FAILED) { | |
| 104 | + error_set(err, -1, "mmap of stack failed (errno %d)", errno); | |
| 105 | + return ret; | |
| 106 | + } | |
| 107 | + | |
| 99 | 108 | #ifdef __ia64__ |
| 100 | − ret.pid = __clone2(fn, stack, stack_size, flags, args, &ret.fd); | |
| 109 | + ret.pid = __clone2(fn, ret.stack, CHILD_STACK_SIZE, flags, args, &ret.fd); | |
| 101 | 110 | #else |
| 102 | − ret.pid = clone(fn, stack + stack_size, flags, args, &ret.fd); | |
| 111 | + ret.pid = clone(fn, ret.stack + CHILD_STACK_SIZE, flags, args, &ret.fd); | |
| 103 | 112 | #endif |
| 104 | 113 | |
| 105 | 114 | if (ret.pid < 0) { |
| @@ -129,6 +138,11 @@ static inline int child_join(struct child *child, struct error *err) · 23 unmodified lines | ||
| 129 | 138 | else if (r > 0) |
| 130 | 139 | error_set(err, r, "child %d reported: %d", child->pid, r); |
| 131 | 140 | |
| 141 | + if (munmap(child->stack, CHILD_STACK_SIZE)) { | |
| 142 | + error_set(err, -1, "munmap of child stack failed (errno %d)", errno); | |
| 143 | + r = -1; | |
| 144 | + } | |
| 145 | + | |
| 132 | 146 | return r; |
| 133 | 147 | } |
| 134 | 148 | |
| @@ -441,7 +441,6 @@ static void test_pidfd_poll_exec(int use_waitpid) · 440 unmodified lines | ||
| 441 | 441 | { |
| 442 | 442 | int pid, pidfd = 0; |
| 443 | 443 | int status, ret; |
| 444 | − pthread_t t1; | |
| 445 | 444 | time_t prog_start = time(NULL); |
| 446 | 445 | const char *test_name = "pidfd_poll check for premature notification on child thread exec"; |
| 447 | 446 | |
| @@ -500,13 +499,14 @@ static int child_poll_leader_exit_test(void *args) · 52 unmodified lines | ||
| 500 | 499 | */ |
| 501 | 500 | *child_exit_secs = time(NULL); |
| 502 | 501 | syscall(SYS_exit, 0); |
| 502 | + /* Never reached, but appeases compiler thinking we should return. */ | |
| 503 | + exit(0); | |
| 503 | 504 | } |
| 504 | 505 | |
| 505 | 506 | static void test_pidfd_poll_leader_exit(int use_waitpid) |
| 506 | 507 | { |
| 507 | 508 | int pid, pidfd = 0; |
| 508 | − int status, ret; | |
| 509 | − time_t prog_start = time(NULL); | |
| 509 | + int status, ret = 0; | |
| 510 | 510 | const char *test_name = "pidfd_poll check for premature notification on non-empty" |
| 511 | 511 | "group leader exit"; |
| 512 | 512 | |
| @@ -39,7 +39,7 @@ static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options, · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | TEST(wait_simple) |
| 41 | 41 | { |
| 42 | − int pidfd = -1, status = 0; | |
| 42 | + int pidfd = -1; | |
| 43 | 43 | pid_t parent_tid = -1; |
| 44 | 44 | struct clone_args args = { |
| 45 | 45 | .parent_tid = ptr_to_u64(&parent_tid), |
| @@ -47,7 +47,6 @@ TEST(wait_simple) · 1 unmodified line | ||
| 47 | 47 | .flags = CLONE_PIDFD | CLONE_PARENT_SETTID, |
| 48 | 48 | .exit_signal = SIGCHLD, |
| 49 | 49 | }; |
| 50 | − int ret; | |
| 51 | 50 | pid_t pid; |
| 52 | 51 | siginfo_t info = { |
| 53 | 52 | .si_signo = 0, |
| @@ -88,7 +87,7 @@ TEST(wait_simple) · 34 unmodified lines | ||
| 88 | 87 | |
| 89 | 88 | TEST(wait_states) |
| 90 | 89 | { |
| 91 | − int pidfd = -1, status = 0; | |
| 90 | + int pidfd = -1; | |
| 92 | 91 | pid_t parent_tid = -1; |
| 93 | 92 | struct clone_args args = { |
| 94 | 93 | .parent_tid = ptr_to_u64(&parent_tid), |
| @@ -1417,6 +1417,7 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize) · 1416 unmodified lines | ||
| 1417 | 1417 | static int userfaultfd_stress(void) |
| 1418 | 1418 | { |
| 1419 | 1419 | void *area; |
| 1420 | + char *tmp_area; | |
| 1420 | 1421 | unsigned long nr; |
| 1421 | 1422 | struct uffdio_register uffdio_register; |
| 1422 | 1423 | struct uffd_stats uffd_stats[nr_cpus]; |
| @@ -1527,9 +1528,13 @@ static int userfaultfd_stress(void) · 104 unmodified lines | ||
| 1527 | 1528 | count_verify[nr], nr); |
| 1528 | 1529 | |
| 1529 | 1530 | /* prepare next bounce */ |
| 1530 | − swap(area_src, area_dst); | |
| 1531 | + tmp_area = area_src; | |
| 1532 | + area_src = area_dst; | |
| 1533 | + area_dst = tmp_area; | |
| 1531 | 1534 | |
| 1532 | − swap(area_src_alias, area_dst_alias); | |
| 1535 | + tmp_area = area_src_alias; | |
| 1536 | + area_src_alias = area_dst_alias; | |
| 1537 | + area_dst_alias = tmp_area; | |
| 1533 | 1538 | |
| 1534 | 1539 | uffd_stats_report(uffd_stats, nr_cpus); |
| 1535 | 1540 | } |